]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Merge pull request #12636 from Habbie/lmdb-comments
authorPeter van Dijk <peter.van.dijk@powerdns.com>
Wed, 3 May 2023 08:39:13 +0000 (10:39 +0200)
committerGitHub <noreply@github.com>
Wed, 3 May 2023 08:39:13 +0000 (10:39 +0200)
auth lmdb: handle lack of support for RRset comments better

283 files changed:
.github/actions/spell-check/allow.txt
.github/actions/spell-check/expect.txt
.github/workflows/build-and-test-all.yml
.github/workflows/builder-dispatch.yml
.github/workflows/builder.yml
.github/workflows/codeql-analysis.yml
.github/workflows/docker.yml
.github/workflows/documentation.yml
.github/workflows/formatting.yml
.github/workflows/misc-dailies.yml
.github/workflows/secpoll.yml
.gitignore
SECURITY.md
build-scripts/docker/repo-test/generate-repo-files.py
build-scripts/test-recursor-bulk
builder-support/debian/recursor/debian-buster/README.source [deleted file]
builder-support/debian/recursor/debian-buster/configure-helpers/net-snmp-config [new file with mode: 0755]
builder-support/debian/recursor/debian-buster/control
builder-support/debian/recursor/debian-buster/copyright
builder-support/debian/recursor/debian-buster/pdns-recursor.default [deleted file]
builder-support/debian/recursor/debian-buster/pdns-recursor.init [deleted file]
builder-support/debian/recursor/debian-buster/pdns-recursor.lintian-overrides
builder-support/debian/recursor/debian-buster/pdns-recursor.postinst
builder-support/debian/recursor/debian-buster/pdns-recursor.preinst [new file with mode: 0644]
builder-support/debian/recursor/debian-buster/pdns-recursor.prerm [deleted file]
builder-support/debian/recursor/debian-buster/rules
builder-support/debian/recursor/debian-buster/source.lintian-overrides [deleted file]
builder-support/debian/recursor/debian-buster/tests/control
builder-support/debian/recursor/debian-buster/tests/smoke
builder-support/dockerfiles/Dockerfile.target.amazon-2023 [new file with mode: 0644]
builder-support/dockerfiles/Dockerfile.target.ubuntu-lunar [new file with mode: 0644]
builder-support/dockerfiles/Dockerfile.target.ubuntu-lunar-amd64 [new symlink]
builder-support/dockerfiles/Dockerfile.target.ubuntu-lunar-arm64 [new symlink]
builder-support/specs/dnsdist.spec
builder-support/specs/pdns-recursor.spec
builder-support/specs/pdns.spec
docs/backends/bind.rst
docs/backends/lmdb.rst
docs/changelog/4.7.rst
docs/changelog/4.8.rst [new file with mode: 0644]
docs/changelog/index.rst
docs/common/security-policy.rst
docs/lua-records/index.rst
docs/secpoll.zone
docs/upgrading.rst
ext/lmdb-safe/lmdb-safe.cc
ext/lmdb-safe/lmdb-safe.hh
ext/lmdb-safe/lmdb-typed.cc
ext/lmdb-safe/lmdb-typed.hh
modules/gmysqlbackend/smysql.cc
modules/gpgsqlbackend/spgsql.cc
modules/lmdbbackend/lmdbbackend.cc
modules/lmdbbackend/lmdbbackend.hh
modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb-0 [deleted file]
modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb-1 [deleted file]
modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb-0 [deleted file]
modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb-1 [deleted file]
modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb [moved from modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb with 95% similarity]
modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb-0 [new file with mode: 0644]
modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb-0-lock [moved from modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb-0-lock with 97% similarity]
modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb-1 [new file with mode: 0644]
modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb-1-lock [moved from modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb-1-lock with 97% similarity]
modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb-lock [moved from modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb-lock with 97% similarity]
modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb [moved from modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb with 95% similarity]
modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb-0 [new file with mode: 0644]
modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb-0-lock [moved from modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb-0-lock with 97% similarity]
modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb-1 [new file with mode: 0644]
modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb-1-lock [moved from modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb-1-lock with 97% similarity]
modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb-lock [moved from modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb-lock with 97% similarity]
modules/tinydnsbackend/data
modules/tinydnsbackend/data.cdb
pdns/Makefile.am
pdns/auth-catalogzone.cc
pdns/auth-main.cc
pdns/capabilities.cc
pdns/communicator.cc
pdns/communicator.hh
pdns/dbdnsseckeeper.cc
pdns/dns.cc
pdns/dns.hh
pdns/dnsbulktest.cc
pdns/dnsdist-cache.cc
pdns/dnsdist-carbon.cc
pdns/dnsdist-console.cc
pdns/dnsdist-lua-actions.cc
pdns/dnsdist-lua-bindings.cc
pdns/dnsdist-lua-inspection.cc
pdns/dnsdist-lua-rules.cc
pdns/dnsdist-lua.cc
pdns/dnsdist-lua.hh
pdns/dnsdist-snmp.cc
pdns/dnsdist-tcp.cc
pdns/dnsdist.cc
pdns/dnsdist.hh
pdns/dnsdistdist/dnsdist-dynblocks.cc
pdns/dnsdistdist/dnsdist-lbpolicies.cc
pdns/dnsdistdist/dnsdist-lua-ffi.cc
pdns/dnsdistdist/dnsdist-lua-inspection-ffi.cc
pdns/dnsdistdist/dnsdist-lua-inspection-ffi.hh
pdns/dnsdistdist/dnsdist-secpoll.hh
pdns/dnsdistdist/docs/changelog.rst
pdns/dnsdistdist/docs/eol.rst
pdns/dnsdistdist/docs/reference/config.rst
pdns/dnsdistdist/docs/reference/ebpf.rst
pdns/dnsdistdist/docs/upgrade_guide.rst
pdns/dnsdistdist/doh.cc
pdns/dnsdistdist/html/index.html
pdns/dnsdistdist/html/local.js
pdns/dnsdistdist/test-dnsdist-dnsparser.cc
pdns/dnsname.cc
pdns/dnspacket.cc
pdns/dnsparser.cc
pdns/dnsparser.hh
pdns/dnsproxy.cc
pdns/dnsrecords.cc
pdns/dnsrecords.hh
pdns/dnsreplay.cc
pdns/dnsscope.cc
pdns/dnssecinfra.cc
pdns/dnssecinfra.hh
pdns/dnssecsigner.cc
pdns/dnstcpbench.cc
pdns/gss_context.cc
pdns/gss_context.hh
pdns/iputils.cc
pdns/ixfr.cc
pdns/ixfr.hh
pdns/ixfrdist.cc
pdns/ixfrutils.cc
pdns/ixfrutils.hh
pdns/ixplore.cc
pdns/libssl.cc
pdns/lua-base4.cc
pdns/lua-record.cc
pdns/mastercommunicator.cc
pdns/minicurl.cc
pdns/misc.cc
pdns/nsec3dig.cc
pdns/nsecrecords.cc
pdns/opensslsigners.cc
pdns/packethandler.cc
pdns/pdnsutil.cc
pdns/pkcs11signers.cc
pdns/recursordist/RECURSOR-MIB.txt
pdns/recursordist/aggressive_nsec.cc
pdns/recursordist/aggressive_nsec.hh
pdns/recursordist/configure.ac
pdns/recursordist/docs/changelog/4.6.rst
pdns/recursordist/docs/changelog/4.7.rst
pdns/recursordist/docs/changelog/4.8.rst
pdns/recursordist/docs/changelog/4.9.rst [new file with mode: 0644]
pdns/recursordist/docs/changelog/index.rst
pdns/recursordist/docs/lua-config/additionals.rst
pdns/recursordist/docs/performance.rst
pdns/recursordist/docs/security-advisories/powerdns-advisory-2023-02.rst [new file with mode: 0644]
pdns/recursordist/docs/settings.rst
pdns/recursordist/docs/upgrade.rst
pdns/recursordist/ednsextendederror.hh
pdns/recursordist/filterpo.cc
pdns/recursordist/filterpo.hh
pdns/recursordist/lazy_allocator.hh
pdns/recursordist/logr.hh
pdns/recursordist/lua-recursor4.cc
pdns/recursordist/lwres.cc
pdns/recursordist/mtasker_context.hh
pdns/recursordist/negcache.cc
pdns/recursordist/negcache.hh
pdns/recursordist/nod.cc
pdns/recursordist/pdns_recursor.cc
pdns/recursordist/rec-lua-conf.cc
pdns/recursordist/rec-lua-conf.hh
pdns/recursordist/rec-main.cc
pdns/recursordist/rec-main.hh
pdns/recursordist/rec-protozero.cc
pdns/recursordist/rec-snmp.cc
pdns/recursordist/rec-tcp.cc
pdns/recursordist/rec-zonetocache.cc
pdns/recursordist/rec_channel_rec.cc
pdns/recursordist/recpacketcache.cc
pdns/recursordist/recpacketcache.hh
pdns/recursordist/recursor_cache.cc
pdns/recursordist/recursor_cache.hh
pdns/recursordist/reczones-helpers.cc
pdns/recursordist/reczones-helpers.hh
pdns/recursordist/reczones.cc
pdns/recursordist/root-addresses.hh
pdns/recursordist/rpzloader.cc
pdns/recursordist/rpzloader.hh
pdns/recursordist/syncres.cc
pdns/recursordist/syncres.hh
pdns/recursordist/test-aggressive_nsec_cc.cc
pdns/recursordist/test-filterpo_cc.cc
pdns/recursordist/test-mtasker.cc
pdns/recursordist/test-negcache_cc.cc
pdns/recursordist/test-nod_cc.cc
pdns/recursordist/test-recursorcache_cc.cc
pdns/recursordist/test-reczones-helpers.cc
pdns/recursordist/test-syncres_cc.cc
pdns/recursordist/test-syncres_cc1.cc
pdns/recursordist/test-syncres_cc10.cc
pdns/recursordist/test-syncres_cc2.cc
pdns/recursordist/test-syncres_cc3.cc
pdns/recursordist/test-syncres_cc4.cc
pdns/recursordist/test-syncres_cc5.cc
pdns/recursordist/test-syncres_cc6.cc
pdns/recursordist/test-syncres_cc7.cc
pdns/recursordist/test-syncres_cc8.cc
pdns/recursordist/test-syncres_cc9.cc
pdns/recursordist/ws-recursor.cc
pdns/resolver.cc
pdns/rfc2136handler.cc
pdns/saxfr.cc
pdns/sdig.cc
pdns/serialtweaker.cc
pdns/signingpipe.cc
pdns/sillyrecords.cc
pdns/slavecommunicator.cc
pdns/snmp-agent.cc
pdns/speedtest.cc
pdns/ssqlite3.cc
pdns/statnode.cc
pdns/statnode.hh
pdns/stubquery.cc
pdns/tcpiohandler.cc
pdns/tcpreceiver.cc
pdns/test-common.hh
pdns/test-dnsname_cc.cc
pdns/test-dnsparser_cc.cc
pdns/test-dnsrecords_cc.cc
pdns/test-mplexer.cc
pdns/test-tsig.cc
pdns/tkey.cc
pdns/tools/rrd/makegraphs
pdns/tsigverifier.cc
pdns/ueberbackend.cc
pdns/unix_utility.cc
pdns/validate.cc
pdns/validate.hh
pdns/zonemd.cc
pdns/zonemd.hh
regression-tests.api/runtests.py
regression-tests.auth-py/test_LuaRecords.py
regression-tests.dnsdist/dnsdisttests.py
regression-tests.dnsdist/requirements.txt
regression-tests.dnsdist/test_API.py
regression-tests.dnsdist/test_Advanced.py
regression-tests.dnsdist/test_BackendDiscovery.py
regression-tests.dnsdist/test_DNSCrypt.py
regression-tests.dnsdist/test_DOH.py
regression-tests.dnsdist/test_Metrics.py
regression-tests.dnsdist/test_TLS.py
regression-tests.nobackend/lmdb-metadata-leak/command [new file with mode: 0755]
regression-tests.nobackend/lmdb-metadata-leak/description [new file with mode: 0644]
regression-tests.nobackend/lmdb-metadata-leak/expected_result [new file with mode: 0644]
regression-tests.nobackend/tinydns-data-check/command
regression-tests.nobackend/tinydns-data-check/expected_result
regression-tests.recursor-dnssec/recursortests.py
regression-tests.recursor-dnssec/requirements.txt
regression-tests.recursor-dnssec/test_AggressiveNSECCache.py
regression-tests.recursor-dnssec/test_ECS.py
regression-tests.recursor-dnssec/test_Lua.py
regression-tests.recursor-dnssec/test_Notify.py
regression-tests.recursor-dnssec/test_PacketCache.py
regression-tests.recursor-dnssec/test_RPZ.py
regression-tests.recursor-dnssec/test_RootNXTrust.py
regression-tests.recursor-dnssec/test_RoutingTag.py
regression-tests/recursor-test
regression-tests/tests/.gitignore
regression-tests/tests/axfr/expected_result
regression-tests/tests/axfr/expected_result.dnssec
regression-tests/tests/axfr/expected_result.nsec3
regression-tests/tests/axfr/expected_result.nsec3-optout
regression-tests/tests/ds-at-unsecure-zone-cut/expected_result.nsec3-optout
regression-tests/tests/ent-unsigned-delegation/expected_result.dnssec
regression-tests/tests/nsec-at-delegation/command [new file with mode: 0755]
regression-tests/tests/nsec-at-delegation/description [new file with mode: 0644]
regression-tests/tests/nsec-at-delegation/expected_result [new file with mode: 0644]
regression-tests/tests/nsec-at-delegation/expected_result.narrow [new file with mode: 0644]
regression-tests/tests/nsec-at-delegation/expected_result.nsec3 [new file with mode: 0644]
regression-tests/tests/nsec-at-delegation/expected_result.nsec3-optout [new file with mode: 0644]
regression-tests/tests/nsec-at-delegation/skip.nodnssec [new file with mode: 0644]
regression-tests/zones/dnssec-parent.com
tasks.py

index bb94e3fc0225008f38036f4bee68e9caa472b63b..cc0e68a3b3d8439d64bf69419098a5c8102bf061 100644 (file)
@@ -2548,7 +2548,6 @@ PBpq
 pbtag
 pcall
 PCDNSSEC
-PCKS
 PCmissing
 pcomp
 pcount
index 54b8a99a0aae6c13426e7f001d199a59125f8b3f..43b7f2bacdf569d20b294d829a01972b51a7b589 100644 (file)
@@ -721,6 +721,7 @@ libsystemd
 libtdsodbc
 libyaml
 libzmq
+lightningstream
 Lindqvist
 linenos
 linenum
@@ -763,6 +764,8 @@ Luuk
 LYg
 Maik
 Maikel
+MAILA
+MAILB
 Majer
 Makefiles
 malcrafted
@@ -789,7 +792,6 @@ mbytes
 Meerwald
 Mekking
 memlock
-MEMLOCK
 Memusage
 menuselection
 metadatabase
@@ -1235,6 +1237,7 @@ Shabanov
 Shafir
 shantikulkarni
 shinsterneck
+shnya
 showdetails
 showflags
 Shukla
@@ -1352,6 +1355,7 @@ supervisord
 Surfnet
 swapcontext
 swoga
+syncer
 syncres
 sysadmin
 syscalls
@@ -1364,6 +1368,7 @@ Tarnell
 taskqueue
 tbhandler
 tcely
+TCounters
 tcp
 tcpconnecttimeouts
 tcpdump
@@ -1424,6 +1429,7 @@ tsigalgo
 tsigkey
 tsigname
 tsigsecret
+Tsinghua
 tstamp
 TSU
 ttls
@@ -1464,6 +1470,7 @@ unshadowing
 untruncated
 unzero
 updatepolicy
+upgradeable
 upperalpha
 upperroman
 urandom
@@ -1545,12 +1552,14 @@ xdp
 Xek
 Xeon
 XForwarded
+Xiang
 xorbooter
 xpf
 XRecord
 XXXXXX
 yahttp
 Yehuda
+yeswehack
 Yiu
 Ylitalo
 yml
index d0f020937e3bcadf696eb37c1043868d2f6265ac..642e34c11e575093c484d65357d4a9ae823fa542 100644 (file)
@@ -23,7 +23,7 @@ jobs:
       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
@@ -33,7 +33,7 @@ jobs:
           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 }}
@@ -72,7 +72,7 @@ jobs:
         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
@@ -82,7 +82,7 @@ jobs:
           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 }}
@@ -125,7 +125,7 @@ jobs:
         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
@@ -135,7 +135,7 @@ jobs:
           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 }}
@@ -191,7 +191,7 @@ jobs:
           --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
@@ -301,7 +301,7 @@ jobs:
           --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
@@ -326,7 +326,7 @@ jobs:
       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
@@ -352,7 +352,7 @@ jobs:
       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
@@ -379,7 +379,7 @@ jobs:
       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
@@ -410,7 +410,7 @@ jobs:
       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
@@ -439,7 +439,7 @@ jobs:
       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
@@ -458,7 +458,7 @@ jobs:
     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
@@ -486,7 +486,7 @@ jobs:
         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
index f4f3de09f7e3e168a27ace45604d1d2605d60b13..ca000c31fdc99659e16c7e785e5fa4ad7858144c 100644 (file)
@@ -61,7 +61,7 @@ jobs:
         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
index 9af59b44c1433016f8e618a5e0cb5943fd9e28c3..8823b25c22db4be73814ac814c772fc8255b3309 100644 (file)
@@ -24,10 +24,12 @@ jobs:
           - 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
index ae8c7d0602865bc1f0199c646ebcfe964412883b..c37001a7e5df002e2b5658a183227168f29fbe2a 100644 (file)
@@ -33,7 +33,7 @@ jobs:
     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.
index f0748e05a0b9850b35181fe4c16caba706c74aa7..82221b5dd81a5180f2fb3634dacc56c11e207017 100644 (file)
@@ -18,7 +18,7 @@ jobs:
       matrix:
         product: ['auth', 'recursor', 'dnsdist']
     steps:
-      - uses: actions/checkout@v3.1.0
+      - uses: actions/checkout@v3
         with:
           fetch-depth: 5
           submodules: recursive
index d26cb4a4d68b11cb86aef4310fc13b58dadb2ead..c02b266a22fc29d53ed1a336858db185de4e0ac5 100644 (file)
@@ -16,7 +16,7 @@ jobs:
     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
index 852239281e8294b01b9db0112f0556e351a78b79..19bac0344a2bfe4f7beded95ac1664093989f8ab 100644 (file)
@@ -14,7 +14,7 @@ jobs:
     # 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
index 0b1e70e62301c15790b4e70aab0cd73ae30d4429..a7d0db59b655ca41cfc3dba29329702dac26ea07 100644 (file)
@@ -28,7 +28,7 @@ jobs:
     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
@@ -47,7 +47,7 @@ jobs:
       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
@@ -72,7 +72,7 @@ jobs:
       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
@@ -102,7 +102,7 @@ jobs:
       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
index be08e63e6cb3819c071a89c4affe760cdd0cbf12..b7b52ea7a1253c0573db029d72bc91b6b26f042f 100644 (file)
@@ -14,7 +14,7 @@ jobs:
     # 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
index 8885c62b1f87b6032ea0d484a84c844554915ba9..07dd058c9e930d5bbea4cf4e2cff7043f43f0a37 100644 (file)
@@ -56,7 +56,7 @@ __pycache__
 .circleci/config.yml-local
 .env
 compile_commands.*
-/.cache
+.cache
 /.clang-tidy
 .gdb_history
 .venv
index 07038efceb4a69e3ed8d9be1d804b1217ea2a087..50bc7f99cdcdbe26a1c965bb779e6cc3bf7fcf08 100644 (file)
@@ -13,7 +13,7 @@ This license is included in this documentation.
 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
 -----------------
index 4274b452e5530ffdd671164cb4112cf3acaa6c95..7e4cc8b768397b9a622c060b0a72ee82c2da7d4c 100755 (executable)
@@ -13,6 +13,7 @@
 # Modules
 
 import argparse
+import re
 import subprocess
 import sys
 
@@ -24,7 +25,7 @@ from jinja2 import Environment, FileSystemLoader
 
 # Globals
 
-g_version = '0.0.1'
+g_version = '1.0.2'
 
 g_verbose = False
 
@@ -44,9 +45,9 @@ def init_argparser():
     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',
@@ -140,9 +141,9 @@ def write_release_files (release):
     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']:
@@ -151,8 +152,6 @@ def write_release_files (release):
         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)
 
@@ -160,20 +159,26 @@ def write_release_files (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)
 
@@ -205,13 +210,21 @@ def run (tag):
         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):
@@ -230,6 +243,7 @@ def test_release (release):
     dockerfiles = sorted(collect_dockerfiles(release))
     failed_builds = []
     failed_runs = []
+    returned_versions = []
     print('=== testing {} ==='.format(release))
     for df in dockerfiles:
         if g_verbose:
@@ -243,10 +257,13 @@ def test_release (release):
             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:')
@@ -256,6 +273,12 @@ def test_release (release):
         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
index c91a9a3b6c3209a8f9b24ec4733600c64b83c283..e4258e2da0288961d58b36aaaaecf4b6b94aadb2 100755 (executable)
@@ -23,13 +23,16 @@ if [ ! -z "$1" ]; then
   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
 
diff --git a/builder-support/debian/recursor/debian-buster/README.source b/builder-support/debian/recursor/debian-buster/README.source
deleted file mode 100644 (file)
index cf42723..0000000
+++ /dev/null
@@ -1 +0,0 @@
-See /usr/share/doc/quilt/README.source
diff --git a/builder-support/debian/recursor/debian-buster/configure-helpers/net-snmp-config b/builder-support/debian/recursor/debian-buster/configure-helpers/net-snmp-config
new file mode 100755 (executable)
index 0000000..6d8d6e7
--- /dev/null
@@ -0,0 +1,21 @@
+#!/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
index b5216671c5744d099251d675db336f4c293e3a7f..f7e5349a5d142d0520728acf2bd2e75dee7620bf 100644 (file)
@@ -1,29 +1,37 @@
 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},
index 8aba47378c53e7f8d974e782879268ab4e2612d9..b8e649b70869dfcf09bf228ff3a63a2c908b3358 100644 (file)
@@ -1,6 +1,7 @@
 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
@@ -30,8 +31,8 @@ Files: debian/*
 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/*
diff --git a/builder-support/debian/recursor/debian-buster/pdns-recursor.default b/builder-support/debian/recursor/debian-buster/pdns-recursor.default
deleted file mode 100644 (file)
index db03e54..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# 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
diff --git a/builder-support/debian/recursor/debian-buster/pdns-recursor.init b/builder-support/debian/recursor/debian-buster/pdns-recursor.init
deleted file mode 100644 (file)
index 8b0f44e..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-#!/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
-
index b7f625e555c60fbcc526e88695b46c9255cd2efb..d6aeec23c146125f613c10a9d4bcd47ccb56ef30 100644 (file)
@@ -1,4 +1,2 @@
 # 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
index 4e1da7099252129ed5d1b5683cd92ee006ce0983..5f83e9d07f37b945ac04413ec984f06a85ef614c 100644 (file)
@@ -3,17 +3,8 @@ set -e
 
 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
   ;;
 
   *)
@@ -22,11 +13,6 @@ case "$1" in
   ;;
 esac
 
-# Startup errors should never cause dpkg to fail.
-initscript_error() {
-    return 0
-}
-
 #DEBHELPER#
 
 exit 0
diff --git a/builder-support/debian/recursor/debian-buster/pdns-recursor.preinst b/builder-support/debian/recursor/debian-buster/pdns-recursor.preinst
new file mode 100644 (file)
index 0000000..691107c
--- /dev/null
@@ -0,0 +1,30 @@
+#!/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#
diff --git a/builder-support/debian/recursor/debian-buster/pdns-recursor.prerm b/builder-support/debian/recursor/debian-buster/pdns-recursor.prerm
deleted file mode 100644 (file)
index e78608c..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-set -e
-
-# Startup errors should never cause dpkg to fail.
-initscript_error() {
-    return 0
-}
-
-#DEBHELPER#
-
-exit 0
index 651c627974949195884d401d7333917b6f0257c2..bcfd5f65a17ed2a074ca39dabc3da1d2e354d10c 100755 (executable)
@@ -1,80 +1,66 @@
 #!/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
diff --git a/builder-support/debian/recursor/debian-buster/source.lintian-overrides b/builder-support/debian/recursor/debian-buster/source.lintian-overrides
deleted file mode 100644 (file)
index 700fed0..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# Source is in html/js/d3.js
-pdns-recursor source: source-is-missing html/js/d3.v3.js line length is 32005 characters (>512)
index a0a6fc4a76c1ea62ba6307c592d73033dbbc8af7..bf44d57917264cb38729f55e05571137de3ab19c 100644 (file)
@@ -1,3 +1,4 @@
 Tests: smoke
-Depends: @, dnsutils
+Depends: dnsutils,
+         @
 Restrictions: needs-root
index 797073364207a42caa696d420dcf2ecc78055f51..23f78fefe0fb05d55ee145c16e9cf7f4546db07d 100755 (executable)
@@ -2,6 +2,12 @@
 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
@@ -12,11 +18,11 @@ example.org.           172800  IN      NS      ns1.example.org.
 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
 
diff --git a/builder-support/dockerfiles/Dockerfile.target.amazon-2023 b/builder-support/dockerfiles/Dockerfile.target.amazon-2023
new file mode 100644 (file)
index 0000000..f47d6d7
--- /dev/null
@@ -0,0 +1,14 @@
+# 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
diff --git a/builder-support/dockerfiles/Dockerfile.target.ubuntu-lunar b/builder-support/dockerfiles/Dockerfile.target.ubuntu-lunar
new file mode 100644 (file)
index 0000000..ce71c39
--- /dev/null
@@ -0,0 +1,36 @@
+# 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
diff --git a/builder-support/dockerfiles/Dockerfile.target.ubuntu-lunar-amd64 b/builder-support/dockerfiles/Dockerfile.target.ubuntu-lunar-amd64
new file mode 120000 (symlink)
index 0000000..5ab4dd2
--- /dev/null
@@ -0,0 +1 @@
+Dockerfile.target.ubuntu-lunar
\ No newline at end of file
diff --git a/builder-support/dockerfiles/Dockerfile.target.ubuntu-lunar-arm64 b/builder-support/dockerfiles/Dockerfile.target.ubuntu-lunar-arm64
new file mode 120000 (symlink)
index 0000000..5ab4dd2
--- /dev/null
@@ -0,0 +1 @@
+Dockerfile.target.ubuntu-lunar
\ No newline at end of file
index 68b3e0dab1f28047273d4f4ea0570f9416af114f..a60c6118153a58519a429a7f0d43a66bd4e60196 100644 (file)
@@ -17,18 +17,17 @@ BuildRequires: systemd-units
 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
@@ -36,19 +35,22 @@ BuildRequires: lua-devel
 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
@@ -85,7 +87,7 @@ export RANLIB=gcc-ranlib
   --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
@@ -96,7 +98,7 @@ export RANLIB=gcc-ranlib
   --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
@@ -112,8 +114,8 @@ make %{?_smp_mflags} check || (cat test-suite.log && false)
 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
@@ -154,4 +156,4 @@ systemctl daemon-reload ||:
 %{_mandir}/man1/*
 %dir %{_sysconfdir}/dnsdist
 %config(noreplace) %{_sysconfdir}/%{name}/dnsdist.conf
-/lib/systemd/system/dnsdist*
+%{_unitdir}/dnsdist*
index ace97b02029e82d0369dcf53230e663d6c0388c7..75a2690f7ec9edd76fb3fff6661414e69643afac 100644 (file)
@@ -9,7 +9,7 @@ Source0: %{name}-%{getenv:BUILDER_VERSION}.tar.bz2
 
 Provides: powerdns-recursor = %{version}-%{release}
 
-%if 0%{?rhel} < 8
+%if 0%{?rhel} < 8 && 0%{?amzn} != 2023
 BuildRequires: boost169-devel
 %else
 BuildRequires: boost-devel
@@ -18,11 +18,14 @@ BuildRequires: libcap-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
@@ -55,8 +58,6 @@ export LDFLAGS=-L/usr/lib64/boost169
 %configure \
     --enable-option-checking=fatal \
     --sysconfdir=%{_sysconfdir}/%{name} \
-    --with-libsodium \
-    --with-net-snmp \
     --disable-silent-rules \
     --disable-static \
     --enable-unit-tests \
@@ -64,7 +65,12 @@ export LDFLAGS=-L/usr/lib64/boost169
     --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}
 
index 9493e6f45cb2507ec2e1e16b28a128cd687c9f48..9f265eda1d543b040e40aa13cb45315941d6dd7a 100644 (file)
@@ -20,15 +20,18 @@ BuildRequires: systemd-devel
 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
@@ -59,7 +62,7 @@ This package contains the extra tools for %{name}
 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
@@ -141,7 +144,7 @@ Summary: Geo backend for %{name}
 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
@@ -203,7 +206,9 @@ export LDFLAGS=-L/usr/lib64/boost169
   --with-lua=%{lua_implementation} \
   --with-dynmodules='%{backends}' \
   --enable-tools \
+%if 0%{?amzn} != 2023
   --with-libsodium \
+%endif
 %if 0%{?amzn} != 2
   --enable-ixfrdist \
 %endif
index 16a8f19b529d19ebb2995df91797f6c09d09ea03..7b3da21e39ab6271fd8f39319e39a120b2dce677 100644 (file)
@@ -117,7 +117,6 @@ The file must contain one IP and account per line, separated by whitespace.
 
 BIND backend can only read this file, not write it.
 
-
 .. _setting-bind-supermaster-config:
 
 ``bind-supermaster-config``
@@ -127,6 +126,14 @@ When a new zone is configured via the autosecondary mechanism, bindbackend *writ
 
 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
index 65dca9606b551483c4e0c9144813dc19b2a38339..b3c48f83c240a82c4c1ca274a1c1963f87ba9ff4 100644 (file)
@@ -72,7 +72,7 @@ Default is 2 on 32 bits systems, and 64 on 64 bits systems.
 ``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.
 
@@ -83,6 +83,7 @@ PowerDNS Version  LMDB Schema version
 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:
@@ -110,6 +111,16 @@ Size, in megabytes, of each LMDB database.
 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
 --------------
 
index 0c3f88d8b59df26610f95ee9af505cc40c341001..341f0e18e35fdde9c801d79741e69065fc5ac359 100644 (file)
@@ -1,6 +1,79 @@
 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
diff --git a/docs/changelog/4.8.rst b/docs/changelog/4.8.rst
new file mode 100644 (file)
index 0000000..5724d2d
--- /dev/null
@@ -0,0 +1,128 @@
+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)
index 6d5dbfcbe0d68c08ed6a63e906aaeae7ecc79c69..c8246ac3b6903aae97898d7faa8d9dc2e7d9bbac 100644 (file)
@@ -6,6 +6,7 @@ The changelogs for the PowerDNS Authoritative Server are split between release t
 .. toctree::
     :maxdepth: 2
 
+    4.8
     4.7
     4.6
     4.5
index 3f457a9f4433cd5ca9fd54024d9aef1d2c72e26e..d400225b22d8f36acf6adbab7bb4e4fb7fca5914 100644 (file)
@@ -12,10 +12,10 @@ This :doc:`license <../common/license>`  is included in this documentation.
 
 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
 ^^^^^^^^^^^^^^^^^
index c3e08efbcde223dfcec38475b448e660b609ba8f..66d0b82876cafb03f0ec90d1d25db82e9882cc3c 100644 (file)
@@ -49,6 +49,14 @@ addresses listen on port 443.
 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.
index 8a3add59dca3296420de8bcf5f575ad6627d1197..9ba2dde0734b56918b385988633523c9cb60026e 100644 (file)
@@ -1,4 +1,4 @@
-@       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.
 
@@ -117,6 +117,8 @@ auth-4.7.0.security-status                              60 IN TXT "1 OK"
 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/"
@@ -323,25 +325,29 @@ recursor-4.6.0-rc1.security-status                      60 IN TXT "3 Unsupported
 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/"
@@ -493,5 +499,8 @@ dnsdist-1.7.0.security-status                              60 IN TXT "1 OK"
 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"
index e68e9687dcd1126e22f4a8d428d73086b4fd3a78..2fa79898a592374c12b9fff54f5fa4c9820934b6 100644 (file)
@@ -8,6 +8,19 @@ Please upgrade to the PowerDNS Authoritative Server 4.0.0 from 3.4.2+.
 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
 ------------------------
 
index fc9e7c7197a56c71d5f6cb358bb290d75b708ac0..33c3d4568acdd585482e2778c6bbba1783a3dc10 100644 (file)
@@ -6,6 +6,10 @@
 #include <string.h>
 #include <map>
 
+#ifndef DNSDIST
+#include "../../pdns/gettime.hh"
+#endif
+
 using std::string;
 using std::runtime_error;
 using std::tuple;
@@ -16,6 +20,59 @@ static string MDBError(int rc)
   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.
@@ -184,6 +241,13 @@ MDB_txn *MDBRWTransactionImpl::openRWTransaction(MDBEnv *env, MDB_txn *parent, i
 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()
@@ -301,9 +365,10 @@ MDBRWCursor MDBRWTransactionImpl::getRWCursor(const MDBDbi& dbi)
   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)
index c900fccd4cb675cce2c3a49b728e05c5ad12379c..2d5983be6761194454bc9c3603c756d0c295f276 100644 (file)
 #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:
@@ -90,6 +100,67 @@ private:
 
 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
@@ -99,54 +170,80 @@ 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);
 }
 
@@ -157,15 +254,20 @@ public:
   {
   }
 
+#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)
   {
@@ -202,13 +304,11 @@ public:
   MDB_val d_mdbval;
 private:
   MDBInVal(){}
+#ifndef DNSDIST
   char d_memory[sizeof(double)];
-
+#endif
 };
 
-
-
-
 class MDBROCursor;
 
 class MDBROTransactionImpl
@@ -249,8 +349,19 @@ public:
 
     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;
   }
@@ -301,18 +412,23 @@ class MDBGenCursor
 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*> &registry, MDB_cursor *cursor):
+  MDBGenCursor(std::vector<T*> &registry, MDB_cursor *cursor, MDB_txn *txn=nullptr, uint64_t txtime=0):
     d_registry(&registry),
-    d_cursor(cursor)
+    d_cursor(cursor),
+    d_txn(txn),
+    d_txtime(txtime)
   {
     registry.emplace_back(static_cast<T*>(this));
   }
@@ -363,13 +479,101 @@ public:
     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)
@@ -378,7 +582,7 @@ public:
     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)
@@ -388,7 +592,7 @@ public:
     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);
   }
 
 
@@ -397,7 +601,7 @@ public:
     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)
@@ -415,7 +619,7 @@ public:
     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)
@@ -485,6 +689,8 @@ private:
 private:
   std::vector<MDBRWCursor*> d_rw_cursors;
 
+  uint64_t d_txtime{0};
+
   void closeRWCursors();
   inline void closeRORWCursors() {
     closeROCursors();
@@ -506,26 +712,41 @@ public:
 
   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)
   {
@@ -533,6 +754,26 @@ public:
     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;
   }
 
@@ -544,17 +785,19 @@ public:
 
     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;
   }
 
@@ -568,6 +811,7 @@ public:
 
   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"
@@ -584,27 +828,71 @@ public:
   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
 };
index 7b0abd339aec8c7321e73902ff873bc6fa52ca5c..720285352db5632c1400168c5943ad1851dfe6ac 100644 (file)
@@ -7,7 +7,7 @@ unsigned int MDBGetMaxID(MDBRWTransaction& txn, MDBDbi& dbi)
   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;
 }
@@ -28,5 +28,3 @@ unsigned int MDBGetRandomID(MDBRWTransaction& txn, MDBDbi& dbi)
   }
   throw std::runtime_error("MDBGetRandomID() could not assign an unused random ID");
 }
-
-
index 0810d9a97e82be2de0583da143dd2b3460f90ceb..a0e2cefb0d8dd10f0844301bef315f0633052d8d 100644 (file)
@@ -1,4 +1,5 @@
 #pragma once
+#include <stdexcept>
 #include <string_view>
 #include <iostream>
 #include "lmdb-safe.hh"
@@ -41,6 +42,7 @@ unsigned int MDBGetMaxID(MDBRWTransaction& txn, MDBDbi& dbi);
 */
 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
@@ -92,6 +94,51 @@ inline std::string keyConv(const T& t)
 }
 
 
+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
@@ -106,14 +153,24 @@ template<class Class,typename Type, typename Parent>
 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)));
     }
   }
@@ -124,6 +181,7 @@ struct LMDBIndexOps
   }
   MDBDbi d_idx;
   Parent* d_parent;
+
 };
 
 /** This is an index on a field in a struct, it derives from the LMDBIndexOps */
@@ -160,13 +218,13 @@ struct index_on_function : LMDBIndexOps<Class, Type, index_on_function<Class, Ty
 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 */)
   {
 
   }
@@ -181,12 +239,12 @@ public:
   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);
@@ -207,22 +265,22 @@ public:
     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)
@@ -239,29 +297,44 @@ public:
     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
     {};
@@ -280,8 +353,9 @@ public:
         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)) {
@@ -289,6 +363,16 @@ public:
           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");
@@ -314,6 +398,8 @@ public:
           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");
@@ -324,18 +410,18 @@ public:
       }
 
 
-      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;
       }
@@ -351,33 +437,45 @@ public:
       }
 
       // 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);
           }
@@ -387,20 +485,23 @@ public:
 
       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()
@@ -474,7 +575,7 @@ public:
     {
       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;
@@ -506,7 +607,7 @@ public:
     {
       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;
@@ -525,19 +626,56 @@ public:
     {
       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;
   };
@@ -603,7 +741,8 @@ public:
         }
         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);
index db8e6c2f3215305d08f9f935ac6cb56bae363e65..04518bb5ce340d6a63a9d5ba1453865cbdaa959f 100644 (file)
@@ -262,7 +262,7 @@ public:
     }
 
     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;
   }
@@ -270,7 +270,7 @@ public:
   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;
   }
index 9b19b0ce2a7eb4b3246742d27d80298787779ea5..f373c8adf75ef533e5684b4230d44b9a60df73da 100644 (file)
@@ -112,7 +112,7 @@ public:
     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();
@@ -143,7 +143,7 @@ public:
   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;
index 0927649ec24fc3998be0cc9054631e5fb8531ee9..a1a2fd9f327f980c7a55547d0bcc37d59092443c 100644 (file)
@@ -20,6 +20,8 @@
  * 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
@@ -49,7 +51,7 @@
 
 #include "lmdbbackend.hh"
 
-#define SCHEMAVERSION 4
+#define SCHEMAVERSION 5
 
 // List the class version here. Default is 0
 BOOST_CLASS_VERSION(LMDBBackend::KeyDataDB, 1)
@@ -59,6 +61,577 @@ static bool s_first = true;
 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
@@ -90,31 +663,55 @@ LMDBBackend::LMDBBackend(const std::string& suffix)
   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>();
@@ -134,17 +731,23 @@ LMDBBackend::LMDBBackend(const std::string& suffix)
         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");
 }
@@ -155,7 +758,7 @@ namespace serialization
 {
 
   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();
@@ -166,7 +769,7 @@ namespace serialization
   }
 
   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;
@@ -179,13 +782,13 @@ namespace serialization
   }
 
   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;
@@ -193,7 +796,7 @@ namespace serialization
   }
 
   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;
@@ -227,13 +830,13 @@ namespace serialization
   }
 
   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;
   }
@@ -251,7 +854,7 @@ namespace serialization
   }
 
   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
@@ -363,8 +966,8 @@ void LMDBBackend::deleteDomainRecords(RecordsRWTransaction& txn, uint32_t domain
   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;
@@ -582,7 +1185,7 @@ std::shared_ptr<LMDBBackend::RecordsRWTransaction> LMDBBackend::getRecordsRWTran
   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);
@@ -599,7 +1202,7 @@ std::shared_ptr<LMDBBackend::RecordsROTransaction> LMDBBackend::getRecordsROTran
     }
     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) {
@@ -614,6 +1217,8 @@ std::shared_ptr<LMDBBackend::RecordsROTransaction> LMDBBackend::getRecordsROTran
   }
 }
 
+#if 0
+// FIXME reinstate soon
 bool LMDBBackend::upgradeToSchemav3()
 {
   g_log << Logger::Warning << "Upgrading LMDB schema" << endl;
@@ -651,7 +1256,7 @@ bool LMDBBackend::upgradeToSchemav3()
     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);
@@ -675,6 +1280,7 @@ bool LMDBBackend::upgradeToSchemav3()
 
   return true;
 }
+#endif
 
 bool LMDBBackend::deleteDomain(const DNSName& domain)
 {
@@ -700,10 +1306,12 @@ 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();
@@ -711,10 +1319,11 @@ bool LMDBBackend::deleteDomain(const DNSName& domain)
 
   { // 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();
@@ -732,17 +1341,18 @@ bool LMDBBackend::deleteDomain(const DNSName& domain)
   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;
     }
   }
@@ -754,8 +1364,10 @@ bool LMDBBackend::list(const DNSName& target, int id, bool include_disabled)
   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();
   }
 
@@ -768,7 +1380,7 @@ bool LMDBBackend::list(const DNSName& target, int id, bool include_disabled)
   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;
@@ -817,16 +1429,16 @@ void LMDBBackend::lookup(const QType& type, const DNSName& qdomain, int zoneId,
     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;
@@ -839,6 +1451,7 @@ void LMDBBackend::lookup(const QType& type, const DNSName& qdomain, int zoneId,
 bool LMDBBackend::get(DNSZoneRecord& zr)
 {
   for (;;) {
+    // std::cerr<<"d_getcursor="<<d_getcursor<<std::endl;
     if (!d_getcursor) {
       d_rotxn.reset();
       return false;
@@ -849,12 +1462,13 @@ bool LMDBBackend::get(DNSZoneRecord& zr)
     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;
@@ -864,7 +1478,7 @@ bool LMDBBackend::get(DNSZoneRecord& zr)
       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++);
@@ -875,13 +1489,14 @@ bool LMDBBackend::get(DNSZoneRecord& zr)
         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();
         }
       }
@@ -910,7 +1525,7 @@ bool LMDBBackend::get(DNSResourceRecord& rr)
   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;
@@ -942,9 +1557,23 @@ bool LMDBBackend::getDomainInfo(const DNSName& domain, DomainInfo& di, bool gets
 {
   {
     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;
   }
 
@@ -1029,11 +1658,12 @@ bool LMDBBackend::createDomain(const DNSName& domain, const DomainInfo::DomainKi
   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();
 
@@ -1180,10 +1810,15 @@ bool LMDBBackend::getAllDomainMetadata(const DNSName& name, std::map<std::string
 {
   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;
 }
@@ -1192,11 +1827,17 @@ bool LMDBBackend::setDomainMetadata(const DNSName& name, const std::string& kind
 {
   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) {
@@ -1210,10 +1851,16 @@ bool LMDBBackend::setDomainMetadata(const DNSName& name, const std::string& kind
 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;
@@ -1340,13 +1987,13 @@ bool LMDBBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna
     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;
@@ -1356,7 +2003,7 @@ bool LMDBBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna
         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
@@ -1365,28 +2012,28 @@ bool LMDBBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna
       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
@@ -1396,18 +2043,18 @@ bool LMDBBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna
         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;
     }
@@ -1416,7 +2063,7 @@ bool LMDBBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna
     // 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;
@@ -1425,7 +2072,7 @@ bool LMDBBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna
           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
@@ -1438,13 +2085,13 @@ bool LMDBBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna
           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;
@@ -1454,7 +2101,7 @@ bool LMDBBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna
             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
@@ -1465,7 +2112,7 @@ bool LMDBBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna
           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;
@@ -1477,14 +2124,14 @@ bool LMDBBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna
             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
@@ -1493,7 +2140,7 @@ bool LMDBBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna
   }
   //  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;
@@ -1501,7 +2148,7 @@ bool LMDBBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna
         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;
@@ -1514,21 +2161,21 @@ bool LMDBBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna
         }
         // 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;
 }
@@ -1548,8 +2195,8 @@ bool LMDBBackend::getBeforeAndAfterNames(uint32_t id, const DNSName& zonenameU,
   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
@@ -1558,7 +2205,7 @@ bool LMDBBackend::getBeforeAndAfterNames(uint32_t id, const DNSName& zonenameU,
   }
   // 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;
@@ -1567,23 +2214,23 @@ bool LMDBBackend::getBeforeAndAfterNames(uint32_t id, const DNSName& zonenameU,
       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;
@@ -1595,39 +2242,39 @@ bool LMDBBackend::getBeforeAndAfterNames(uint32_t id, const DNSName& zonenameU,
         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;
@@ -1639,16 +2286,16 @@ bool LMDBBackend::getBeforeAndAfterNames(uint32_t id, const DNSName& zonenameU,
 
   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;
   }
@@ -1692,15 +2339,15 @@ bool LMDBBackend::updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName
   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);
         }
@@ -1724,7 +2371,9 @@ bool LMDBBackend::updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName
   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) {
@@ -1819,12 +2468,16 @@ bool LMDBBackend::updateEmptyNonTerminals(uint32_t domain_id, set<DNSName>& inse
 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;
+      }
     }
   }
 
@@ -1836,9 +2489,15 @@ bool LMDBBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, cons
 {
   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);
+      }
     }
   }
 
@@ -1855,10 +2514,16 @@ bool LMDBBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, cons
 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;
@@ -1874,6 +2539,21 @@ bool LMDBBackend::getTSIGKeys(std::vector<struct TSIGKey>& keys)
   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:
@@ -1888,6 +2568,7 @@ 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
   {
index 4b55184748b3dbe469e1f2436d911e9e62e50d09..f0333eae43c2eac5c327b00323738f63764161df 100644 (file)
@@ -148,6 +148,13 @@ public:
     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
   {
diff --git a/modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb-0 b/modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb-0
deleted file mode 100644 (file)
index 4bc4471..0000000
Binary files a/modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb-0 and /dev/null differ
diff --git a/modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb-1 b/modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb-1
deleted file mode 100644 (file)
index 65c700b..0000000
Binary files a/modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb-1 and /dev/null differ
diff --git a/modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb-0 b/modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb-0
deleted file mode 100644 (file)
index 4bc4471..0000000
Binary files a/modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb-0 and /dev/null differ
diff --git a/modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb-1 b/modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb-1
deleted file mode 100644 (file)
index 65c700b..0000000
Binary files a/modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb-1 and /dev/null differ
similarity index 95%
rename from modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb
rename to modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb
index d9b1f630e9e5f9281d55663e66a0f976646439e2..856f85242659bbca5e9f0f140010128ffbd61b3b 100644 (file)
Binary files a/modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb and b/modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb differ
diff --git a/modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb-0 b/modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb-0
new file mode 100644 (file)
index 0000000..9bed565
Binary files /dev/null and b/modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb-0 differ
similarity index 97%
rename from modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb-0-lock
rename to modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb-0-lock
index 26ca8a5f365fd503e3e11bc90fa6454543a92044..59479a6fb7dadb307e78cf5a0f69b35e42c3740b 100644 (file)
Binary files a/modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb-0-lock and b/modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb-0-lock differ
diff --git a/modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb-1 b/modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb-1
new file mode 100644 (file)
index 0000000..fa74288
Binary files /dev/null and b/modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb-1 differ
similarity index 97%
rename from modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb-1-lock
rename to modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb-1-lock
index ba97d65258bc0fee208828391896fb23a5b99da6..8d710b8cb3c63f33724a8fa7c96138df15c71b1d 100644 (file)
Binary files a/modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb-1-lock and b/modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb-1-lock differ
similarity index 97%
rename from modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb-lock
rename to modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb-lock
index a833f3b30a2fc4e92725e270956d7af2594432e6..f82fccb7791bf92010e6391df89fdd0dcc511de6 100644 (file)
Binary files a/modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb-lock and b/modules/lmdbbackend/test-assets/lmdb-v3-x86_64/pdns.lmdb-lock differ
similarity index 95%
rename from modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb
rename to modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb
index e3080c130fc14c94a04cc91845a80620ea9b3f4d..0d56ee3f5dd028dbeb12e206b88cd1d1d10f035f 100644 (file)
Binary files a/modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb and b/modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb differ
diff --git a/modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb-0 b/modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb-0
new file mode 100644 (file)
index 0000000..9bed565
Binary files /dev/null and b/modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb-0 differ
similarity index 97%
rename from modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb-0-lock
rename to modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb-0-lock
index eaa314cbde70d4bb48f4112c14aa5506e66c398d..cb698cc0d9519e7f7abbf70f3b941777437e2e42 100644 (file)
Binary files a/modules/lmdbbackend/test-assets/lmdb-v2-x86_64/pdns.lmdb-0-lock and b/modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb-0-lock differ
diff --git a/modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb-1 b/modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb-1
new file mode 100644 (file)
index 0000000..fa74288
Binary files /dev/null and b/modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb-1 differ
similarity index 97%
rename from modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb-1-lock
rename to modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb-1-lock
index 3858eb5a6dd3a436086ee27349d3ce3e944d79df..4cf2b295911bc2b7c44df330f0a231adee07a2b3 100644 (file)
Binary files a/modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb-1-lock and b/modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb-1-lock differ
similarity index 97%
rename from modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb-lock
rename to modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb-lock
index b3399636ce6af381310c0bec4c214b5393d9f3b7..62c3165d538baad93fb8410092d2db067600e415 100644 (file)
Binary files a/modules/lmdbbackend/test-assets/lmdb-v1-x86_64/pdns.lmdb-lock and b/modules/lmdbbackend/test-assets/lmdb-v4-x86_64/pdns.lmdb-lock differ
index a6685097350d177b95c01ac44cd108166c61978c..7a262b3edac8391b341fb7c7407c1394c98eff80 100644 (file)
@@ -20271,6 +20271,7 @@ Znztest.com:ns1.nztest.com.:ahu.example.com.:2005092501:28800:7200:604800:86400:
 +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
index e70be8d883affea4a2ecc871b705679efb0befe5..b71ae2d51ecda7103f1a61fb5fa10ea28aebb0ab 100644 (file)
Binary files a/modules/tinydnsbackend/data.cdb and b/modules/tinydnsbackend/data.cdb differ
index f05f6f4be90b02e1a5b63331cd3e33cda34d7831..88229c32a7416c682027be9dbfd8558352037c2d 100644 (file)
@@ -232,6 +232,7 @@ pdns_server_SOURCES = \
        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 \
@@ -368,6 +369,7 @@ pdnsutil_SOURCES = \
        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 \
index 16d6e893ac2f5683fb58d52655c87dfa63a7f28d..b8d825dd5de53c0a7ef596c29703a11fdedfc9df 100644 (file)
@@ -116,7 +116,7 @@ DNSZoneRecord CatalogInfo::getCatalogVersionRecord(const DNSName& zone)
   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;
 }
 
@@ -135,14 +135,14 @@ void CatalogInfo::toDNSZoneRecords(const DNSName& zone, vector<DNSZoneRecord>& d
   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);
   }
 
@@ -150,7 +150,7 @@ void CatalogInfo::toDNSZoneRecords(const DNSName& zone, vector<DNSZoneRecord>& d
     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);
   }
 }
index 0eb9bfb1ec01a1215d111bc92a2ceabb94d47c5f..5f46624b62a0607178817e4249f69ee7ab3adb34 100644 (file)
@@ -210,7 +210,7 @@ static void declareArguments()
   ::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";
 
@@ -1241,6 +1241,8 @@ int main(int argc, char** argv)
       ::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"))
@@ -1254,6 +1256,7 @@ int main(int argc, char** argv)
     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"));
index e073d2c77bd671d7a004740292c2c0b9efacac1a..2747fc93f57e40bfbc31ddb63020923614705ba4 100644 (file)
@@ -33,7 +33,7 @@
 #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();
index fd44af19fe9238bdfd9e655d4c9d698212ea82ac..bbe23eef6a3a5ce1e8ea3434d008ee41163b88db 100644 (file)
@@ -118,22 +118,22 @@ void CommunicatorClass::mainloop()
   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();
@@ -156,7 +156,7 @@ void CommunicatorClass::mainloop()
           }
           break; // something happened
         }
-        // this gets executed at least once every second
+        // this gets executed about once per second
         doNotifications(&P);
       }
     }
@@ -176,4 +176,3 @@ void CommunicatorClass::mainloop()
     _exit(1);
   }
 }
-
index fe4ffe4bdb3de717fafab254fadc87b049442dc5..9cd12fcbea03cd5e75a51fde9837975945916cbc 100644 (file)
@@ -253,7 +253,7 @@ public:
         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;
   }
index 86b41c4a18d6057623f726ad11932125158f171d..9d7b85a332f95c06d78b6bdf93eed3627b83a53b 100644 (file)
@@ -638,12 +638,11 @@ void DNSSECKeeper::getPreRRSIGs(UeberBackend& db, vector<DNSZoneRecord>& rrs, ui
   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;
       }
index d9fb5096f88c213ff88e369c131bb5da12674fe9..99bbd72aa65e8749e66ee8237914427ab80ba681 100644 (file)
@@ -71,8 +71,9 @@ static const std::array<std::string, 10> rcodes_short_s =  {
 };
 
 std::string RCode::to_s(uint8_t rcode) {
-  if (rcode > 0xF)
+  if (rcode > 0xF) {
     return std::string("ErrOutOfRange");
+  }
   return ERCode::to_s(rcode);
 }
 
@@ -83,9 +84,10 @@ std::string RCode::to_short_s(uint8_t 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);
 }
 
index ef44cf813d0b6c6389db733d9da92e5c430761c9..7ceda1eeecc7c7d20cf8a2ecdd80dc62c5ae6dc4 100644 (file)
@@ -32,7 +32,7 @@ struct DNSRecord;
 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;
@@ -41,8 +41,8 @@ public:
 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
index 1a4d20f78ee345edde94c8f32828fd53ada102c9..0cba797fa230ef5fe90647c87a9456c8c68985f8 100644 (file)
@@ -157,14 +157,14 @@ struct SendReceive
       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";
         }
       }
       
@@ -188,9 +188,9 @@ struct SendReceive
   {
     (*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();
       }
@@ -351,9 +351,9 @@ try
   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]);
index a5bd944ee9ab26d3ed92e554cb9cfe8e09b1c460..7ca9be2f6e7ee0291b2e60c9410f883471969c42 100644 (file)
@@ -296,7 +296,8 @@ bool DNSDistPacketCache::get(DNSQuestion& dq, uint16_t queryId, uint32_t* keyOut
   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(),
index b953180180e8e8220a5bc4a059392134efc2536e..90cdd5acbc8d2ede802cb4aaa7b1cc649295035b 100644 (file)
@@ -77,6 +77,7 @@ static bool doOneCarbonExport(const Carbon::Endpoint& endpoint)
       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";
@@ -281,7 +282,7 @@ static void carbonHandler(Carbon::Endpoint&& endpoint)
           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;
       }
index 86647243ad4e806351f366dcfb84e822c9282d36..7eff465774b04cb3bf1849c9bc7e91d34140333e 100644 (file)
@@ -548,7 +548,7 @@ const std::vector<ConsoleKeyword> g_consoleKeywords{
   { "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'"},
index acbada4e14d7096bd2ebf7c4a3a0067e82922583..905cf3d08f9d84271eef715607d5717e27b562a1 100644 (file)
@@ -118,7 +118,7 @@ public:
   }
   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;
@@ -1755,7 +1755,7 @@ public:
   }
   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;
index d6087531fa6cdf1018c24cfcd2008c897f06da3e..5246e482142e067d47f9129c0f8d44e9b31564cc 100644 (file)
@@ -119,7 +119,7 @@ void setupLuaBindings(LuaContext& luaCtx, bool client)
     });
   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);
index ccc4a997cb82249f26e5c689f35ba5593afc1374..f427e2cf2ec46977e2fa528b3f348461e6b8e877 100644 (file)
@@ -19,6 +19,8 @@
  * 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"
@@ -114,7 +116,7 @@ static counts_t filterScore(const counts_t& counts,
   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)
 {
@@ -128,13 +130,20 @@ 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);
     }
   }
 
@@ -401,38 +410,59 @@ void setupLuaInspection(LuaContext& luaCtx)
       }
     });
 
-  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;
+            }
           }
         }
       }
@@ -470,12 +500,19 @@ void setupLuaInspection(LuaContext& luaCtx)
 
       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);
           }
@@ -495,17 +532,19 @@ void setupLuaInspection(LuaContext& luaCtx)
             }
             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);
         }
@@ -518,13 +557,13 @@ void setupLuaInspection(LuaContext& luaCtx)
           }
         }
         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();
@@ -549,8 +588,13 @@ void setupLuaInspection(LuaContext& luaCtx)
         }
       }
 
-      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());
+        }
       }
     });
 
@@ -589,14 +633,14 @@ void setupLuaInspection(LuaContext& luaCtx)
         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);
@@ -785,6 +829,7 @@ void setupLuaInspection(LuaContext& luaCtx)
   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);
index 7100cf72bebdf25062d26a0f68ecdce33f053428..ba8f465d23572e22eb16d79978f6df8de1c985ad 100644 (file)
@@ -67,7 +67,7 @@ static boost::uuids::uuid makeRuleID(std::string& id)
   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;
 
@@ -468,7 +468,7 @@ void setupLuaRules(LuaContext& luaCtx)
         }
       }
       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();
 
     });
 
index fdce3a779f9da49cc13bf614cd34a94f47d275dc..9efa59dd2837d312160acd458f98f747c28eb4c2 100644 (file)
@@ -498,7 +498,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
 
                          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);
@@ -881,14 +881,15 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
       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};
@@ -903,11 +904,13 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
           }
           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();
@@ -916,12 +919,12 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
       }
       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;
       }
 
index 6fb357595bcc1effc9c74ecac14ac0f09b61a757..61a021fedf0a1062b2a5c98da7d24d821cf9a1cb 100644 (file)
@@ -161,7 +161,7 @@ using luaruleparams_t = LuaAssociativeTable<std::string>;
 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);
index 784af371ab62bab8b34fd5ac188c939a93a617cd..d853a32d04eaddae84be3a8f367c7704d6b76c8e 100644 (file)
@@ -303,7 +303,7 @@ static int backendStatTable_handler(netsnmp_mib_handler* handler,
         break;
       case COLUMN_BACKENDLATENCY:
         DNSDistSNMPAgent::setCounter64Value(request,
-                                            server->latencyUsec/1000.0);
+                                            server->getRelevantLatencyUsec() / 1000.0);
         break;
       case COLUMN_BACKENDWEIGHT:
         DNSDistSNMPAgent::setCounter64Value(request,
index 11da401daf2ba5f3e781aea19a6be815e97d8b17..a5af69e2ced7d1f7caa7989f20fdb487a431b21c 100644 (file)
@@ -241,7 +241,7 @@ static void handleResponseSent(std::shared_ptr<IncomingTCPConnectionState>& stat
   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) {
@@ -1084,8 +1084,14 @@ void IncomingTCPConnectionState::handleIO(std::shared_ptr<IncomingTCPConnectionS
 
 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;
 
@@ -1114,6 +1120,11 @@ void IncomingTCPConnectionState::notifyIOError(InternalQueryState&& query, const
 
 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));
 }
index 6dddd4fd5057b37b25837f02a1ba8ede0a1a5250..06aa910ab68f91e832c0853007591d388951f93b 100644 (file)
@@ -174,7 +174,7 @@ static ssize_t sendfromto(int sock, const void* data, size_t len, int flags, con
   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 {
@@ -696,10 +696,10 @@ static void handleResponseForUDPClient(InternalQueryState& ids, PacketBuffer& re
   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);
@@ -1612,6 +1612,7 @@ static void processUDPQuery(ClientState& cs, LocalHolders& holders, const struct
          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;
index 88900e1dab03cf40dbfdf56c5570f06238d05156..472a729ba17088ba3ea5002d59dda03eba82f98d 100644 (file)
@@ -1048,6 +1048,14 @@ public:
     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;
index d6d84c0b9935f4dc449276e51361a4201f2384ca..ae9896ed273d6339ff59a56e63e149ca6e4683a8 100644 (file)
@@ -416,7 +416,12 @@ void DynBlockRulesGroup::processResponseRules(counts_t& counts, StatNode& root,
       }
 
       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);
       }
     }
   }
index cec6769dd0fbadbc69857c1a31f5279add5a7f15..70fec893c88ada5f81a3153cb4f472186e5f5bbf 100644 (file)
@@ -40,7 +40,7 @@ template <class T> static std::shared_ptr<DownstreamState> getLeastOutstanding(c
   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++;
     }
   }
index b690dd368bb52e4afcc562efa48172afd0d43408..c9fa8407ef80ef3632c1d8c66ca21927e5a0c5bc 100644 (file)
@@ -683,7 +683,7 @@ int dnsdist_ffi_server_get_order(const dnsdist_ffi_server_t* server)
 
 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)
index 4c50e4bf15f7c61eddb16715f60bbc52ed47048b..0187ebcb4e74660c678f456004911537d386b575 100644 (file)
@@ -54,6 +54,11 @@ uint64_t dnsdist_ffi_stat_node_get_bytes(const dnsdist_ffi_stat_node_t* node)
   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;
@@ -101,6 +106,11 @@ uint64_t dnsdist_ffi_stat_node_get_children_bytes_count(const dnsdist_ffi_stat_n
   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);
index 05f087f649d4f31126b0b48aefe965ebcc26a800..f45a180dc6767d4dac77020627c0dd462a57336f 100644 (file)
@@ -29,6 +29,7 @@ extern "C" {
   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")));
 
@@ -40,6 +41,7 @@ extern "C" {
   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")));
 }
index 536fb39cce9e58e0ad56950a4d12d7bc09d68b45..1a376a8eada1d8956556cab041a2fdc9e9c4512d 100644 (file)
@@ -25,6 +25,7 @@
 
 #ifndef DISABLE_SECPOLL
 #include <string>
+#include <ctime>
 
 extern std::string g_secPollSuffix;
 extern time_t g_secPollInterval;
index 0888d3f0991c0208b4cc6997a610b6f3d1142c37..a54a942a503df3be34975ed80535639307fd7720 100644 (file)
@@ -1,6 +1,174 @@
 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
@@ -867,7 +1035,7 @@ Changelog
     :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
index 259417be177551c377e9f3d002636eff19df2b21..781d0ef529702ac3b1adb29b89d87eaa2cff8317 100644 (file)
@@ -8,18 +8,22 @@ End of life statements
      - 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
index d7c41e7317e6d16035d19ac082ce2a5b837e4faf..c9faac2ca09206a911f4c64780e8294bee945879 100644 (file)
@@ -1138,8 +1138,11 @@ Status, Statistics and More
 
   :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.
@@ -1153,7 +1156,12 @@ Status, Statistics and More
 
   :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)
 
@@ -1877,18 +1885,18 @@ Other functions
 
   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
 ~~~~~~~~~~~
index 2a3b4f71f13903c3642ef246c9591cf2ac2df7a9..99e508a8ff0ad71ceae7fcf9c010daf786d960b0 100644 (file)
@@ -28,6 +28,7 @@ These are all the functions, objects and methods related to the :doc:`../advance
   :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.
@@ -38,7 +39,7 @@ These are all the functions, objects and methods related to the :doc:`../advance
   * ``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
 
index f3302729e74e7cb5a266fc48c9c28d07cf03b163..d089a9d0f7c8b98185b4faf4afad492d4027fd16 100644 (file)
@@ -12,6 +12,11 @@ The :func:`setMaxTCPConnectionsPerClient` limit is now properly applied to DNS o
 
 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
 --------------
 
index 8481193d877b901a4c32dbbd63528a154b3b93f8..021eec32d2d00d022753a7ed596933da601dc4ca 100644 (file)
@@ -486,7 +486,7 @@ public:
 
     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) {
@@ -1735,7 +1735,7 @@ void handleUDPResponseForDoH(DOHUnitUniquePtr&& du, PacketBuffer&& udpResponse,
 
     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);
 
index 7e2599780bd47087448866cc076df0a280e7bc15..4f3bc695e95e9f5948b801197e2a4cdc242c5b7a 100644 (file)
@@ -50,7 +50,8 @@
     </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">
index cbf9534063688fb19570be155d54136fe12ce9d5..81c1b061faae45a8f272d001f384be8e0be3123a 100644 (file)
@@ -151,6 +151,9 @@ $(document).ready(function() {
                 $("#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;
 
@@ -190,11 +193,12 @@ $(document).ready(function() {
                      $("#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>";
index ed7ec5a9995cdd9c310085876db318efebf8e2dc..cc29a195d5430acaf71f37b567f141455327949d 100644 (file)
@@ -194,7 +194,7 @@ BOOST_AUTO_TEST_CASE(test_Response)
     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());
 
index 3bfbf3007fbd4dc4f037ab557c17e9fe4e41020c..25a90078a89081922ed3ca1458a358532db66faa 100644 (file)
@@ -296,7 +296,11 @@ void DNSName::makeUsRelative(const DNSName& zone)
 
 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();
index 9e40f6f0ad04c45c1d82446bf8c856fd7b9ffd4d..b9fcdfabe307fffeaa4a2e50796a16adc68aa095 100644 (file)
@@ -174,7 +174,7 @@ void DNSPacket::addRecord(DNSZoneRecord&& rr)
   // 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) {
@@ -354,7 +354,7 @@ void DNSPacket::wrapup(bool throwsOnTruncation)
         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");
@@ -516,7 +516,7 @@ bool DNSPacket::getTSIGDetails(TSIGRecordContent* trc, DNSName* keyname, uint16_
   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;
@@ -549,7 +549,7 @@ bool DNSPacket::getTKEYRecord(TKEYRecordContent *tr, DNSName *keyname) const
 
     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;
index 0b486edef3ccc2f4a355e4198a6f23f541080b12..7f755793cedd4dba2e4c33983ab687a398cc991f 100644 (file)
@@ -73,7 +73,7 @@ string UnknownRecordContent::getZoneRepresentation(bool /* noDot */) const
   return str.str();
 }
 
-void UnknownRecordContent::toPacket(DNSPacketWriter& pw)
+void UnknownRecordContent::toPacket(DNSPacketWriter& pw) const
 {
   pw.xfrBlob(string(d_record.begin(),d_record.end()));
 }
@@ -211,7 +211,7 @@ DNSResourceRecord DNSResourceRecord::fromWire(const DNSRecord& d) {
   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;
@@ -279,11 +279,11 @@ void MOADNSParser::init(bool query, const std::string_view& packet)
           !(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:
@@ -925,47 +925,45 @@ void clearDNSPacketRecordTypes(PacketBuffer& packet, const std::unordered_set<QT
 }
 
 // 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)
index c19c766c5e639097ccd31a1dd10d0c8fbda25b1f..4b22a7ac7c515e622fbcc790ae2065b17d073ae0 100644 (file)
@@ -199,9 +199,9 @@ public:
 
   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);
@@ -312,7 +312,9 @@ struct DNSRecord
     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{};
@@ -331,6 +333,21 @@ struct DNSRecord
     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))
@@ -416,7 +433,7 @@ public:
   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;
@@ -471,8 +488,8 @@ private:
 };
 
 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);
@@ -486,9 +503,9 @@ bool getEDNSUDPPayloadSizeAndZ(const char* packet, size_t length, uint16_t* payl
 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
index 179a8c9aabb7250d65824e6217a8ab83a8f8f228..a25691c916cd11bff5a30c79d6b6843d32fffea4 100644 (file)
@@ -252,7 +252,7 @@ void DNSProxy::mainloop()
         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)) {
 
@@ -262,7 +262,7 @@ void DNSProxy::mainloop()
                 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));
               }
             }
index aab8577513e20955aed8e4740fd27096273f9a4b..1cf4c2c82845799a98919dbf9d758089de35cacd 100644 (file)
@@ -181,13 +181,13 @@ string LUARecordContent::getCode() const
 }
 #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())
@@ -471,7 +471,7 @@ std::shared_ptr<DNSRecordContent> EUI48RecordContent::make(const string& zone)
     }
     return ret;
 }
-void EUI48RecordContent::toPacket(DNSPacketWriter& pw)
+void EUI48RecordContent::toPacket(DNSPacketWriter& pw) const
 {
     string blob(d_eui48, d_eui48+6);
     pw.xfrBlob(blob);
@@ -516,7 +516,7 @@ std::shared_ptr<DNSRecordContent> EUI64RecordContent::make(const string& zone)
     }
     return ret;
 }
-void EUI64RecordContent::toPacket(DNSPacketWriter& pw)
+void EUI64RecordContent::toPacket(DNSPacketWriter& pw) const
 {
     string blob(d_eui64, d_eui64+8);
     pw.xfrBlob(blob);
@@ -687,7 +687,7 @@ std::shared_ptr<DNSRecordContent> APLRecordContent::make(const string& zone) {
 
 
 // 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);
@@ -760,14 +760,16 @@ void SVCBBaseRecordContent::setHints(const SvcParam::SvcParamKey &key, const std
   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;
   }
@@ -805,6 +807,16 @@ set<SvcParam>::const_iterator SVCBBaseRecordContent::getParamIt(const SvcParam::
   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,
@@ -847,12 +859,6 @@ static uint16_t makeTag(const std::string& data)
 }
 
 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()));
 }
index 3974084b4e1b62a7bb2a682a5a4e684a9eeac0c2..dc2a1ce60048c0658f054702213e338c097f0b1c 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "dnsparser.hh"
 #include "dnswriter.hh"
+#include "lock.hh"
 #include "rcpgenerator.hh"
 #include <set>
 #include <bitset>
@@ -40,8 +41,9 @@
   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
@@ -272,6 +274,11 @@ class ALIASRecordContent : public DNSRecordContent
 public:
   includeboilerplate(ALIAS)
 
+  [[nodiscard]] const DNSName& getContent() const
+  {
+    return d_content;
+  }
+private:
   DNSName d_content;
 };
 #endif
@@ -329,7 +336,7 @@ class OPTRecordContent : public DNSRecordContent
 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;
 };
@@ -360,7 +367,6 @@ public:
   DNSKEYRecordContent();
   includeboilerplate(DNSKEY)
   uint16_t getTag() const;
-  uint16_t getTag();
 
   uint16_t d_flags{0};
   uint8_t d_protocol{0};
@@ -527,26 +533,29 @@ class SVCBBaseRecordContent : public DNSRecordContent
     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
@@ -664,7 +673,7 @@ public:
   }
 
   void fromPacket(PacketReader& pr);
-  void toPacket(DNSPacketWriter& pw);
+  void toPacket(DNSPacketWriter& pw) const;
   std::string getZoneRepresentation() const;
 
   static constexpr size_t const nbTypes = 65536;
@@ -699,7 +708,7 @@ public:
   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;
@@ -737,7 +746,7 @@ public:
   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};
@@ -784,7 +793,7 @@ public:
   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
   {
@@ -813,7 +822,7 @@ public:
   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
   {
@@ -838,7 +847,7 @@ public:
   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};
@@ -899,7 +908,7 @@ public:
   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
@@ -914,7 +923,7 @@ public:
   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
@@ -998,7 +1007,7 @@ std::shared_ptr<RNAME##RecordContent::DNSRecordContent> RNAME##RecordContent::ma
   return std::make_shared<RNAME##RecordContent>(zonedata);                                         \
 }                                                                                                  \
                                                                                                    \
-void RNAME##RecordContent::toPacket(DNSPacketWriter& pw)                                           \
+void RNAME##RecordContent::toPacket(DNSPacketWriter& pw) const                                     \
 {                                                                                                  \
   this->xfrPacket(pw);                                                                             \
 }                                                                                                  \
@@ -1042,6 +1051,12 @@ void RNAME##RecordContent::xfrPacket(Convertor& conv, bool /* noDot */) \
   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
 {
index 8d3a529b8e25a7d7491a6190d2402d332a19275b..588ca66026166e2f91dd439da3f53fb9705f2dbe 100644 (file)
@@ -306,9 +306,9 @@ static void emitFlightTimes()
   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;
@@ -366,10 +366,10 @@ static void measureResultAndClean(qids_t::const_iterator iter)
     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";
 
index 2f858813a4e49a63daa1a8b139886a2ac9e1356c..06c45dd4e22a7fc63b120f073d09c2c5d417e9d1 100644 (file)
@@ -358,7 +358,7 @@ try
              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) {
@@ -478,9 +478,9 @@ try
 
         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;
@@ -494,9 +494,9 @@ try
     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;
@@ -507,7 +507,7 @@ try
 
   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());
index 50479d5ee788d6a956b24fa6e81041ae12662848..5a8e3cd96fcb9618a8f595c5de4869ca0b1c53b4 100644 (file)
@@ -375,7 +375,7 @@ void DNSCryptoKeyEngine::testMakers(unsigned int algo, maker_t* creator, maker_t
 
   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");
@@ -414,7 +414,7 @@ string getMessageForRRSET(const DNSName& qname, const RRSIGRecordContent& rrc, c
   // 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());
@@ -435,7 +435,7 @@ string getMessageForRRSET(const DNSName& qname, const RRSIGRecordContent& rrc, c
     }
   }
 
-  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);
@@ -492,7 +492,7 @@ DSRecordContent makeDSFromDNSKey(const DNSName& qname, const DNSKEYRecordContent
 {
   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 {
index f2d00f28f84cc18a0250757f4bf945586b2c4f74..c6ddb5bc0ec6ce52abb1669ae16eb513120fe0ae 100644 (file)
@@ -263,12 +263,12 @@ struct CanonicalCompare
 };
 
 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);
 
index 702e791a7db4e2462ba3957e81ed198c8b415086..74dc882ab012fffdcdf4301d58f912f6cc06b46b 100644 (file)
@@ -169,7 +169,7 @@ static void addSignature(DNSSECKeeper& dk, UeberBackend& db, const DNSName& sign
     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);
     }
   }
@@ -205,7 +205,7 @@ void addRRSigs(DNSSECKeeper& dk, UeberBackend& db, const set<DNSName>& authSet,
 {
   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;
@@ -219,11 +219,17 @@ void addRRSigs(DNSSECKeeper& dk, UeberBackend& db, const set<DNSName>& authSet,
   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
@@ -236,10 +242,10 @@ void addRRSigs(DNSSECKeeper& dk, UeberBackend& db, const set<DNSName>& authSet,
     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);
 }
index 51f1e8b3cefd2f2854dbe059b01f582f898f4659..b35ebc7a9607a3a63f9ef826c343b5fc43ac0e18 100644 (file)
@@ -247,7 +247,7 @@ try
   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;
   }
 
@@ -305,8 +305,8 @@ try
   }
 
   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;
index 1c2337100101cea5512ec81f8b5950569e4ea283..b76ca1a21845c2cfa7967c1f1940783fd6441ce7 100644 (file)
@@ -29,21 +29,21 @@ std::tuple<size_t, size_t, size_t> GssContext::getCounts() { return std::make_tu
 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
index 4c746befab51d86730d36a8ffdda6f7ee30b4777..ba2e545e92bcfcf2491ec44a7b93f40c031c5b1f 100644 (file)
@@ -74,10 +74,10 @@ public:
     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;
 
@@ -89,9 +89,13 @@ public:
     }
 
     return true;
-#endif
+  }
+#else
+  bool setName(const std::string& /* name */)
+  {
     return false;
-  };
+  }
+#endif
 
   ~GssName()
   {
@@ -101,24 +105,28 @@ public:
 #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;
@@ -132,10 +140,13 @@ public:
     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()
index e0c7218f775c6400bc34f9aeaa4c41aacdc1d482..31ac2a9773e3d63a794a1637e31f0f2a53259b98 100644 (file)
@@ -147,7 +147,7 @@ int SSetsockopt(int sockfd, int level, int opname, int value)
   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)
index aef59e4dff32900ba670f2135db71e7c132af0c1..9615d7c6b321de4bf77a8cd9b0b5f0d2b0154072 100644 (file)
@@ -27,7 +27,7 @@
 #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;
 
@@ -137,7 +137,7 @@ vector<pair<vector<DNSRecord>, vector<DNSRecord>>> getIXFRDeltas(const ComboAddr
   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;
@@ -193,7 +193,7 @@ vector<pair<vector<DNSRecord>, vector<DNSRecord>>> getIXFRDeltas(const ComboAddr
   //   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;
@@ -255,7 +255,7 @@ vector<pair<vector<DNSRecord>, vector<DNSRecord>>> getIXFRDeltas(const ComboAddr
           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;
         }
index 34408e251092ed03384b34c6fcbaa91b1b371976..bdbabd3d8db42540f788b0fe07a1095362b179af 100644 (file)
@@ -32,4 +32,4 @@ vector<pair<vector<DNSRecord>, vector<DNSRecord>>>   getIXFRDeltas(const ComboAd
                                                                    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);
index b0485463a8f16e840a28a16cd53ab5b16ddc3e8d..9207a346242aa1816761dc581ad7c2639388ad50 100644 (file)
@@ -124,8 +124,8 @@ struct convert<Netmask> {
 } // 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;
@@ -133,7 +133,7 @@ struct ixfrdiff_t {
 };
 
 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;
@@ -227,7 +227,7 @@ static void cleanUpDomain(const DNSName& domain, const uint16_t& keep, const str
   }
 }
 
-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);
@@ -241,7 +241,7 @@ static void getSOAFromRecords(const records_t& records, shared_ptr<SOARecordCont
   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;
@@ -282,7 +282,7 @@ static void updateThread(const string& workdir, const uint16_t& keep, const uint
     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);
@@ -330,7 +330,7 @@ static void updateThread(const string& workdir, const uint16_t& keep, const uint
       }
 
       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;
@@ -349,7 +349,7 @@ static void updateThread(const string& workdir, const uint16_t& keep, const uint
 
       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);
@@ -373,7 +373,7 @@ static void updateThread(const string& workdir, const uint16_t& keep, const uint
       TSIGTriplet tt;
 
       // The *new* SOA
-      shared_ptr<SOARecordContent> soa;
+      shared_ptr<const SOARecordContent> soa;
       uint32_t soaTTL = 0;
       records_t records;
       try {
@@ -545,7 +545,7 @@ static bool makeRefusedPacket(const MOADNSParser& mdp, vector<uint8_t>& packet)
   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;
@@ -573,7 +573,7 @@ static bool sendPacketOverTCP(int fd, const std::vector<uint8_t>& packet)
 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;
@@ -640,7 +640,7 @@ static bool handleAXFR(int fd, const MOADNSParser& mdp) {
     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;
 
@@ -665,7 +665,7 @@ static bool handleAXFR(int fd, const MOADNSParser& mdp) {
 /* 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.
@@ -925,7 +925,7 @@ static void tcpWorker(int tid) {
          *  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;
index 292287fc33d34a8fc524ff311687069914697d11..4715e1dcd32769315a2502ac1cab1b866f051407 100644 (file)
@@ -29,7 +29,7 @@
 #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);
@@ -97,7 +97,7 @@ uint32_t getSerialFromRecords(const records_t& records, DNSRecord& soaret)
   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;
@@ -113,7 +113,7 @@ static void writeRecords(FILE* fp, const records_t& records)
             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());
     }
   }
@@ -187,7 +187,7 @@ void loadZoneFromDisk(records_t& records, const string& fname, const DNSName& zo
  * 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();
index bce8c6b48fd900d7599ab91253aed18246713ab2..7e31efb52dac7d29e02d306005905457173ecccd 100644 (file)
@@ -26,6 +26,7 @@
 #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"
@@ -34,7 +35,7 @@ using namespace boost::multi_index;
 
 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());
   }
@@ -49,15 +50,15 @@ typedef multi_index_container <
                       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);
index 90e60e505c994fa29fde9beddc7f06cfaad2c072..e6eedf42ce2a849485856d8afb88df4b1a9f701a 100644 (file)
@@ -87,12 +87,12 @@ int main(int argc, char** argv) {
 
       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);
     }
@@ -177,7 +177,7 @@ int main(int argc, char** argv) {
 
       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;
@@ -199,7 +199,7 @@ int main(int argc, char** argv) {
         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;
           }
         }
 
@@ -214,8 +214,8 @@ int main(int argc, char** argv) {
         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;
@@ -225,7 +225,7 @@ int main(int argc, char** argv) {
         }
 
         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) {
index a85c5f2da6b505c1676ab6e675771157b8dfa03a..24fd774a73a8113fec016c9bffef199ededccec6 100644 (file)
@@ -254,9 +254,9 @@ void libssl_set_ticket_key_callback_data(SSL_CTX* ctx, void* data)
 }
 
 #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) {
@@ -300,7 +300,7 @@ static long libssl_server_name_callback(SSL* ssl, int* al, void* arg)
   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) {
@@ -680,7 +680,7 @@ void OpenSSLTLSTicketKeysRing::loadTicketsKeys(const std::string& keyFile)
   file.close();
 }
 
-void OpenSSLTLSTicketKeysRing::rotateTicketsKey(time_t now)
+void OpenSSLTLSTicketKeysRing::rotateTicketsKey(time_t /* now */)
 {
   auto newKey = std::make_shared<OpenSSLTLSTicketKey>();
   addKey(newKey);
index c82c93a047ad2be591e4ea64f6d180a235dab675..a0fb5892d3061c91cdcb9295cc6240f5cfd35840 100644 (file)
@@ -217,22 +217,22 @@ void BaseLua4::prepareContext() {
   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) {
index 5665bdbbd04c05f856c4af60396aa9c6eb32f284..639653fede220b89d8f15361cb7a6ec25aacc10f 100644 (file)
@@ -301,7 +301,6 @@ bool doCompare(const T& var, const std::string& res, const C& cmp)
 }
 }
 
-
 static std::string getGeo(const std::string& ip, GeoIPInterface::GeoIPQueryAttribute qa)
 {
   static bool initialized;
@@ -548,18 +547,41 @@ static vector<string> convComboAddressListToString(const vector<ComboAddress>& i
   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;
@@ -596,6 +618,37 @@ typedef struct AuthLuaRecordContext
 
 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", []() {
@@ -832,34 +885,18 @@ static void setupLuaRecords(LuaContext& lua)
    *
    * @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) {
@@ -898,42 +935,11 @@ static void setupLuaRecords(LuaContext& lua)
   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
index c78a65dc9f1d7c9ee4a00aa973bb471ddcc5e76c..2fcace7e1799e5091d19a93cca4f6c5a4a23f7a2 100644 (file)
@@ -366,5 +366,4 @@ void CommunicatorClass::makeNotifySockets()
 void CommunicatorClass::notify(const DNSName &domain, const string &ip)
 {
   d_nq.add(domain, ip);
-  d_any_sem.post();
 }
index 5d45406f1e5c9e4a8b010cb1bb37e667adface44..c1e16b810c7a5db4fe66f15b3fd76599373a03df 100644 (file)
@@ -116,7 +116,7 @@ static string extractHostFromURL(const std::string& url)
   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));
@@ -198,7 +198,7 @@ void MiniCurl::setupURL(const std::string& str, const ComboAddress* rem, const C
   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));
index b28b4a2b0c7aeffecbfeb075813149e26f4836f4..4cfe6d4196cc7f70e69afc283c7cd8930e08f7fc 100644 (file)
@@ -1014,7 +1014,7 @@ bool isNonBlocking(int sock)
   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;
@@ -1159,7 +1159,7 @@ int getMACAddress(const ComboAddress& ca, char* dest, size_t destLen)
   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;
 }
@@ -1175,7 +1175,7 @@ string getMACAddress(const ComboAddress& ca)
   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");
@@ -1217,7 +1217,7 @@ uint64_t udpErrorStats(const std::string& str)
   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 = {
@@ -1545,7 +1545,7 @@ bool isSettingThreadCPUAffinitySupported()
 #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__
@@ -1613,7 +1613,7 @@ std::vector<ComboAddress> getResolvers(const std::string& resolvConfPath)
   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);
@@ -1627,7 +1627,7 @@ size_t getPipeBufferSize(int fd)
 #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())) {
index 1481e0a608f0b699acd66d1f307d552a757bc2e1..f47ed2c58b5e642cf05042db2ecc905c695f1cba 100644 (file)
@@ -171,7 +171,7 @@ try
     {
       // 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;
       }
@@ -191,11 +191,11 @@ try
 
     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
index 3bf755ed6eb5e0d196fe283803a739f9ccc5bf48..815e3fcaac6ab5cece06fbf60a61777cf6f17b27 100644 (file)
@@ -72,7 +72,7 @@ private:
   string tmp;
 };
 
-void NSECBitmap::toPacket(DNSPacketWriter& pw)
+void NSECBitmap::toPacket(DNSPacketWriter& pw) const
 {
   NSECBitmapGenerator nbg(pw);
   if (d_bitset) {
@@ -186,7 +186,7 @@ NSECRecordContent::NSECRecordContent(const string& content, const DNSName& zone)
   }
 }
 
-void NSECRecordContent::toPacket(DNSPacketWriter& pw)
+void NSECRecordContent::toPacket(DNSPacketWriter& pw) const
 {
   pw.xfrName(d_next);
   d_bitmap.toPacket(pw);
@@ -240,7 +240,7 @@ NSEC3RecordContent::NSEC3RecordContent(const string& content, const DNSName& zon
   }
 }
 
-void NSEC3RecordContent::toPacket(DNSPacketWriter& pw)
+void NSEC3RecordContent::toPacket(DNSPacketWriter& pw) const
 {
   pw.xfr8BitInt(d_algorithm);
   pw.xfr8BitInt(d_flags);
@@ -306,7 +306,7 @@ NSEC3PARAMRecordContent::NSEC3PARAMRecordContent(const string& content, const DN
   rtr.xfrHexBlob(d_salt);
 }
 
-void NSEC3PARAMRecordContent::toPacket(DNSPacketWriter& pw)
+void NSEC3PARAMRecordContent::toPacket(DNSPacketWriter& pw) const
 {
   pw.xfr8BitInt(d_algorithm);
         pw.xfr8BitInt(d_flags);
@@ -366,7 +366,7 @@ CSYNCRecordContent::CSYNCRecordContent(const string& content, const DNSName& zon
   }
 }
 
-void CSYNCRecordContent::toPacket(DNSPacketWriter& pw)
+void CSYNCRecordContent::toPacket(DNSPacketWriter& pw) const
 {
   pw.xfr32BitInt(d_serial);
   pw.xfr16BitInt(d_flags);
index f734089e9dd4035bf155d052e02450442a8131ea..a8ca7c0712626730620c2f3ebe15e5d975000e80 100644 (file)
@@ -1843,7 +1843,7 @@ int OpenSSLEDDSADNSCryptoKeyEngine::getBits() const
   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};
index a1e3c71afe04a757dddd861f40c94398c16cc3d1..5d603648c510cd45a9342f1e53bf235e205ae897 100644 (file)
@@ -129,7 +129,7 @@ bool PacketHandler::addCDNSKEY(DNSPacket& p, std::unique_ptr<DNSPacket>& r)
   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;
   }
@@ -140,7 +140,7 @@ bool PacketHandler::addCDNSKEY(DNSPacket& p, std::unique_ptr<DNSPacket>& r)
     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;
   }
@@ -177,7 +177,7 @@ bool PacketHandler::addDNSKEY(DNSPacket& p, std::unique_ptr<DNSPacket>& r)
     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;
@@ -221,7 +221,7 @@ bool PacketHandler::addCDS(DNSPacket& p, std::unique_ptr<DNSPacket>& r)
   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;
   }
@@ -235,7 +235,7 @@ bool PacketHandler::addCDS(DNSPacket& p, std::unique_ptr<DNSPacket>& r)
       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;
     }
@@ -265,7 +265,7 @@ bool PacketHandler::addNSEC3PARAM(const DNSPacket& p, std::unique_ptr<DNSPacket>
     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;
@@ -295,7 +295,7 @@ int PacketHandler::doChaosRequest(const DNSPacket& p, std::unique_ptr<DNSPacket>
       }
       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
@@ -309,7 +309,7 @@ int PacketHandler::doChaosRequest(const DNSPacket& p, std::unique_ptr<DNSPacket>
       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);
@@ -360,7 +360,7 @@ void PacketHandler::getBestDNAMESynth(DNSPacket& p, DNSName &target, vector<DNSZ
       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);
@@ -420,9 +420,9 @@ bool PacketHandler::getBestWildcard(DNSPacket& p, const DNSName &target, DNSName
           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);
             }
@@ -549,29 +549,40 @@ void PacketHandler::doAdditionalProcessing(DNSPacket& p, std::unique_ptr<DNSPack
     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));
     }
   }
 
@@ -679,7 +690,7 @@ void PacketHandler::emitNSEC(std::unique_ptr<DNSPacket>& r, const DNSName& name,
   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;
 
@@ -771,7 +782,7 @@ void PacketHandler::emitNSEC3(std::unique_ptr<DNSPacket>& r, const NSEC3PARAMRec
   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;
 
@@ -1583,9 +1594,9 @@ std::unique_ptr<DNSPacket> PacketHandler::doQuestion(DNSPacket& p)
           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);
               }
@@ -1627,7 +1638,7 @@ std::unique_ptr<DNSPacket> PacketHandler::doQuestion(DNSPacket& p)
           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;
       }
 
index eb30fbec3b0ac6fcf009c724ccbae664d1597e8c..cea44001b8fcb71c15d51686d8380be935450953 100644 (file)
@@ -1208,7 +1208,7 @@ static int editZone(const DNSName &zone, const PDNSColors& col) {
     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");
     }
@@ -1283,7 +1283,7 @@ static int editZone(const DNSName &zone, const PDNSColors& col) {
   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();
 
   }
@@ -1292,7 +1292,7 @@ static int editZone(const DNSName &zone, const PDNSColors& col) {
   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;
@@ -1310,7 +1310,7 @@ static int editZone(const DNSName &zone, const PDNSColors& col) {
           {
             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);
@@ -1322,7 +1322,7 @@ static int editZone(const DNSName &zone, const PDNSColors& col) {
             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;
@@ -2642,6 +2642,7 @@ try
     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;
@@ -2649,6 +2650,10 @@ try
 
   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;
@@ -3174,7 +3179,7 @@ try
   }
   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) == ".")
index 1d12e85afadea1fc8f6de5c38d8751de65cd4999..9269c9e5f8af125075595c5c7157c62d3a8ad1b9 100644 (file)
@@ -376,7 +376,7 @@ class Pkcs11Token {
       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];
@@ -386,7 +386,7 @@ class Pkcs11Token {
       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];
@@ -407,7 +407,7 @@ class Pkcs11Token {
             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();
@@ -419,13 +419,13 @@ class Pkcs11Token {
             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;
index 816fc47d0eeaa74fb29db154aba873953bb06f33..40b26617a90a3cf8571dede91a4a8db619a65b81 100644 (file)
@@ -54,6 +54,9 @@ rec MODULE-IDENTITY
     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 }
@@ -1212,6 +1215,22 @@ authrcode15Count OBJECT-TYPE
         "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
@@ -1404,7 +1423,9 @@ recGroup OBJECT-GROUP
         authrcode12Count,
         authrcode13Count,
         authrcode14Count,
-        authrcode15Count
+        authrcode15Count,
+        packetCacheContended,
+        packetCacheAcquired
     }
     STATUS current
     DESCRIPTION "Objects conformance group for PowerDNS Recursor"
index c82ff698da2d4a20c4f693f0064143dbf986bf5d..96c1c20359f31203404686391e532bdadbd64982 100644 (file)
@@ -202,7 +202,7 @@ void AggressiveNSECCache::prune(time_t now)
   }
 }
 
-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
@@ -268,7 +268,7 @@ bool AggressiveNSECCache::isSmallCoveringNSEC3(const DNSName& owner, const std::
   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;
@@ -342,15 +342,15 @@ void AggressiveNSECCache::insertNSEC(const DNSName& zone, const DNSName& owner,
     }
 
     /* 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;
       }
@@ -433,7 +433,7 @@ bool AggressiveNSECCache::getNSEC3(time_t now, std::shared_ptr<LockGuarded<Aggre
   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;
 
@@ -455,7 +455,7 @@ static void addToRRSet(const time_t now, std::vector<DNSRecord>& recordSet, std:
       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));
@@ -463,13 +463,13 @@ static void addToRRSet(const time_t now, std::vector<DNSRecord>& recordSet, std:
   }
 }
 
-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));
@@ -480,7 +480,7 @@ static void addRecordToRRSet(time_t now, const DNSName& owner, const QType& type
       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));
@@ -493,7 +493,7 @@ bool AggressiveNSECCache::synthesizeFromNSEC3Wildcard(time_t now, const DNSName&
   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);
@@ -502,11 +502,12 @@ bool AggressiveNSECCache::synthesizeFromNSEC3Wildcard(time_t now, const DNSName&
 
   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;
 }
 
@@ -515,7 +516,7 @@ bool AggressiveNSECCache::synthesizeFromNSECWildcard(time_t now, const DNSName&
   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);
@@ -523,14 +524,15 @@ bool AggressiveNSECCache::synthesizeFromNSECWildcard(time_t now, const DNSName&
   }
 
   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;
@@ -551,13 +553,13 @@ bool AggressiveNSECCache::getNSEC3Denial(time_t now, std::shared_ptr<LockGuarded
   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;
     }
@@ -565,7 +567,7 @@ bool AggressiveNSECCache::getNSEC3Denial(time_t now, std::shared_ptr<LockGuarded
     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
@@ -585,7 +587,7 @@ bool AggressiveNSECCache::getNSEC3Denial(time_t now, std::shared_ptr<LockGuarded
     ++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;
   }
 
@@ -599,7 +601,7 @@ bool AggressiveNSECCache::getNSEC3Denial(time_t now, std::shared_ptr<LockGuarded
     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;
@@ -608,7 +610,7 @@ bool AggressiveNSECCache::getNSEC3Denial(time_t now, std::shared_ptr<LockGuarded
       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
@@ -656,7 +658,7 @@ bool AggressiveNSECCache::getNSEC3Denial(time_t now, std::shared_ptr<LockGuarded
     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;
@@ -683,7 +685,7 @@ bool AggressiveNSECCache::getNSEC3Denial(time_t now, std::shared_ptr<LockGuarded
   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;
@@ -692,7 +694,7 @@ bool AggressiveNSECCache::getNSEC3Denial(time_t now, std::shared_ptr<LockGuarded
     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
@@ -708,7 +710,7 @@ bool AggressiveNSECCache::getNSEC3Denial(time_t now, std::shared_ptr<LockGuarded
       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);
     }
@@ -722,7 +724,7 @@ bool AggressiveNSECCache::getNSEC3Denial(time_t now, std::shared_ptr<LockGuarded
       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;
@@ -740,14 +742,14 @@ bool AggressiveNSECCache::getNSEC3Denial(time_t now, std::shared_ptr<LockGuarded
   }
 
   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);
@@ -787,7 +789,7 @@ bool AggressiveNSECCache::getDenial(time_t now, const DNSName& name, const QType
 
   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);
@@ -809,14 +811,14 @@ bool AggressiveNSECCache::getDenial(time_t now, const DNSName& name, const QType
     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;
@@ -839,9 +841,9 @@ bool AggressiveNSECCache::getDenial(time_t now, const DNSName& name, const QType
 
     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) {
@@ -876,10 +878,10 @@ bool AggressiveNSECCache::getDenial(time_t now, const DNSName& name, const QType
   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);
index 46fb4cba0e54ea945c9f1c2f47ec493e69809ecd..05a3eeb3a54465aaa0cdb29030a19e621638eabb 100644 (file)
@@ -53,7 +53,7 @@ public:
     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);
@@ -114,8 +114,8 @@ private:
 
     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;
@@ -144,7 +144,7 @@ private:
   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&);
 
index e8c86edb2fd9f584202f58fa85a2c39f73eb04e0..8f7e900b7e1da47677680bc49a040db5fd1cf4ce 100644 (file)
@@ -12,8 +12,8 @@ AC_CONFIG_HEADERS([config.h])
 
 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],
index cd433237a1b1005a7d5b1c57eb2138b2793fb610..4372face88d1af319212631323b974b0b3df1576 100644 (file)
@@ -1,6 +1,16 @@
 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
index 9a605e7ad4bc1f3d100ab5d93a49e43917181aa8..f30e8f1568186b0fd0f1f0849be07c47415f6302 100644 (file)
@@ -1,6 +1,16 @@
 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
index 1bbf0623bf8160a8958faa9f6ff5b6ef79334b3a..888633f8d4068b7acf840345190376689db549ba 100644 (file)
@@ -1,6 +1,16 @@
 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
diff --git a/pdns/recursordist/docs/changelog/4.9.rst b/pdns/recursordist/docs/changelog/4.9.rst
new file mode 100644 (file)
index 0000000..b0976cb
--- /dev/null
@@ -0,0 +1,199 @@
+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.
+
index 2db2f634bd3e60db7ab305f5bfba9c5bdfdb5380..56b0bd0e997580688cc9655290638e021a254d03 100644 (file)
@@ -6,6 +6,7 @@ The changelogs for the recursor are split between release trains.
 .. toctree::
     :maxdepth: 2
 
+    4.9
     4.8
     4.7
     4.6
index 7d1395ce01f8e1b3b0c4e317f9c9577207d0ee39..39d046538198f0c3e10600c26f9f620bed8a3c66 100644 (file)
@@ -33,11 +33,21 @@ An example of a configuration:
 
 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``
index 6e5d24616181c8095292ab26dc1fa35651ccac6a..3834a68eaf2bb5e26de9154f055e78b1176c678f 100644 (file)
@@ -15,21 +15,26 @@ See below for more information about the various caches.
 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.
@@ -37,6 +42,13 @@ If ``SO_REUSEPORT`` support is available and :ref:`setting-reuseport` is set to
 .. 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
 --------------------
 
@@ -74,6 +86,7 @@ For high load operation (thousands of queries/second), It is advised to either t
 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
@@ -84,6 +97,7 @@ Sample Linux command lines would be::
     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
@@ -97,6 +111,7 @@ When using FirewallD (Centos 7+ / Red Hat 7+ / Fedora 21+), connection tracking
 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
@@ -107,6 +122,7 @@ The settings can be made permanent by using the ``--permanent`` flag::
     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
diff --git a/pdns/recursordist/docs/security-advisories/powerdns-advisory-2023-02.rst b/pdns/recursordist/docs/security-advisories/powerdns-advisory-2023-02.rst
new file mode 100644 (file)
index 0000000..f2c4dcc
--- /dev/null
@@ -0,0 +1,28 @@
+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.
+
+
index bf7b41f6ec8fd0d64baa0f424ad8471e300e05cd..427b39904f738f6b6fbfbf78b38764a6ea55ca12 100644 (file)
@@ -42,12 +42,11 @@ In this case the address ``128.66.1.2`` is excluded from the addresses allowed a
 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
@@ -466,8 +465,7 @@ overloaded, but it will be at the cost of an increased latency.
 -  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:
 
@@ -1582,10 +1580,27 @@ If an answer containing an NSEC3 record with more iterations is received, its DN
 ``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``
@@ -1595,23 +1610,42 @@ Maximum number of seconds to cache an item in the packet cache, no matter what t
 
 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:
 
@@ -1771,11 +1805,16 @@ A typical value is 10. If the value is zero, this functionality is disabled.
 ``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:
 
index 5f5e2b6c07a5fc6ccbc356e1e61c70ae80ea5bd8..871186e6d3e7e0f58363f70c52f8131c26220990 100644 (file)
@@ -15,6 +15,25 @@ This is now resolved, but has the consequence that some metrics (in particular r
 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.
@@ -61,7 +80,6 @@ Additionally, the ``dump-edns`` command  now only lists IPs that have a not OK s
 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
 --------------
 
index 600aa14534429b41a7ef1280a7ce9f795f53daf1..5b264fcf69b6f2985ac39d8b5ba9a01e25ff924a 100644 (file)
@@ -50,7 +50,12 @@ struct EDNSExtendedError
     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;
index 2d2d201a50d59327cd8c277ddc53af219adf6692..cc46516dbf61104429bd3940b1efa66a92e63945 100644 (file)
@@ -564,7 +564,7 @@ void DNSFilterEngine::Policy::info(Logr::Priority prio, const std::shared_ptr<Lo
             "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;
@@ -572,15 +572,15 @@ DNSRecord DNSFilterEngine::Policy::getRecordFromCustom(const DNSName& qname, con
   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));
       }
     }
   }
@@ -607,15 +607,15 @@ std::vector<DNSRecord> DNSFilterEngine::Policy::getCustomRecords(const DNSName&
     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));
         }
       }
     }
@@ -681,7 +681,7 @@ std::vector<DNSRecord> DNSFilterEngine::Policy::getRecords(const DNSName& qname)
     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));
   }
 
@@ -692,7 +692,7 @@ void DNSFilterEngine::Zone::dumpNamedPolicy(FILE* fp, const DNSName& name, const
 {
   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());
   }
 }
 
@@ -779,7 +779,7 @@ void DNSFilterEngine::Zone::dumpAddrPolicy(FILE* fp, const Netmask& nm, const DN
 
   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());
   }
 }
 
index 224ee3672cb75d81a29e93dc265175b5099ab149..4d11af52ccd67df41fd18bbd822cbe872366c004 100644 (file)
@@ -108,7 +108,7 @@ public:
     {
     }
 
-    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)
     {
     }
@@ -178,7 +178,7 @@ public:
     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;
@@ -188,7 +188,7 @@ public:
     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
index 720fd4f5ee14819e8ebeb5764a4c5d132d23e362..39665b6ad266a350e3d10c5ccc5cde13fb207f1a 100644 (file)
 #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>
@@ -88,7 +90,7 @@ struct lazy_allocator
 #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();
     }
index 55959d177f34f7a13f9939ccd4f3e2011587ceb1..dea00b806f74bb916bbab3a56ad5178433610105 100644 (file)
@@ -170,10 +170,8 @@ private:
     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>&;
index 6358c5d84eae95920b77f4ef98859e68c21dd095..b35cfd0d943396db77b48c06bd30ee4134b3b8af 100644 (file)
@@ -134,7 +134,7 @@ void RecursorLua4::DNSQuestion::addRecord(uint16_t type, const std::string& cont
   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);
 }
 
@@ -156,13 +156,13 @@ struct DynMetric
 
 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; });
@@ -274,20 +274,20 @@ void RecursorLua4::postPrepareContext()
       }
       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;
     });
@@ -295,7 +295,7 @@ void RecursorLua4::postPrepareContext()
   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);
@@ -436,10 +436,10 @@ void RecursorLua4::postPrepareContext()
       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) {
@@ -1026,7 +1026,7 @@ bool pdns_ffi_param_add_record(pdns_ffi_param_t* ref, const char* name, uint16_t
     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;
@@ -1137,12 +1137,12 @@ bool pdns_postresolve_ffi_handle_get_record(pdns_postresolve_ffi_handle_t* ref,
       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();
     }
@@ -1166,10 +1166,10 @@ bool pdns_postresolve_ffi_handle_set_record(pdns_postresolve_ffi_handle_t* ref,
   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;
@@ -1195,10 +1195,10 @@ bool pdns_postresolve_ffi_handle_add_record(pdns_postresolve_ffi_handle_t* ref,
     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));
 
index 0d520669400c3957a9b2374b4252de5bc1221415..833ae7ffc1486db10ddb2c6694115fcd8cda85bc 100644 (file)
@@ -282,7 +282,7 @@ static void logIncomingResponse(const std::shared_ptr<std::vector<std::unique_pt
   }
 }
 
-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;
 
@@ -510,7 +510,7 @@ static LWResult::Result asyncresolve(const ComboAddress& ip, const DNSName& doma
         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) {
index fe8c1757ca9fe8166654dc0ba16522ebfeaf63aa..dbc5683f2964c87ff0fc92da2ef779ce76273624 100644 (file)
@@ -54,12 +54,15 @@ extern __thread void* t_mainStack;
 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()
 {
index 995104351a90df9f11a66932e41ac7db9563e6aa..57ac811e130015492ce1b6d1327ad17259eee45e 100644 (file)
@@ -295,7 +295,7 @@ void NegCache::prune(size_t maxEntries)
  *
  * \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) {
@@ -308,9 +308,6 @@ size_t NegCache::doDump(int fd, size_t maxCacheEntries)
   }
   fprintf(fp.get(), "; negcache dump follows\n;\n");
 
-  struct timeval now;
-  Utility::gettimeofday(&now, nullptr);
-
   size_t ret = 0;
 
   size_t shard = 0;
@@ -326,19 +323,19 @@ size_t NegCache::doDump(int fd, size_t maxCacheEntries)
     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());
       }
     }
   }
index 0d42afee1099384033f3ceb60fc67e70f8f0f129..90d64ee822fbb342e9b06b8ed53da14513209161 100644 (file)
@@ -100,7 +100,7 @@ public:
   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;
@@ -170,7 +170,5 @@ private:
   }
 
 public:
-  void preRemoval(MapCombo::LockedContent& map, const NegCacheEntry& entry)
-  {
-  }
+  void preRemoval(MapCombo::LockedContent& /* map */, const NegCacheEntry& /* entry */) {}
 };
index f2f064f2bef9df3e7bd0942165166fb5ecca1b43..e35fc699b002b67b9e4f4536c435c71388c93a9e 100644 (file)
@@ -40,7 +40,7 @@ namespace filesystem = boost::filesystem;
 
 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) {
index 64d56f43767f74a56f2b10a515eb1e78b35275ef..f6e0c6bb0303e9049eb894df638382b440ed3ade 100644 (file)
@@ -49,8 +49,8 @@ thread_local ProtobufServersInfo t_outgoingProtobufServers;
 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;
@@ -263,7 +263,7 @@ static void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t&);
 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)
 {
 
@@ -315,7 +315,7 @@ LWResult::Result asendto(const char* data, size_t len, int flags,
   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");
@@ -409,7 +409,7 @@ static void handleRPZCustom(const DNSRecord& spoofed, const QType& qtype, SyncRe
     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);
@@ -420,14 +420,18 @@ static void handleRPZCustom(const DNSRecord& spoofed, const QType& qtype, SyncRe
   }
 }
 
-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) {
@@ -618,16 +622,16 @@ static bool udrCheckUniqueDNSRecord(Logr::log_t nodlogger, const DNSName& dname,
   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;
     }
@@ -712,7 +716,7 @@ int getFakeAAAARecords(const DNSName& qname, ComboAddress prefix, vector<DNSReco
       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;
@@ -755,7 +759,7 @@ int getFakePTRRecords(const DNSName& qname, vector<DNSRecord>& ret)
   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"));
@@ -875,6 +879,20 @@ static void dumpTrace(const string& trace, const timeval& timev)
   // 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));
@@ -984,6 +1002,7 @@ void startDoResolve(void* 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());
@@ -1413,7 +1432,7 @@ void startDoResolve(void* p)
           continue;
         }
 
-        if (!addRecordToPacket(pw, *i, minTTL, dc->d_ttlCap, maxanswersize)) {
+        if (!addRecordToPacket(pw, *i, minTTL, dc->d_ttlCap, maxanswersize, seenAuthSOA)) {
           needCommit = false;
           break;
         }
@@ -1654,13 +1673,9 @@ void startDoResolve(void* p)
 #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,
@@ -1942,7 +1957,7 @@ bool checkForCacheHit(bool qnameParsed, unsigned int tag, const string& data,
                       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;
@@ -1950,10 +1965,10 @@ bool checkForCacheHit(bool qnameParsed, unsigned int tag, const string& data,
   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) {
@@ -1979,11 +1994,12 @@ bool checkForCacheHit(bool qnameParsed, unsigned int tag, const string& data,
 
     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
@@ -2306,7 +2322,7 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr
   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);
@@ -2749,35 +2765,40 @@ static void doResends(MT_t::waiters_t::iterator& iter, const std::shared_ptr<Pac
 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));
@@ -2799,10 +2820,18 @@ static void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t& var)
   }
   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)));
@@ -2810,14 +2839,16 @@ static void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t& var)
     }
   }
 
-  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
index ce8bfb034e79900e0b531ec8b89fa854bfe1aa8b..c384bd65b2d3b6f02f0c3506aafb21f4398c57b1 100644 (file)
@@ -283,7 +283,7 @@ static void rpzPrimary(LuaConfigItems& lci, luaConfigDelayedThreads& delayedThre
 
   size_t zoneIdx;
   std::string dumpFile;
-  std::shared_ptr<SOARecordContent> sr = nullptr;
+  std::shared_ptr<const SOARecordContent> sr = nullptr;
 
   try {
     std::string seedFile;
index a357de5eb5f16330a0d44f6b34f5c1f19558304e..29a18b00f61a452625d2ac5070f7fb8b130dcc1b 100644 (file)
@@ -126,7 +126,7 @@ extern GlobalStateHolder<LuaConfigItems> g_luaconfs;
 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&);
index 7a5beab8be526b35be0e4a295c6584083fe14947..36401172383a33da3466d858b75e8f32b3e6919d 100644 (file)
@@ -746,7 +746,6 @@ static void setupNODThread(Logr::log_t log)
     }
     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");
@@ -766,7 +765,6 @@ static void setupNODThread(Logr::log_t log)
     }
     std::thread t(nod::UniqueResponseDB::startHousekeepingThread, t_udrDBp, std::this_thread::get_id());
     t.detach();
-    g_udr_pbtag = ::arg()["unique-response-pb-tag"];
   }
 }
 
@@ -791,6 +789,8 @@ static void setupNODGlobal()
   // 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 */
 
@@ -832,7 +832,7 @@ static void usr2Handler(int)
   ::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;
@@ -987,13 +987,15 @@ static void doStats(void)
   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");
 
@@ -1007,7 +1009,8 @@ static void doStats(void)
   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: "
@@ -1034,7 +1037,10 @@ static void doStats(void)
                 "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()),
@@ -1356,7 +1362,7 @@ template ThreadTimes broadcastAccFunction(const std::function<ThreadTimes*()>& f
 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"));
@@ -1441,7 +1447,6 @@ static int serviceMain(int argc, char* argv[], Logr::log_t log)
   g_maxNSEC3Iterations = ::arg().asNum("nsec3-max-iterations");
 
   g_maxCacheEntries = ::arg().asNum("max-cache-entries");
-  g_maxPacketCacheEntries = ::arg().asNum("max-packetcache-entries");
 
   luaConfigDelayedThreads delayedLuaThreads;
   try {
@@ -1510,10 +1515,12 @@ static int serviceMain(int argc, char* argv[], Logr::log_t log)
   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");
@@ -2008,7 +2015,7 @@ static int serviceMain(int argc, char* argv[], Logr::log_t log)
   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;
 
@@ -2042,7 +2049,7 @@ static void handlePipeRequest(int fd, FDMultiplexer::funcparam_t& var)
   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 {
@@ -2137,14 +2144,6 @@ static void houseKeeping(void*)
     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]() {
@@ -2182,6 +2181,12 @@ static void houseKeeping(void*)
       });
     }
     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);
@@ -2360,11 +2365,6 @@ static void recursorThread()
       }
     }
 
-    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);
@@ -2692,9 +2692,10 @@ int main(int argc, char** argv)
     ::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();
@@ -2738,7 +2739,7 @@ int main(int argc, char** argv)
     ::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";
@@ -2758,8 +2759,11 @@ int main(int argc, char** argv)
     ::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") = "";
@@ -2807,7 +2811,10 @@ int main(int argc, char** argv)
     ::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";
 
@@ -3032,6 +3039,10 @@ int main(int argc, char** argv)
 
     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);
   }
@@ -3123,11 +3134,6 @@ string doTraceRegex(FDWrapper file, vector<string>::const_iterator begin, vector
   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;
@@ -3135,7 +3141,9 @@ struct WipeCacheResult wipeCaches(const DNSName& canon, bool subtree, uint16_t q
   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);
index 1a1c9ee63006433784eea535eb3adc66b9e9e7a9..72ded229e7dd92dbb097e118cdb23a9cbf6afc0e 100644 (file)
@@ -187,7 +187,7 @@ enum class PaddingMode
 
 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>;
 
index 3d544c1be404e1ae384f6bbc6c5492a4b0ff946f..e7ef18eb927eb0340eef3163dc72f87c31000833 100644 (file)
@@ -49,50 +49,77 @@ void pdns::ProtoZero::RecMessage::addRR(const DNSRecord& record, const std::set<
 
   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:
index 7ffce2acb184e15e209f853312f9181f1c5ae030..35519347618a12b8f9a1367c29bf769730d29eae 100644 (file)
@@ -167,6 +167,9 @@ static const oid rcode13AnswersOID[] = {RECURSOR_STATS_OID, 142};
 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
@@ -174,7 +177,7 @@ static std::unordered_map<oid, std::string> s_statsMap;
 /* 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)
@@ -201,7 +204,7 @@ static int handleCounter64Stats(netsnmp_mib_handler* handler,
   }
 }
 
-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)
@@ -401,6 +404,8 @@ RecursorSNMPAgent::RecursorSNMPAgent(const std::string& name, const std::string&
   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);
index fcb5c42fffaf585af041d2314bc46f329c10897e..3da26229019c327a2a49318ad94a328e1c9bbe83 100644 (file)
@@ -189,7 +189,7 @@ public:
   {
     d_fd = -1;
   }
-  bool handleTCPReadResult(int fd, ssize_t bytes)
+  bool handleTCPReadResult(int /* fd */, ssize_t bytes)
   {
     if (bytes == 0) {
       /* EOF */
@@ -858,7 +858,7 @@ static void TCPIOHandlerIO(int fd, FDMultiplexer::funcparam_t& var)
   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;
index 1177f66ebfaf3b76be8a15d60b45d185d508f7c7..2f2cbfabec4e8007138f919bc93d4142d34012b3 100644 (file)
@@ -48,7 +48,7 @@ struct ZoneData
   // 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;
@@ -105,7 +105,7 @@ void ZoneData::parseDRForCache(DNSRecord& dr)
       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});
     }
@@ -401,7 +401,7 @@ void ZoneData::ZoneToCache(const RecZoneToCache::Config& config)
     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;
index 2766c7cf5741e42f8faeb5c7778cd2589879b257..f2a7d628e78dc453ee7f19c6a96bbccd382ea683 100644 (file)
@@ -334,11 +334,6 @@ static uint64_t dumpAggressiveNSECCache(int fd)
   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));
@@ -406,17 +401,19 @@ static RecursorControlChannel::Answer doDumpToFile(int s, uint64_t* (*function)(
 }
 
 // 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 (...) {
   }
@@ -847,6 +844,7 @@ static string setMaxPacketCacheEntries(T begin, T end)
   }
   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) {
@@ -1078,46 +1076,6 @@ static uint64_t doGetCacheMisses()
   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
@@ -1306,10 +1264,12 @@ static void registerAllStats1()
   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; });
index 8756aecbfcb2d526f1675e99b08b176ed1a17cbc..184555ebd8e7b928e6042cce5de98e962163efc8 100644 (file)
 
 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;
 }
@@ -48,7 +114,7 @@ bool RecursorPacketCache::qrMatch(const packetCache_t::index<HashTag>::type::ite
   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
@@ -59,7 +125,7 @@ bool RecursorPacketCache::checkResponseMatches(std::pair<packetCache_t::index<Ha
     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;
@@ -77,8 +143,8 @@ bool RecursorPacketCache::checkResponseMatches(std::pair<packetCache_t::index<Ha
         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) {
@@ -91,70 +157,58 @@ bool RecursorPacketCache::checkResponseMatches(std::pair<packetCache_t::index<Ha
 
       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;
 
@@ -163,7 +217,7 @@ void RecursorPacketCache::insertResponsePacket(unsigned int tag, uint32_t qhash,
       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;
@@ -177,54 +231,67 @@ void RecursorPacketCache::insertResponsePacket(unsigned int tag, uint32_t qhash,
     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;
 }
index 45ba4298ee926ed05bb6097b669911786ab0bea1..5ff974fefdcef7820e358a61bbdf1c43d46a2fc2 100644 (file)
@@ -34,6 +34,8 @@
 
 #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:
@@ -57,44 +54,54 @@ 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,
@@ -129,24 +136,84 @@ private:
     }
   };
 
+  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 */)
+  {
+  }
 };
index 2bf5d556e999149ac8419db312aece30ccae5d42..4c95c052c55c00fe14425dafb93e7409ecd29e57 100644 (file)
@@ -62,30 +62,31 @@ MemRecursorCache::MemRecursorCache(size_t mapsCount) :
 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;
 }
@@ -94,12 +95,12 @@ size_t MemRecursorCache::ecsIndexSize()
 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!
       }
     }
@@ -139,51 +140,51 @@ static void updateDNSSECValidationStateFromCache(boost::optional<vState>& state,
   }
 }
 
-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;
   }
 
@@ -291,7 +292,7 @@ MemRecursorCache::cache_t::const_iterator MemRecursorCache::getEntryUsingECSInde
   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) {
@@ -345,7 +346,7 @@ time_t MemRecursorCache::fakeTTD(MemRecursorCache::OrderedTagIterator_t& entry,
   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;
@@ -354,32 +355,32 @@ time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qt, F
   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);
         }
@@ -395,9 +396,9 @@ time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qt, F
       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;
         }
@@ -408,18 +409,18 @@ time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qt, F
   }
 
   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;
         }
 
@@ -430,7 +431,7 @@ time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qt, F
 
         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;
@@ -448,7 +449,7 @@ time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qt, F
     }
   }
   // 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;
@@ -456,11 +457,11 @@ time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qt, F
     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;
       }
 
@@ -471,7 +472,7 @@ time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qt, F
 
       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;
@@ -530,12 +531,12 @@ bool MemRecursorCache::CacheEntry::shouldReplace(time_t now, bool auth, vState s
   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();
   }
@@ -544,10 +545,10 @@ void MemRecursorCache::replace(time_t now, const DNSName& qname, const QType qt,
   // 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;
   }
 
@@ -560,9 +561,9 @@ void MemRecursorCache::replace(time_t now, const DNSName& qname, const QType qt,
     /* 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);
     }
@@ -607,15 +608,15 @@ void MemRecursorCache::replace(time_t now, const DNSName& qname, const QType qt,
        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)
@@ -623,17 +624,17 @@ size_t MemRecursorCache::doWipeCache(const DNSName& name, bool sub, const 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;
@@ -641,12 +642,12 @@ size_t MemRecursorCache::doWipeCache(const DNSName& name, bool sub, const QType
     }
 
     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);
     }
@@ -687,26 +688,27 @@ size_t MemRecursorCache::doWipeCache(const DNSName& name, bool sub, const QType
 // 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;
   }
@@ -775,17 +777,17 @@ uint64_t MemRecursorCache::doDump(int fd, size_t maxCacheEntries)
 
   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) {
@@ -820,8 +822,8 @@ void MemRecursorCache::doPrune(size_t keep)
 
 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;
 }
 }
index 91102d99ae2e8fe66f57ab72043f542545d51b2f..ce37145f003ef178fb2fbd64dd27de70deef1c92 100644 (file)
@@ -67,9 +67,9 @@ public:
   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);
@@ -88,7 +88,7 @@ private:
     {
     }
 
-    typedef vector<std::shared_ptr<DNSRecordContent>> records_t;
+    typedef vector<std::shared_ptr<const DNSRecordContent>> records_t;
 
     bool isStale(time_t now) const
     {
@@ -110,7 +110,7 @@ private:
     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;
@@ -278,7 +278,7 @@ private:
   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&);
 
index 1d69a402bf2ef4137d90c92e400fcf0830e03fe5..721a8d2e7db42f44259556470773a6d4372cae06 100644 (file)
 #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)
@@ -34,14 +176,14 @@ 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;
@@ -87,7 +229,7 @@ static void makeNameToIPZone(SyncRes::domainmap_t& newMap,
   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);
 }
 
@@ -105,7 +247,7 @@ static void makeIPToNamesZone(SyncRes::domainmap_t& newMap,
 
   // 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);
index e68fed2ec08a8f6ddb09bd8c39a44fe863cbdef3..dafeee4daf9f93e91412dd20563613710fa90147 100644 (file)
@@ -32,6 +32,9 @@
 #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);
index 4af95fee50ed7bb97e8e19ed758b566a16821533..ba658b19c2be49bded83a19cda84c2a88632dc76 100644 (file)
 #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)
index 3455b9bcfea82a44309dce184adc210e6e753694..e766fd9490ada18d5ce4057b19dc635d67746f83 100644 (file)
  */
 #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.
@@ -36,9 +39,8 @@ static const char* const rootIps4[] = {
   "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.
@@ -53,4 +55,3 @@ static const char* const rootIps6[] = {
   "2001:500:9f::42", // l.root-servers.net.
   "2001:dc3::35" // m.root-servers.net.
 };
-static size_t const rootIps6Count = sizeof(rootIps6) / sizeof(*rootIps6);
index 16008f3b4621806d24044745937534c62dc32059..f81ef2fbce4e78f1ead98e8c84943c81bb816c6b 100644 (file)
@@ -124,7 +124,7 @@ static void RPZRecordToPolicy(const DNSRecord& dr, std::shared_ptr<DNSFilterEngi
     }
     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<<": ";
     }
   }
@@ -135,7 +135,7 @@ static void RPZRecordToPolicy(const DNSRecord& dr, std::shared_ptr<DNSFilterEngi
     }
     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<<": ";
     }
   }
@@ -194,7 +194,7 @@ static void RPZRecordToPolicy(const DNSRecord& dr, std::shared_ptr<DNSFilterEngi
   }
 }
 
-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));
@@ -216,7 +216,7 @@ static shared_ptr<SOARecordContent> loadRPZFromServer(Logr::log_t plogger, const
   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) {
@@ -286,9 +286,9 @@ static void setRPZZoneNewState(const std::string& zone, uint32_t serial, uint64_
 }
 
 // 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"));
@@ -381,7 +381,7 @@ static bool dumpZoneToDisk(Logr::log_t logger, const DNSName& zoneName, const st
   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;
@@ -450,7 +450,7 @@ void RPZIXFRTracker(const std::vector<ComboAddress>& primaries, const boost::opt
 
   for (;;) {
     DNSRecord dr;
-    dr.d_content = sr;
+    dr.setContent(sr);
 
     if (skipRefreshDelay) {
       skipRefreshDelay = false;
@@ -516,7 +516,7 @@ void RPZIXFRTracker(const std::vector<ComboAddress>& primaries, const boost::opt
       /* 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;
index fcb379cb4b209665015595236c60c4cb7018196c..8f37a0b4c0f7613ec3770ca1a0be5b17a904a6ad 100644 (file)
@@ -26,8 +26,8 @@
 
 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
 {
index 0c24565a3441e354ee5ba40bcce546a2d9941834..f7270474f1062bfc652320f4d706675904463d8d 100644 (file)
@@ -436,6 +436,7 @@ unsigned int SyncRes::s_minimumTTL;
 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;
@@ -865,7 +866,7 @@ bool SyncRes::doSpecialNamesResolve(const DNSName& qname, const QType qtype, con
     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);
     }
   }
@@ -1008,7 +1009,7 @@ bool SyncRes::doOOBResolve(const AuthDomain& domain, const DNSName& qname, const
   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);
@@ -1768,14 +1769,18 @@ int SyncRes::doResolve(const DNSName& qname, const QType qtype, vector<DNSRecord
         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;
@@ -1788,6 +1793,18 @@ int SyncRes::doResolve(const DNSName& qname, const QType qtype, vector<DNSRecord
   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
@@ -1801,15 +1818,20 @@ int SyncRes::doResolve(const DNSName& qname, const QType qtype, vector<DNSRecord
  */
 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;
@@ -2395,14 +2417,18 @@ static bool scanForCNAMELoop(const DNSName& name, const vector<DNSRecord>& recor
 
 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();
@@ -2480,7 +2506,7 @@ bool SyncRes::doCNAMECacheCheck(const DNSName& qname, const QType qtype, vector<
         }
       }
 
-      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;
@@ -2494,7 +2520,7 @@ bool SyncRes::doCNAMECacheCheck(const DNSName& qname, const QType qtype, vector<
         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);
@@ -2523,7 +2549,7 @@ bool SyncRes::doCNAMECacheCheck(const DNSName& qname, const QType qtype, vector<
           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) {
@@ -2599,7 +2625,7 @@ namespace
 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
@@ -2612,7 +2638,7 @@ 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)
@@ -2642,7 +2668,7 @@ static void reapRecordsForValidation(std::map<QType, CacheEntry>& entries, const
   }
 }
 
-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);
@@ -2732,7 +2758,7 @@ bool SyncRes::doCacheCheck(const DNSName& qname, const DNSName& authname, bool w
     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)) {
@@ -2754,13 +2780,13 @@ bool SyncRes::doCacheCheck(const DNSName& qname, const DNSName& authname, bool w
           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"};
           }
         }
       }
@@ -2786,7 +2812,7 @@ bool SyncRes::doCacheCheck(const DNSName& qname, const DNSName& authname, bool w
           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;
         }
@@ -2823,7 +2849,7 @@ bool SyncRes::doCacheCheck(const DNSName& qname, const DNSName& authname, bool w
 
   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();
@@ -2891,7 +2917,7 @@ bool SyncRes::doCacheCheck(const DNSName& qname, const DNSName& authname, bool w
 
     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;
@@ -2919,7 +2945,7 @@ bool SyncRes::doCacheCheck(const DNSName& qname, const DNSName& authname, bool w
       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);
@@ -2948,7 +2974,7 @@ bool SyncRes::doCacheCheck(const DNSName& qname, const DNSName& authname, bool w
     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;
     }
@@ -3033,7 +3059,7 @@ vector<ComboAddress> SyncRes::shuffleForwardSpeed(const DNSName& qname, const ve
   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) {
@@ -3065,14 +3091,14 @@ static void harvestNXRecords(const vector<DNSRecord>& records, NegCache::NegCach
       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));
           }
@@ -3109,7 +3135,7 @@ static cspmap_t harvestCSPFromNE(const NegCache::NegCacheEntry& ne)
     }
   }
   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;
 }
@@ -3303,7 +3329,7 @@ bool SyncRes::nameserverIPBlockedByRPZ(const DNSFilterEngine& dfe, const ComboAd
   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;
 
@@ -3413,7 +3439,7 @@ bool SyncRes::validationEnabled() const
   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) {
@@ -3428,7 +3454,7 @@ uint32_t SyncRes::computeLowestTTD(const std::vector<DNSRecord>& records, const
     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));
       }
@@ -3442,7 +3468,7 @@ uint32_t SyncRes::computeLowestTTD(const std::vector<DNSRecord>& records, const
     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));
         }
@@ -3738,7 +3764,7 @@ vState SyncRes::getValidationStatus(const DNSName& name, bool wouldBeValid, bool
   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()) {
@@ -3849,7 +3875,7 @@ vState SyncRes::getDNSKeys(const DNSName& signer, skeyset_t& keys, bool& servFai
   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()) {
@@ -3945,7 +3971,7 @@ vState SyncRes::validateRecordsWithSigs(unsigned int depth, const string& prefix
 
   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);
@@ -4086,7 +4112,7 @@ void SyncRes::sanitizeRecords(const std::string& prefix, LWResult& lwr, const DN
     }
 
     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;
     }
@@ -4096,20 +4122,20 @@ void SyncRes::sanitizeRecords(const std::string& prefix, LWResult& lwr, const DN
       /* 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;
     }
@@ -4124,20 +4150,20 @@ void SyncRes::sanitizeRecords(const std::string& prefix, LWResult& lwr, const DN
 
     /* 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;
       }
@@ -4158,7 +4184,7 @@ void SyncRes::sanitizeRecords(const std::string& prefix, LWResult& lwr, const DN
        * 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;
     }
@@ -4168,7 +4194,7 @@ void SyncRes::sanitizeRecords(const std::string& prefix, LWResult& lwr, const DN
        * 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;
     }
@@ -4179,13 +4205,13 @@ void SyncRes::sanitizeRecords(const std::string& prefix, LWResult& lwr, const DN
 
     /* 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;
     }
@@ -4282,9 +4308,9 @@ RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, const string&
            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
@@ -4334,7 +4360,7 @@ RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, const string&
       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
 
@@ -4569,7 +4595,7 @@ RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, const string&
              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;
@@ -4789,7 +4815,7 @@ bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, co
     }
     // 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;
@@ -4852,7 +4878,7 @@ bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, co
     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)) {
@@ -4867,14 +4893,14 @@ bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, co
         }
       }
       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 */
@@ -4971,7 +4997,7 @@ bool SyncRes::processRecords(const std::string& prefix, const DNSName& qname, co
     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));
   }
 
@@ -5110,7 +5136,7 @@ bool SyncRes::doResolveAtThisIP(const std::string& prefix, const DNSName& qname,
     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) {
@@ -5158,6 +5184,12 @@ bool SyncRes::doResolveAtThisIP(const std::string& prefix, const DNSName& qname,
   }
 
   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));
 
@@ -5172,7 +5204,7 @@ bool SyncRes::doResolveAtThisIP(const std::string& prefix, const DNSName& qname,
     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)++;
 
@@ -5189,9 +5221,6 @@ bool SyncRes::doResolveAtThisIP(const std::string& prefix, const DNSName& qname,
       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)++;
@@ -5284,7 +5313,7 @@ bool SyncRes::doResolveAtThisIP(const std::string& prefix, const DNSName& qname,
   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);
@@ -5298,7 +5327,9 @@ void SyncRes::handleNewTarget(const std::string& prefix, const DNSName& qname, c
     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;
@@ -5661,7 +5692,7 @@ int SyncRes::doResolveAt(NsSet& nameservers, DNSName auth, bool flawedNSSet, con
               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);
 
index 1b99c277f02c4955d38f303e4ffecd7f0b545d28..b271acfbfaf63a7cf8bcb02097ee6cf4c056d241 100644 (file)
@@ -518,6 +518,7 @@ public:
   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;
@@ -652,10 +653,10 @@ private:
   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);
@@ -666,9 +667,10 @@ private:
   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()
   {
@@ -762,7 +764,7 @@ struct PacketID
   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);
@@ -920,8 +922,6 @@ uint64_t* pleaseGetNsSpeedsSize();
 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);
index 3892d246d9fa818ce2ea0d55cab4487e55874e8c..f5424e608a76db4df2b159c2c583dbfe611b5ba3 100644 (file)
@@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec_nxdomain)
 
   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) {
@@ -147,7 +147,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec_nodata)
 
   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) {
@@ -233,7 +233,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec_nodata_wildcard)
 
   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) {
@@ -326,7 +326,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec_ancestor)
 
   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) {
@@ -440,7 +440,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec_wildcard_synthesis)
 
   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) {
@@ -557,7 +557,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_nxdomain)
 
   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) {
@@ -660,7 +660,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_nodata)
 
   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) {
@@ -747,7 +747,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_nodata_wildcard)
 
   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) {
@@ -852,7 +852,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_ancestor)
 
   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) {
@@ -972,7 +972,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_wildcard_synthesis)
 
   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) {
@@ -1087,18 +1087,18 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec_wiping)
   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);
 
@@ -1136,12 +1136,12 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec_pruning)
   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);
@@ -1153,7 +1153,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec_pruning)
   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);
 
@@ -1197,18 +1197,18 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec_dump)
   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);
 
@@ -1258,7 +1258,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_rollover)
   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);
@@ -1289,7 +1289,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_rollover)
     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);
 
@@ -1318,7 +1318,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_rollover)
     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);
 
@@ -1348,7 +1348,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_rollover)
     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);
 
@@ -1378,7 +1378,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec_ancestor_cases)
   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);
@@ -1401,7 +1401,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec_ancestor_cases)
       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);
 
@@ -1434,7 +1434,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec_ancestor_cases)
       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);
 
@@ -1466,7 +1466,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec_ancestor_cases)
       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);
 
@@ -1504,7 +1504,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec_ancestor_cases)
         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);
 
@@ -1523,7 +1523,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec_ancestor_cases)
         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);
 
@@ -1561,7 +1561,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_ancestor_cases)
   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);
@@ -1593,7 +1593,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_ancestor_cases)
       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);
 
@@ -1632,7 +1632,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_ancestor_cases)
       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);
 
@@ -1670,7 +1670,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_ancestor_cases)
       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);
 
@@ -1717,7 +1717,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_ancestor_cases)
         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);
 
@@ -1745,7 +1745,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_ancestor_cases)
         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);
 
@@ -1773,7 +1773,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_ancestor_cases)
         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);
 
@@ -1822,7 +1822,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_ancestor_cases)
         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);
 
@@ -1850,7 +1850,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_ancestor_cases)
         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);
 
@@ -1878,7 +1878,7 @@ BOOST_AUTO_TEST_CASE(test_aggressive_nsec3_ancestor_cases)
         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);
 
index 9b0ff1fe19095dbea1c3beb347ace5401bd7f674..ac033238197ebdd1ce7859bdd77886d0f83e8794 100644 (file)
@@ -190,7 +190,7 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_basic)
     /* 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);
@@ -205,7 +205,7 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_basic)
     /* 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;
@@ -341,7 +341,7 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_local_data)
     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.");
   }
@@ -359,7 +359,7 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_local_data)
         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");
       }
@@ -367,7 +367,7 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_local_data)
         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");
       }
@@ -379,7 +379,7 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_local_data)
       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.");
     }
@@ -408,7 +408,7 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_local_data)
         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");
       }
@@ -420,7 +420,7 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_local_data)
       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.");
     }
@@ -460,14 +460,14 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_local_data_netmask)
     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");
   }
@@ -481,7 +481,7 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_local_data_netmask)
     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");
   }
@@ -507,7 +507,7 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_local_data_netmask)
     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");
   }
@@ -520,7 +520,7 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_local_data_netmask)
     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");
   }
@@ -540,7 +540,7 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_local_data_netmask)
     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");
   }
@@ -587,7 +587,7 @@ BOOST_AUTO_TEST_CASE(test_multiple_filter_policies)
     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.");
   }
@@ -602,7 +602,7 @@ BOOST_AUTO_TEST_CASE(test_multiple_filter_policies)
     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.");
   }
@@ -617,7 +617,7 @@ BOOST_AUTO_TEST_CASE(test_multiple_filter_policies)
     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.");
   }
@@ -632,7 +632,7 @@ BOOST_AUTO_TEST_CASE(test_multiple_filter_policies)
     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.");
   }
@@ -687,7 +687,7 @@ BOOST_AUTO_TEST_CASE(test_multiple_filter_policies_order)
     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.");
   }
@@ -709,7 +709,7 @@ BOOST_AUTO_TEST_CASE(test_multiple_filter_policies_order)
     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.");
   }
@@ -724,7 +724,7 @@ BOOST_AUTO_TEST_CASE(test_multiple_filter_policies_order)
     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.");
   }
@@ -746,7 +746,7 @@ BOOST_AUTO_TEST_CASE(test_multiple_filter_policies_order)
     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.");
   }
@@ -768,7 +768,7 @@ BOOST_AUTO_TEST_CASE(test_multiple_filter_policies_order)
     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.");
   }
@@ -790,7 +790,7 @@ BOOST_AUTO_TEST_CASE(test_multiple_filter_policies_order)
     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.");
   }
@@ -806,7 +806,7 @@ BOOST_AUTO_TEST_CASE(test_multiple_filter_policies_order)
     /* 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);
@@ -815,7 +815,7 @@ BOOST_AUTO_TEST_CASE(test_multiple_filter_policies_order)
     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.");
   }
@@ -824,7 +824,7 @@ BOOST_AUTO_TEST_CASE(test_multiple_filter_policies_order)
     /* 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);
index 246924298c98b12357f70a4b4f2a8f19b83e7b3b..dd716cae0e5ccca5e590840c71d811627e93d860 100644 (file)
@@ -91,7 +91,7 @@ BOOST_AUTO_TEST_CASE(test_MtaskerException)
 
 #else
 
-static void willThrow(void* p)
+static void willThrow(void* /* p */)
 {
   throw std::runtime_error("Help!");
 }
index e050097ec1da85f912d7e69f6f2d9e8bf3302d14..96172d458faac144aa2ea88549b0b2d9f33dbb70 100644 (file)
@@ -15,13 +15,13 @@ static recordsAndSignatures genRecsAndSigs(const DNSName& name, const uint16_t q
   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);
   }
 
@@ -526,7 +526,7 @@ BOOST_AUTO_TEST_CASE(test_dumpToFile)
   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;
index 9748b55783d8d54947f88a4e2dd2788bb1a3a0de..d764570419401972eff1eb0918edd711fd3950d9 100644 (file)
@@ -9,7 +9,7 @@ using namespace nod;
 
 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)
 {
index 5e343384f8568e74730515b09a09f6a8215d8b44..e456d3f11681e48827834846c2cfd244890802e7 100644 (file)
@@ -17,7 +17,7 @@ static void simple(time_t now)
 
   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;
@@ -27,7 +27,7 @@ static void simple(time_t now)
   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;
 
@@ -85,7 +85,7 @@ static void simple(time_t now)
     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;
 
@@ -94,7 +94,7 @@ static void simple(time_t now)
     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;
@@ -233,7 +233,7 @@ static void simple(time_t now)
     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;
@@ -313,7 +313,7 @@ static void simple(time_t now)
     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;
 
@@ -391,7 +391,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheGhost)
 
   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);
@@ -404,7 +404,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheGhost)
   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);
@@ -434,7 +434,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheReplaceAuthByNonAuthMargin)
 
   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);
@@ -447,7 +447,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheReplaceAuthByNonAuthMargin)
   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);
@@ -478,7 +478,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCache_ExpungingExpiredEntries)
   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);
@@ -495,7 +495,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCache_ExpungingExpiredEntries)
   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;
 
@@ -505,7 +505,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCache_ExpungingExpiredEntries)
   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;
 
@@ -572,7 +572,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCache_ExpungingValidEntries)
   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);
@@ -589,7 +589,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCache_ExpungingValidEntries)
   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;
 
@@ -599,7 +599,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCache_ExpungingValidEntries)
   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;
 
@@ -703,7 +703,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCache_ExpungingValidEntries)
     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);
@@ -753,7 +753,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheECSIndex)
   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");
@@ -765,7 +765,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheECSIndex)
   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;
 
@@ -774,7 +774,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheECSIndex)
   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;
 
@@ -912,7 +912,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCache_Wipe)
   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");
@@ -924,7 +924,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCache_Wipe)
   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;
 
@@ -1000,7 +1000,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheTagged)
 
   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;
 
@@ -1010,7 +1010,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheTagged)
   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;
@@ -1021,7 +1021,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheTagged)
   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;
@@ -1136,7 +1136,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheTagged)
     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;
@@ -1147,7 +1147,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheTagged)
     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;
@@ -1158,7 +1158,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheTagged)
     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;
index 4a7aa30e78d0b34930678e9ce7bfc370d282412c..921c7d1f11c4e016f2921d306362e4caa155df04 100644 (file)
@@ -258,4 +258,48 @@ BOOST_FIXTURE_TEST_CASE(test_loading_etc_hosts, Fixture)
   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()
index a9058e15ae40424bd460bead274b180349765c73..f291661e90f1a4f99e3ba4934555ee03c015fbd6 100644 (file)
@@ -32,16 +32,16 @@ BaseLua4::~BaseLua4()
 {
 }
 
-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;
 }
@@ -58,11 +58,11 @@ void RecursorLua4::postLoad()
 {
 }
 
-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;
 }
@@ -96,22 +96,22 @@ bool primeHints(time_t now)
     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;
 }
 
@@ -273,14 +273,14 @@ void addRecordToLW(LWResult* res, const std::string& name, uint16_t type, const
 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;
       }
@@ -332,7 +332,7 @@ bool addRRSIG(const testkeysset_t& keys, std::vector<DNSRecord>& records, const
   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());
     }
   }
 
@@ -348,7 +348,7 @@ bool addRRSIG(const testkeysset_t& keys, std::vector<DNSRecord>& records, const
   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;
@@ -367,7 +367,7 @@ void addDNSKEY(const testkeysset_t& keys, const DNSName& signer, uint32_t ttl, s
   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);
 }
 
@@ -383,7 +383,7 @@ bool addDS(const DNSName& domain, uint32_t ttl, std::vector<DNSRecord>& records,
   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;
@@ -401,7 +401,7 @@ void addNSECRecordToLW(const DNSName& domain, const DNSName& next, const std::se
   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);
@@ -423,7 +423,7 @@ void addNSEC3RecordToLW(const DNSName& hashedName, const std::string& hashedNext
   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);
index e218e86c43749b67ee97ca21396b5c5504095158..9d1c19d420c8416c4a02c363935b144a0df6ae9a 100644 (file)
@@ -47,7 +47,7 @@ BOOST_AUTO_TEST_CASE(test_root_primed_ns)
 
   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) {
@@ -82,7 +82,7 @@ BOOST_AUTO_TEST_CASE(test_root_not_primed)
 
   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) {
@@ -118,7 +118,7 @@ BOOST_AUTO_TEST_CASE(test_root_not_primed_and_no_response)
      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;
   });
@@ -142,7 +142,7 @@ BOOST_AUTO_TEST_CASE(test_root_ns_poison_resistance)
   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);
@@ -207,7 +207,7 @@ BOOST_AUTO_TEST_CASE(test_root_primed_ns_update)
 
   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) {
@@ -262,7 +262,7 @@ static void test_edns_formerr_fallback_f(bool sample)
   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;
@@ -320,7 +320,7 @@ BOOST_AUTO_TEST_CASE(test_edns_formerr_but_edns_enabled)
   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++;
     }
@@ -365,7 +365,7 @@ BOOST_AUTO_TEST_CASE(test_meta_types)
   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;
     });
@@ -385,7 +385,7 @@ BOOST_AUTO_TEST_CASE(test_tc_fallback_to_tcp)
   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;
@@ -414,7 +414,7 @@ BOOST_AUTO_TEST_CASE(test_tc_over_tcp)
 
   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;
@@ -449,7 +449,7 @@ BOOST_AUTO_TEST_CASE(test_all_nss_down)
 
   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);
@@ -496,7 +496,7 @@ BOOST_AUTO_TEST_CASE(test_all_nss_network_error)
 
   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);
@@ -545,7 +545,7 @@ BOOST_AUTO_TEST_CASE(test_all_nss_send_tc_then_garbage_over_tcp)
 
   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);
@@ -591,7 +591,7 @@ BOOST_AUTO_TEST_CASE(test_all_nss_send_garbage_over_udp)
   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);
@@ -635,7 +635,7 @@ BOOST_AUTO_TEST_CASE(test_regular_ns_send_refused)
   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);
@@ -687,7 +687,7 @@ BOOST_AUTO_TEST_CASE(test_forward_ns_send_refused)
   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);
@@ -738,7 +738,7 @@ BOOST_AUTO_TEST_CASE(test_forward_ns_send_servfail)
   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);
@@ -781,7 +781,7 @@ BOOST_AUTO_TEST_CASE(test_only_one_ns_up_resolving_itself_with_glue)
 
   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) {
@@ -835,7 +835,7 @@ BOOST_AUTO_TEST_CASE(test_os_limit_errors)
 
   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);
@@ -892,7 +892,7 @@ BOOST_AUTO_TEST_CASE(test_glued_referral)
 
   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;
@@ -942,7 +942,7 @@ BOOST_AUTO_TEST_CASE(test_glueless_referral)
 
   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);
 
@@ -1011,7 +1011,7 @@ BOOST_AUTO_TEST_CASE(test_glueless_referral_aaaa_task)
 
   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);
 
@@ -1099,7 +1099,7 @@ BOOST_AUTO_TEST_CASE(test_edns_subnet_by_domain)
   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");
 
@@ -1159,7 +1159,7 @@ BOOST_AUTO_TEST_CASE(test_edns_subnet_by_addr)
   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);
 
@@ -1211,7 +1211,7 @@ BOOST_AUTO_TEST_CASE(test_ecs_use_requestor)
   // 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);
 
@@ -1255,7 +1255,7 @@ BOOST_AUTO_TEST_CASE(test_ecs_use_scope_zero)
   // 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);
 
@@ -1300,7 +1300,7 @@ BOOST_AUTO_TEST_CASE(test_ecs_honor_incoming_mask)
   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);
 
@@ -1345,7 +1345,7 @@ BOOST_AUTO_TEST_CASE(test_ecs_honor_incoming_mask_zero)
   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);
 
@@ -1385,7 +1385,7 @@ BOOST_AUTO_TEST_CASE(test_following_cname)
   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);
@@ -1430,7 +1430,7 @@ BOOST_AUTO_TEST_CASE(test_cname_nxdomain)
   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);
@@ -1488,7 +1488,7 @@ BOOST_AUTO_TEST_CASE(test_included_poisonous_cname)
   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);
@@ -1539,7 +1539,7 @@ BOOST_AUTO_TEST_CASE(test_cname_loop)
   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)) {
@@ -1592,7 +1592,7 @@ BOOST_AUTO_TEST_CASE(test_cname_long_loop)
   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)) {
@@ -1657,7 +1657,7 @@ BOOST_AUTO_TEST_CASE(test_cname_depth)
   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);
@@ -1694,7 +1694,7 @@ BOOST_AUTO_TEST_CASE(test_time_limit)
   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)) {
@@ -1750,7 +1750,7 @@ BOOST_AUTO_TEST_CASE(test_dname_processing)
 
   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)) {
@@ -1894,7 +1894,7 @@ BOOST_AUTO_TEST_CASE(test_dname_dnssec_secure)
 
   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.
@@ -2045,7 +2045,7 @@ BOOST_AUTO_TEST_CASE(test_dname_plus_ns_dnssec_secure)
 
   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) {
@@ -2152,7 +2152,7 @@ BOOST_AUTO_TEST_CASE(test_dname_dnssec_insecure)
 
   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)) {
@@ -2281,7 +2281,7 @@ BOOST_AUTO_TEST_CASE(test_dname_processing_no_CNAME)
 
   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)) {
@@ -2372,7 +2372,7 @@ BOOST_AUTO_TEST_CASE(test_glued_referral_child_ns_set_wrong)
 
   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;
index a20dfc489e7a7be82d0badcae96ebe65300f9b98..4353d843fc443656317f74d97b28f782b622db5c 100644 (file)
@@ -17,7 +17,7 @@ BOOST_AUTO_TEST_CASE(test_outgoing_v4_only)
   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);
@@ -70,7 +70,7 @@ BOOST_AUTO_TEST_CASE(test_outgoing_v4_only_no_A_in_delegation)
   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);
@@ -109,7 +109,7 @@ BOOST_AUTO_TEST_CASE(test_outgoing_v6_only_no_AAAA_in_delegation)
   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);
@@ -160,7 +160,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_skipped_cut_invalid_ds_denia
 
   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) {
@@ -291,7 +291,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_wrong_rrsig_fake_signer)
 
   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) {
@@ -406,7 +406,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_missing_soa)
 
   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) {
@@ -552,7 +552,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_missing_dnskey)
 
   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) {
@@ -682,7 +682,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_nxd_dnskey)
 
   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) {
@@ -812,7 +812,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_nxd_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) {
@@ -945,7 +945,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_loop)
 
   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) {
@@ -1075,7 +1075,7 @@ BOOST_AUTO_TEST_CASE(test_servestale)
 
   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++;
@@ -1213,7 +1213,7 @@ BOOST_AUTO_TEST_CASE(test_servestale_neg)
 
   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++;
@@ -1348,7 +1348,7 @@ BOOST_AUTO_TEST_CASE(test_servestale_neg_to_available)
   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++;
@@ -1491,7 +1491,7 @@ BOOST_AUTO_TEST_CASE(test_servestale_cname_to_nxdomain)
   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++;
@@ -1642,7 +1642,7 @@ BOOST_AUTO_TEST_CASE(test_servestale_immediateservfail)
 
   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()) {
@@ -1716,7 +1716,7 @@ BOOST_AUTO_TEST_CASE(test_glued_referral_additional_update)
   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;
@@ -1807,7 +1807,7 @@ BOOST_AUTO_TEST_CASE(test_glued_referral_additional_no_update_because_locked)
   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;
@@ -1897,7 +1897,7 @@ BOOST_AUTO_TEST_CASE(test_locked_nonauth_update_to_auth)
 
   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;
index af5259a0b3a79da2c6c398e30a375b1d8a45953e..8d4bb74b50d17b68a5ee49aef6ffb4c8748a1aba 100644 (file)
@@ -17,7 +17,7 @@ static void do_test_referral_depth(bool limited)
   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)) {
@@ -115,7 +115,7 @@ BOOST_AUTO_TEST_CASE(test_glueless_referral_loop)
   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)) {
@@ -181,7 +181,7 @@ BOOST_AUTO_TEST_CASE(test_glueless_referral_loop_with_nonresolving)
   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)) {
@@ -246,7 +246,7 @@ BOOST_AUTO_TEST_CASE(test_glueless_referral_with_non_resolving)
 
   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);
 
@@ -341,7 +341,7 @@ BOOST_AUTO_TEST_CASE(test_cname_qperq)
   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)) {
@@ -385,7 +385,7 @@ BOOST_AUTO_TEST_CASE(test_throttled_server)
   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);
@@ -471,7 +471,7 @@ BOOST_AUTO_TEST_CASE(test_dont_query_server)
   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);
@@ -515,7 +515,7 @@ BOOST_AUTO_TEST_CASE(test_root_nx_trust)
   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)) {
@@ -580,7 +580,7 @@ BOOST_AUTO_TEST_CASE(test_root_nx_trust_specific)
   /* 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)) {
@@ -642,7 +642,7 @@ BOOST_AUTO_TEST_CASE(test_root_nx_dont_trust)
   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)) {
@@ -705,7 +705,7 @@ BOOST_AUTO_TEST_CASE(test_rfc8020_nothing_underneath)
   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)) {
@@ -814,7 +814,7 @@ BOOST_AUTO_TEST_CASE(test_rfc8020_nothing_underneath_dnssec)
 
   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;
@@ -974,7 +974,7 @@ BOOST_AUTO_TEST_CASE(test_rfc8020_nodata)
   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)) {
@@ -1048,7 +1048,7 @@ BOOST_AUTO_TEST_CASE(test_rfc8020_nodata_bis)
   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)) {
@@ -1124,7 +1124,7 @@ BOOST_AUTO_TEST_CASE(test_dont_skip_negcache_for_variable_response)
   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");
 
@@ -1180,7 +1180,7 @@ BOOST_AUTO_TEST_CASE(test_ecs_cache_limit_allowed)
   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");
 
@@ -1219,7 +1219,7 @@ BOOST_AUTO_TEST_CASE(test_ecs_cache_limit_no_ttl_limit_allowed)
   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");
 
@@ -1258,7 +1258,7 @@ BOOST_AUTO_TEST_CASE(test_ecs_cache_ttllimit_allowed)
   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");
 
@@ -1298,7 +1298,7 @@ BOOST_AUTO_TEST_CASE(test_ecs_cache_ttllimit_and_scope_allowed)
   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");
 
@@ -1338,7 +1338,7 @@ BOOST_AUTO_TEST_CASE(test_ecs_cache_ttllimit_notallowed)
   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");
 
@@ -1372,7 +1372,7 @@ BOOST_AUTO_TEST_CASE(test_ns_speed)
 
   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);
@@ -1441,7 +1441,7 @@ BOOST_AUTO_TEST_CASE(test_flawed_nsset)
 
   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);
@@ -1462,7 +1462,7 @@ BOOST_AUTO_TEST_CASE(test_flawed_nsset)
   /* 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>());
@@ -1483,7 +1483,7 @@ BOOST_AUTO_TEST_CASE(test_completely_flawed_nsset)
   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) {
@@ -1519,7 +1519,7 @@ BOOST_AUTO_TEST_CASE(test_completely_flawed_big_nsset)
   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) {
@@ -1561,14 +1561,14 @@ BOOST_AUTO_TEST_CASE(test_cache_hit)
 
   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>());
@@ -1591,7 +1591,7 @@ BOOST_AUTO_TEST_CASE(test_no_rd)
 
   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;
   });
@@ -1613,7 +1613,7 @@ BOOST_AUTO_TEST_CASE(test_cache_min_max_ttl)
   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);
@@ -1671,7 +1671,7 @@ BOOST_AUTO_TEST_CASE(test_cache_min_max_ecs_ttl)
   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");
 
@@ -1735,7 +1735,7 @@ BOOST_AUTO_TEST_CASE(test_cache_expired_ttl)
 
   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);
@@ -1757,7 +1757,7 @@ BOOST_AUTO_TEST_CASE(test_cache_expired_ttl)
   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>());
@@ -1780,7 +1780,7 @@ BOOST_AUTO_TEST_CASE(test_cache_almost_expired_ttl)
 
   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);
@@ -1803,7 +1803,7 @@ BOOST_AUTO_TEST_CASE(test_cache_almost_expired_ttl)
   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>());
index 1fe09133de6bdbb1117f8757f7c392c6533e9dc3..7acdb4f4ca65ec4e7bf374774a7b13e85d8b77d9 100644 (file)
@@ -16,7 +16,7 @@ BOOST_AUTO_TEST_CASE(test_cache_auth)
      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);
@@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE(test_unauth_any)
 
   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);
@@ -86,9 +86,9 @@ static void test_no_data_f(bool qmin)
   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;
     });
@@ -121,7 +121,7 @@ BOOST_AUTO_TEST_CASE(test_extra_answers)
   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);
@@ -185,7 +185,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_extra_answers)
   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);
     }
@@ -245,7 +245,7 @@ BOOST_AUTO_TEST_CASE(test_skip_opt_any)
 
   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");
@@ -268,7 +268,7 @@ BOOST_AUTO_TEST_CASE(test_nodata_nsec_nodnssec)
 
   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 */
@@ -293,7 +293,7 @@ BOOST_AUTO_TEST_CASE(test_nodata_nsec_dnssec)
 
   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 */
@@ -318,7 +318,7 @@ BOOST_AUTO_TEST_CASE(test_nx_nsec_nodnssec)
 
   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 */
@@ -343,7 +343,7 @@ BOOST_AUTO_TEST_CASE(test_nx_nsec_dnssec)
 
   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 */
@@ -369,7 +369,7 @@ BOOST_AUTO_TEST_CASE(test_qclass_none)
   /* 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;
   });
@@ -391,7 +391,7 @@ BOOST_AUTO_TEST_CASE(test_answer_no_aa)
 
   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;
@@ -407,7 +407,7 @@ BOOST_AUTO_TEST_CASE(test_answer_no_aa)
   /* 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);
 }
 
@@ -421,7 +421,7 @@ BOOST_AUTO_TEST_CASE(test_special_types)
   /* {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;
@@ -461,7 +461,7 @@ BOOST_AUTO_TEST_CASE(test_special_names)
 
   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;
   });
@@ -584,7 +584,7 @@ BOOST_AUTO_TEST_CASE(test_nameserver_ipv4_rpz)
   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);
@@ -625,7 +625,7 @@ BOOST_AUTO_TEST_CASE(test_nameserver_ipv6_rpz)
   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);
@@ -667,7 +667,7 @@ BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz)
   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);
@@ -709,7 +709,7 @@ BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz_disabled)
   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);
@@ -764,7 +764,7 @@ BOOST_AUTO_TEST_CASE(test_forward_zone_nord)
 
   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);
@@ -823,7 +823,7 @@ BOOST_AUTO_TEST_CASE(test_forward_zone_rd)
   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) {
@@ -874,7 +874,7 @@ BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_nord)
 
   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);
@@ -932,7 +932,7 @@ BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd)
   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);
 
@@ -978,7 +978,7 @@ BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd_dnssec)
   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);
@@ -1049,7 +1049,7 @@ BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_nord_dnssec)
   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);
@@ -1153,7 +1153,7 @@ BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd_dnssec_bogus)
   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);
@@ -1221,7 +1221,7 @@ BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd_dnssec_nodata_bogus)
 
   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);
@@ -1279,12 +1279,12 @@ BOOST_AUTO_TEST_CASE(test_auth_zone_oob)
   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;
   });
@@ -1340,19 +1340,19 @@ BOOST_AUTO_TEST_CASE(test_auth_zone_oob_cname)
   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;
   });
@@ -1409,21 +1409,21 @@ BOOST_AUTO_TEST_CASE(test_auth_zone)
   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");
@@ -1458,21 +1458,21 @@ BOOST_AUTO_TEST_CASE(test_auth_zone_cname_lead_to_oob)
   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) {
@@ -1514,21 +1514,21 @@ BOOST_AUTO_TEST_CASE(test_auth_zone_oob_lead_to_outgoing_queryb)
   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) {
@@ -1570,21 +1570,21 @@ BOOST_AUTO_TEST_CASE(test_auth_zone_ds)
   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);
index 01b10fa549edd27925c4dfcb6d8179211af8e50f..3e02e501bc1287831880eba91167c8229d7aad87 100644 (file)
@@ -23,21 +23,21 @@ BOOST_AUTO_TEST_CASE(test_auth_zone_nodata)
   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;
@@ -69,14 +69,14 @@ BOOST_AUTO_TEST_CASE(test_auth_zone_nx)
   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;
@@ -111,21 +111,21 @@ BOOST_AUTO_TEST_CASE(test_auth_zone_delegation)
   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>();
@@ -143,7 +143,7 @@ BOOST_AUTO_TEST_CASE(test_auth_zone_delegation)
      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);
@@ -189,28 +189,28 @@ BOOST_AUTO_TEST_CASE(test_auth_zone_delegation_point)
   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) {
@@ -249,21 +249,21 @@ BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard)
   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;
@@ -297,28 +297,28 @@ BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard_with_ent)
   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;
@@ -354,21 +354,21 @@ BOOST_AUTO_TEST_CASE(test_auth_zone_wildcard_nodata)
   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;
@@ -400,21 +400,21 @@ BOOST_AUTO_TEST_CASE(test_auth_zone_cache_only)
   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");
@@ -456,7 +456,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_rrsig)
   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);
@@ -480,7 +480,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_csk)
 
   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) {
@@ -565,7 +565,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_root_validation_ksk_zsk)
 
   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) {
@@ -633,7 +633,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_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) {
@@ -709,7 +709,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_without_zone_flag)
 
   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) {
@@ -785,7 +785,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_revoked)
 
   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) {
@@ -868,7 +868,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_dnskey_doesnt_match_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 (domain == target && type == QType::NS) {
@@ -979,7 +979,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_rrsig_signed_with_unknown_dnskey)
 
   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) {
@@ -1046,7 +1046,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_rrsig)
 
   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) {
@@ -1121,7 +1121,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_no_rrsig_noaa)
 
   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) {
@@ -1210,7 +1210,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_algorithm)
 
   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) {
@@ -1290,7 +1290,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_insecure_unknown_ds_digest)
 
   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) {
@@ -1363,7 +1363,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_sig)
 
   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) {
@@ -1431,7 +1431,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_bad_algo)
 
   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) {
@@ -1502,7 +1502,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_unsigned_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++;
 
     DNSName auth = domain;
@@ -1583,7 +1583,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_unsigned_ds_direct)
 
   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;
index 1af1d8719665d6a79168973a13f7d4fa586d7199..bb893939f1b6518c889c3edc520c269914e0b570 100644 (file)
@@ -33,7 +33,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_various_algos)
 
   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;
@@ -129,7 +129,7 @@ static void testFixedPointInTime(time_t fixedNow)
 
   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;
@@ -254,7 +254,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_a_then_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;
@@ -357,7 +357,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_insecure_a_then_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;
@@ -463,7 +463,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_with_nta)
 
   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;
@@ -564,7 +564,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_with_nta)
 
   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) {
@@ -648,7 +648,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec)
 
   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) {
@@ -739,7 +739,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_nxdomain_nsec)
 
   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;
@@ -855,7 +855,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_wildcard)
 
   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) {
@@ -974,7 +974,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_wildcard_proof_before_rrsig)
 
   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) {
@@ -1089,7 +1089,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_nodata_nowildcard)
 
   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) {
@@ -1169,7 +1169,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_nodata_nowildcard)
 
   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) {
@@ -1260,7 +1260,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_nodata_nowildcard_duplicated_n
 
   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) {
@@ -1355,7 +1355,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_nodata_nowildcard_too_many_ite
 
   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) {
@@ -1448,7 +1448,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_wildcard)
 
   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) {
@@ -1570,7 +1570,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec3_wildcard_too_many_iterations)
 
   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) {
@@ -1685,7 +1685,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_nsec_wildcard_missing)
 
   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) {
@@ -1789,7 +1789,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_wildcard_expanded_onto_itself)
 
   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.");
@@ -1844,7 +1844,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_wildcard_expanded_onto_itself_nodata
 
   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.");
@@ -1898,7 +1898,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_wildcard_like_expanded_from_wildcard
 
   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.");
@@ -1963,7 +1963,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_incomplete_cache_zonecut_qm)
 
   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);
@@ -2096,7 +2096,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_servfail_ds)
 
   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;
@@ -2179,7 +2179,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_servfail_ds)
   }
 }
 
-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);
@@ -2207,7 +2207,7 @@ static void dnssec_secure_servfail_dnskey(DNSSECMode mode, vState expectedValida
 
   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;
@@ -2329,7 +2329,7 @@ static void dnssec_secure_servfail_dnskey_insecure(DNSSECMode mode, vState expec
 
   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;
index 9a335c6177434915f722e2ac863cba6c163d7b51..bae815c34d170ef69d809c9de906426deb29dca8 100644 (file)
@@ -27,7 +27,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_secure)
   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) {
@@ -146,7 +146,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_ds_sign_loop)
 
   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) {
@@ -265,7 +265,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_ds_denial_loop)
 
   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)) {
@@ -341,7 +341,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_ds_root)
 
   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) {
@@ -402,7 +402,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_dnskey_signed_child)
 
   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) {
@@ -510,7 +510,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_dnskey_unpublished)
 
   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) {
@@ -612,7 +612,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_dnskey_unpublished_nsec3)
 
   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) {
@@ -713,7 +713,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_no_ds_on_referral_insecure)
   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) {
@@ -823,7 +823,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_unsigned_nsec)
 
   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) {
@@ -911,7 +911,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_bogus_no_nsec)
 
   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) {
@@ -999,7 +999,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure)
 
   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) {
@@ -1111,7 +1111,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_optout)
 
   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) {
@@ -1228,7 +1228,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_nxd_optout)
 
   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) {
@@ -1338,7 +1338,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_direct_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) {
@@ -1404,7 +1404,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_insecure_direct_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) {
@@ -1468,7 +1468,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_skipped_cut)
 
   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) {
@@ -1593,7 +1593,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_secure_without_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) {
@@ -1692,7 +1692,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_broken_without_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) {
@@ -1794,7 +1794,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_broken_cname_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) {
@@ -1903,7 +1903,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_cname_for_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) {
index 9ee88d298e27afc2d19637a12a6b875bd5c112f9..df5fb0850aacd0b025bc8a30889cdaf9e6cdb417 100644 (file)
@@ -28,7 +28,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_ta_skipped_cut)
 
   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) {
@@ -153,7 +153,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_nodata)
 
   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) {
@@ -285,7 +285,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_cname)
 
   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) {
@@ -415,7 +415,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_cname_glue)
 
   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) {
@@ -537,7 +537,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_insecure_to_secure_cname)
 
   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) {
@@ -664,7 +664,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_secure_cname)
 
   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) {
@@ -760,7 +760,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_bogus_cname)
 
   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) {
@@ -856,7 +856,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_secure_cname)
 
   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) {
@@ -952,7 +952,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_to_insecure_cname)
 
   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) {
@@ -1073,7 +1073,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta)
 
   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) {
@@ -1169,7 +1169,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_insecure_ta_norrsig)
 
   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) {
@@ -1263,7 +1263,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_nta)
 
   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) {
@@ -1329,7 +1329,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_no_ta)
 
   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) {
@@ -1387,7 +1387,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_nodata)
 
   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) {
@@ -1448,7 +1448,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_insecure_missing_soa_on_nodata)
 
   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) {
@@ -1523,7 +1523,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_insecure_missing_soa_on_nxd)
 
   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) {
@@ -1599,7 +1599,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_bogus_nxdomain)
 
   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) {
@@ -1663,7 +1663,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_secure_to_insecure_cut_with_cname_at_apex)
 
   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) {
@@ -1802,7 +1802,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_cname_inside_secure_zone)
 
   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) {
index 8c3eb4b9246e19700e48b01ce16030ec8a062c5b..2026f607fb71dea6e4acbfa4cda4c33f363cdeca 100644 (file)
@@ -15,14 +15,14 @@ BOOST_AUTO_TEST_CASE(test_nsec_denial_nowrap)
   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();
@@ -37,7 +37,7 @@ BOOST_AUTO_TEST_CASE(test_nsec_denial_nowrap)
   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();
@@ -64,14 +64,14 @@ BOOST_AUTO_TEST_CASE(test_nsec_denial_wrap_case_1)
   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();
@@ -100,14 +100,14 @@ BOOST_AUTO_TEST_CASE(test_nsec_denial_wrap_case_2)
   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();
@@ -136,14 +136,14 @@ BOOST_AUTO_TEST_CASE(test_nsec_denial_only_one_nsec)
   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();
@@ -172,14 +172,14 @@ BOOST_AUTO_TEST_CASE(test_nsec_root_nxd_denial)
   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();
@@ -194,7 +194,7 @@ BOOST_AUTO_TEST_CASE(test_nsec_root_nxd_denial)
   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();
@@ -217,7 +217,7 @@ BOOST_AUTO_TEST_CASE(test_nsec_ancestor_nxqtype_denial)
   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.
@@ -227,7 +227,7 @@ BOOST_AUTO_TEST_CASE(test_nsec_ancestor_nxqtype_denial)
     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();
@@ -269,10 +269,10 @@ BOOST_AUTO_TEST_CASE(test_nsec_ds_denial_from_child)
   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();
@@ -300,7 +300,7 @@ BOOST_AUTO_TEST_CASE(test_nsec_insecure_delegation_denial)
   vector<DNSRecord> records;
 
   sortedRecords_t recordContents;
-  vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+  vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
 
   /*
    * RFC 5155 section 8.9:
@@ -315,7 +315,7 @@ BOOST_AUTO_TEST_CASE(test_nsec_insecure_delegation_denial)
     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();
@@ -342,7 +342,7 @@ BOOST_AUTO_TEST_CASE(test_nsec_insecure_delegation_denial_soa)
   vector<DNSRecord> records;
 
   sortedRecords_t recordContents;
-  vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+  vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
 
   /*
    * RFC 5155 section 8.9:
@@ -356,7 +356,7 @@ BOOST_AUTO_TEST_CASE(test_nsec_insecure_delegation_denial_soa)
     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();
@@ -382,10 +382,10 @@ BOOST_AUTO_TEST_CASE(test_nsec_nxqtype_cname)
   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();
@@ -411,10 +411,10 @@ BOOST_AUTO_TEST_CASE(test_nsec3_nxqtype_ds)
   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)));
 
@@ -441,10 +441,10 @@ BOOST_AUTO_TEST_CASE(test_nsec3_nxqtype_cname)
   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)));
 
@@ -470,10 +470,10 @@ BOOST_AUTO_TEST_CASE(test_nsec_nxdomain_denial_missing_wildcard)
   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();
@@ -498,10 +498,10 @@ BOOST_AUTO_TEST_CASE(test_nsec3_nxdomain_denial_missing_wildcard)
   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)));
 
@@ -516,7 +516,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_nxdomain_denial_missing_wildcard)
   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)));
 
@@ -538,11 +538,11 @@ BOOST_AUTO_TEST_CASE(test_nsec_expanded_wildcard_proof)
   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();
@@ -569,11 +569,11 @@ BOOST_AUTO_TEST_CASE(test_nsec_wildcard_with_cname)
   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();
@@ -588,7 +588,7 @@ BOOST_AUTO_TEST_CASE(test_nsec_wildcard_with_cname)
   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();
@@ -608,7 +608,7 @@ BOOST_AUTO_TEST_CASE(test_nsec_wildcard_with_cname)
   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();
@@ -635,11 +635,11 @@ BOOST_AUTO_TEST_CASE(test_nsec3_wildcard_with_cname)
   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)));
 
@@ -654,7 +654,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_wildcard_with_cname)
   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)));
 
@@ -667,7 +667,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_wildcard_with_cname)
   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)));
 
@@ -687,7 +687,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_wildcard_with_cname)
   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)));
 
@@ -713,10 +713,10 @@ BOOST_AUTO_TEST_CASE(test_nsec_ent_denial)
   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();
@@ -745,7 +745,7 @@ BOOST_AUTO_TEST_CASE(test_nsec_ent_denial)
   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();
@@ -772,7 +772,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_ancestor_nxqtype_denial)
   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.
@@ -781,7 +781,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_ancestor_nxqtype_denial)
     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)));
 
@@ -813,7 +813,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_ancestor_nxqtype_denial)
   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)));
 
@@ -826,7 +826,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_ancestor_nxqtype_denial)
   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)));
 
@@ -852,11 +852,11 @@ BOOST_AUTO_TEST_CASE(test_nsec3_denial_too_many_iterations)
   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)));
 
@@ -882,7 +882,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_insecure_delegation_denial)
   vector<DNSRecord> records;
 
   sortedRecords_t recordContents;
-  vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+  vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
 
   /*
    * RFC 5155 section 8.9:
@@ -897,7 +897,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_insecure_delegation_denial)
     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)));
 
@@ -924,7 +924,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_insecure_delegation_denial_soa)
   vector<DNSRecord> records;
 
   sortedRecords_t recordContents;
-  vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+  vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
 
   /*
    * RFC 5155 section 8.9:
@@ -938,7 +938,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_insecure_delegation_denial_soa)
     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)));
 
@@ -964,7 +964,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_ent_opt_out)
   vector<DNSRecord> records;
 
   sortedRecords_t recordContents;
-  vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+  vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
 
   /*
    * RFC 7129 section 5.1:
@@ -979,7 +979,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_ent_opt_out)
     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)));
 
@@ -995,7 +995,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_ent_opt_out)
   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)));
 
@@ -1028,7 +1028,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_rrsig_negcache_validity)
   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;
@@ -1096,7 +1096,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_rrsig_negcache_bogus_validity)
   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;
@@ -1168,7 +1168,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_rrsig_cache_validity)
   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;
@@ -1197,7 +1197,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_rrsig_cache_validity)
   /* 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);
@@ -1236,7 +1236,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_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 (type == QType::DS || type == QType::DNSKEY) {
@@ -1302,7 +1302,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_insecure)
 
   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) {
@@ -1368,7 +1368,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_bogus)
 
   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) {
@@ -1456,7 +1456,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cache_secure_any)
 
   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) {
index a16607bc9c3154882035129be47ec04119927ef8..5a2dfab2c52581333b86c920e99c2b4dbfffe7bf 100644 (file)
@@ -30,7 +30,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cname_cache_secure)
 
   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) {
@@ -105,7 +105,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cname_cache_insecure)
 
   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) {
@@ -178,7 +178,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_cname_cache_bogus)
 
   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) {
@@ -273,7 +273,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_additional_without_rrsig)
 
   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) {
@@ -357,7 +357,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_secure)
   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;
@@ -442,7 +442,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_secure_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) {
@@ -498,7 +498,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_insecure)
 
   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;
@@ -575,7 +575,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_from_negcache_bogus)
 
   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;
@@ -675,7 +675,7 @@ BOOST_AUTO_TEST_CASE(test_lowercase_outgoing)
   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)) {
@@ -715,7 +715,7 @@ BOOST_AUTO_TEST_CASE(test_lowercase_outgoing)
   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());
@@ -749,7 +749,7 @@ BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo)
   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) {
@@ -799,7 +799,7 @@ BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_all_sha)
   // 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) {
@@ -852,7 +852,7 @@ BOOST_AUTO_TEST_CASE(test_getDSRecords_multialgo_two_highest)
   // 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) {
@@ -889,7 +889,7 @@ BOOST_AUTO_TEST_CASE(test_cname_plus_authority_ns_ttl)
   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)) {
@@ -968,7 +968,7 @@ BOOST_AUTO_TEST_CASE(test_bogus_does_not_replace_secure_in_the_cache)
   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 */);
@@ -1040,7 +1040,7 @@ BOOST_AUTO_TEST_CASE(test_records_sanitization_general)
 
   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 */
@@ -1086,7 +1086,7 @@ BOOST_AUTO_TEST_CASE(test_records_sanitization_keep_relevant_additional_aaaa)
 
   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);
@@ -1120,7 +1120,7 @@ BOOST_AUTO_TEST_CASE(test_records_sanitization_keep_glue)
 
   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)) {
@@ -1178,7 +1178,7 @@ BOOST_AUTO_TEST_CASE(test_records_sanitization_keep_glue)
   /* 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)
@@ -1190,7 +1190,7 @@ 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);
@@ -1240,7 +1240,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_referral_on_ds_query_insecure)
 
   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")) {
@@ -1329,7 +1329,7 @@ BOOST_AUTO_TEST_CASE(test_dnssec_validation_referral_on_ds_query_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.isPartOf(DNSName("signed.ds-ignorant.com.")) && ip == ComboAddress("192.0.2.1:53")) {
index c5ca3ccc66ea4a88d26ce6385bc4d1951992a646..ae0cde21e1d5a7f5e74f10f00c629ec6bdb6af39 100644 (file)
@@ -162,7 +162,7 @@ static void fillZone(const DNSName& zonename, HttpResponse* resp)
       {"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)
@@ -385,7 +385,7 @@ static void apiServerSearchData(HttpRequest* req, HttpResponse* resp)
     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{
@@ -393,7 +393,7 @@ static void apiServerSearchData(HttpRequest* req, HttpResponse* resp)
         {"zone_id", zoneId},
         {"zone_name", zoneName},
         {"name", rr.d_name.toString()},
-        {"content", rr.d_content->getZoneRepresentation()}});
+        {"content", rr.getContent()->getZoneRepresentation()}});
     }
   }
   resp->setJsonBody(doc);
@@ -1070,7 +1070,15 @@ const std::map<std::string, MetricDefinition> MetricDefinitionStorage::d_metrics
 
   {"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,
index ae29350e3f61251a05d5f8b59335746cf1906db3..abdbff900754cbf9e65bbf25b9faae9fc250c510 100644 (file)
@@ -217,7 +217,7 @@ namespace pdns {
         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);
       }
 
@@ -287,14 +287,14 @@ bool Resolver::tryGetSOASerial(DNSName *domain, ComboAddress* remote, uint32_t *
   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);
index ffce117ad8609daaed32f5d134cd820a69fc3b43..ceeb2d3c6fd5c1e3b0b1df312285357e6b1e94c4 100644 (file)
@@ -125,7 +125,7 @@ uint PacketHandler::performUpdate(const string &msgPrefix, const DNSRecord *rr,
     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;
@@ -153,7 +153,7 @@ uint PacketHandler::performUpdate(const string &msgPrefix, const DNSRecord *rr,
         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);
@@ -168,9 +168,9 @@ uint PacketHandler::performUpdate(const string &msgPrefix, const DNSRecord *rr,
       } 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++;
           }
         }
@@ -192,7 +192,7 @@ uint PacketHandler::performUpdate(const string &msgPrefix, const DNSRecord *rr,
             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();
@@ -371,7 +371,7 @@ uint PacketHandler::performUpdate(const string &msgPrefix, const DNSRecord *rr,
       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
@@ -410,8 +410,8 @@ uint PacketHandler::performUpdate(const string &msgPrefix, const DNSRecord *rr,
           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);
@@ -956,7 +956,7 @@ int PacketHandler::processUpdate(DNSPacket& p) {
       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);
           }
         }
index 9470ef44308aaa53f38692b955ef797387afb25a..fa2335e54094aa0086e9042ce0db26fe5b84366f 100644 (file)
@@ -145,7 +145,7 @@ try
        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;
        }
     }
@@ -213,7 +213,7 @@ try
         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)
@@ -221,26 +221,26 @@ try
         ++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]<<" ";
@@ -254,14 +254,14 @@ try
       }
       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());
index 848c4b48ccf6096bbc91af28a6e56b05de7dac95..87b4f558e47161da6130c08cee1223ee807a8676 100644 (file)
@@ -124,12 +124,12 @@ static void printReply(const string& reply, bool showflags, bool hidesoadetails,
          << 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] << " "
@@ -138,7 +138,7 @@ static void printReply(const string& reply, bool showflags, bool hidesoadetails,
         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] "
@@ -150,7 +150,7 @@ static void printReply(const string& reply, bool showflags, bool hidesoadetails,
         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] << " "
@@ -158,7 +158,7 @@ static void printReply(const string& reply, bool showflags, bool hidesoadetails,
         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] << " "
@@ -167,7 +167,7 @@ static void printReply(const string& reply, bool showflags, bool hidesoadetails,
         continue;
       }
     }
-    cout << "\t" << i->first.d_content->getZoneRepresentation() << "\n";
+    cout << "\t" << i->first.getContent()->getZoneRepresentation() << "\n";
   }
 
   EDNSOpts edo;
index 3b85ae055b43abf2e915f1e761c90bf5aeb9d1ae..72f31a7d58096d06f8fef0f8be0530709a8a537f 100644 (file)
@@ -170,7 +170,7 @@ DNSZoneRecord makeEditedDNSZRFromSOAData(DNSSECKeeper& dk, const SOAData& sd, DN
   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;
index 0198686d5c24651e8e2e6840db54f88172ed9750..f740ae8bb7a8233fdc33215169bbebc076b54f96 100644 (file)
@@ -100,12 +100,12 @@ namespace {
 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
 }
 }
 
index e66856e103834cb692cdbbf30070d45ab3ff7b7f..cb97acc8fe493373de5cc5bade5d39d869ae2415 100644 (file)
@@ -168,7 +168,7 @@ std::shared_ptr<DNSRecordContent> LOCRecordContent::make(const string& content)
 }
 
 
-void LOCRecordContent::toPacket(DNSPacketWriter& pw)
+void LOCRecordContent::toPacket(DNSPacketWriter& pw) const
 {
   pw.xfr8BitInt(d_version);
   pw.xfr8BitInt(d_size);
index a60d12dfead3df9a670cc22e2d0745773f2966b4..e4a1ffc8d0ccdb2ccad2def627d0e234259447fe 100644 (file)
@@ -449,7 +449,7 @@ void CommunicatorClass::ixfrSuck(const DNSName& domain, const TSIGTriplet& tt, c
     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;
index f00bf6d6c96a2ed093c09730b05fa5ab9f2d699f..18a088ea435307a9f3b9c4e3d90f449dd08ff0be 100644 (file)
@@ -78,7 +78,7 @@ void SNMPAgent::handleSNMPQueryEvent(int fd)
   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)
index d4c6a3c638a7de4864e530138a4d50215f0cbf50..9c7b5264a1339556e5c702e17cf325913687f7e1 100644 (file)
@@ -53,7 +53,7 @@ template<typename C> void doRun(const C& cmd, int mseconds=100)
     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;
index c2c96ebea7b8bc23700726e832c099c21cf28d3c..85efc190659e1c07d7e07b0bca84bf3f1022efd0 100644 (file)
@@ -97,12 +97,12 @@ public:
       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;
   }
index e4c8f9edb50f669f79d6d6b25cf2cb2c77eac3cf..a2b493496edbe8a51b716f0014b254c0372a6b74 100644 (file)
@@ -13,6 +13,7 @@ StatNode::Stat StatNode::print(unsigned int depth, Stat newstat, bool silent) co
   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;
@@ -26,7 +27,8 @@ StatNode::Stat StatNode::print(unsigned int depth, Stat newstat, bool silent) co
       childstat.nxdomains<<" nxdomains, "<< 
       childstat.servfails<<" servfails, "<< 
       childstat.drops<<" drops, "<<
-      childstat.bytes<<" bytes"<<endl;
+      childstat.bytes<<" bytes, "<<
+      childstat.hits<<" hits"<<endl;
 
   newstat+=childstat;
 
@@ -48,7 +50,7 @@ void StatNode::visit(visitor_t visitor, Stat &newstat, unsigned int depth) const
 }
 
 
-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();
@@ -57,7 +59,7 @@ void StatNode::submit(const DNSName& domain, int rcode, unsigned int bytes, boos
   }
 
   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. -> 
@@ -67,7 +69,7 @@ void StatNode::submit(const DNSName& domain, int rcode, unsigned int bytes, boos
    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) 
@@ -96,18 +98,26 @@ void StatNode::submit(std::vector<string>::const_iterator end, std::vector<strin
     //    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()) {
@@ -122,6 +132,6 @@ void StatNode::submit(std::vector<string>::const_iterator end, std::vector<strin
     }
     //    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);
   }
 }
index 88b4a210aa7d1a63eb7fd7ee57208cc1e6da0a42..4f9590507e21bf0e13c2cf3bf97e8464454c575f 100644 (file)
@@ -30,45 +30,53 @@ public:
 
   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);
 };
index 27954eead18e5fcc63538d35a84beebb3daf15fe..ea17b7c12330455209130467317c1d9862206619 100644 (file)
@@ -56,7 +56,7 @@ try
 
   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)
index 3cb2aad8c7d382da706cb17fee482ca6d0618ce0..8f4d3212390140bdfa27f27e475b5fc1f3e1b4f9 100644 (file)
@@ -859,7 +859,7 @@ public:
 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;
index 7d9a4f54b5178b2f53b56500973b22fa50c49bab..3341b11392613b77163d529226b94cd4ab8a186e 100644 (file)
@@ -720,7 +720,7 @@ int TCPNameserver::doAXFR(const DNSName &target, std::unique_ptr<DNSPacket>& q,
         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);
 
@@ -730,10 +730,10 @@ int TCPNameserver::doAXFR(const DNSName &target, std::unique_ptr<DNSPacket>& q,
           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);
           }
         }
@@ -744,11 +744,11 @@ int TCPNameserver::doAXFR(const DNSName &target, std::unique_ptr<DNSPacket>& q,
           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);
             }
           }
@@ -762,7 +762,7 @@ int TCPNameserver::doAXFR(const DNSName &target, std::unique_ptr<DNSPacket>& q,
     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);
@@ -782,7 +782,7 @@ int TCPNameserver::doAXFR(const DNSName &target, std::unique_ptr<DNSPacket>& q,
       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);
     }
 
@@ -825,17 +825,17 @@ int TCPNameserver::doAXFR(const DNSName &target, std::unique_ptr<DNSPacket>& q,
     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;
@@ -858,7 +858,7 @@ int TCPNameserver::doAXFR(const DNSName &target, std::unique_ptr<DNSPacket>& q,
     }
   }
 
-  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
@@ -866,8 +866,12 @@ int TCPNameserver::doAXFR(const DNSName &target, std::unique_ptr<DNSPacket>& q,
       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;
@@ -876,13 +880,13 @@ int TCPNameserver::doAXFR(const DNSName &target, std::unique_ptr<DNSPacket>& q,
           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;
@@ -891,11 +895,13 @@ int TCPNameserver::doAXFR(const DNSName &target, std::unique_ptr<DNSPacket>& q,
           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));
     }
   }
 
@@ -987,9 +993,7 @@ send:
   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) {
@@ -1061,7 +1065,7 @@ send:
           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;
@@ -1095,7 +1099,7 @@ send:
       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;
@@ -1172,7 +1176,7 @@ int TCPNameserver::doIXFR(std::unique_ptr<DNSPacket>& q, int outsock)
     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]);
index 50de3b7ec0943bda08876f711f4d3fcaa4eb48e4..8436fca4402959bc24268079fc9f137847ab44a8 100644 (file)
@@ -36,7 +36,7 @@ static inline void addRecordToList(std::vector<DNSRecord>& records, const DNSNam
   rec.d_type = type;
   rec.d_ttl = ttl;
 
-  rec.d_content = getRecordContent(type, content);
+  rec.setContent(getRecordContent(type, content));
 
   records.push_back(rec);
 }
index 0001d1ee04f6fe4618f8ace6cd1317ff6de68fa6..43c1b900ddf649ced32610b3e02cf31ba71d130b 100644 (file)
@@ -1019,14 +1019,18 @@ BOOST_AUTO_TEST_CASE(test_getcommonlabels) {
   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()
index 37f97d29fe62204545aa6f32d541aad8cbd91994..05894f3343a3d5ebdf44712720345b458ab64336 100644 (file)
@@ -117,7 +117,8 @@ BOOST_AUTO_TEST_CASE(test_ageDNSPacket) {
   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++) {
@@ -127,14 +128,14 @@ BOOST_AUTO_TEST_CASE(test_ageDNSPacket) {
 
   /* 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;
 
index 5b931945eb1370b842380701b6cfabe7dbf53437..141cfc3f9eed67451e004d899b66824a20895b65 100644 (file)
@@ -697,7 +697,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_records_types) {
     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++) {
index 5a6bbde62b1d5b72015667dca4d4e821c79686bc..4c2b44d9bad648ea211a646fcb79da671a0ccf4a 100644 (file)
@@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE(test_MPlexer)
     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;
@@ -100,7 +100,7 @@ BOOST_AUTO_TEST_CASE(test_MPlexer)
     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;
@@ -243,12 +243,12 @@ BOOST_AUTO_TEST_CASE(test_MPlexer_ReadAndWrite)
 
     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;
index c3231c04860d78db367ba6b6736cf7acb484cf87..8dc1ac868baadbdcc5fdcff73885d04685cdaf6e 100644 (file)
@@ -85,7 +85,7 @@ static void checkTSIG(const DNSName& tsigName, const DNSName& tsigAlgo, const st
       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;
index 7fdd540229f7024a7a0cb8a586ea1976382fb32a..a057b196d59c16dd2a66a85df8469557a8b74779 100644 (file)
@@ -26,11 +26,12 @@ void PacketHandler::tkeyHandler(const DNSPacket& p, std::unique_ptr<DNSPacket>&
     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
@@ -107,7 +108,7 @@ void PacketHandler::tkeyHandler(const DNSPacket& p, std::unique_ptr<DNSPacket>&
   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));
 
@@ -116,7 +117,7 @@ void PacketHandler::tkeyHandler(const DNSPacket& p, std::unique_ptr<DNSPacket>&
   {
     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;
index a0f66998c2e1ee0af69634e650c51e728c6ef6d7..62dfbf6787a38f1c814df6e23fa9474fbd5342bb 100755 (executable)
@@ -78,8 +78,8 @@ function makeGraphs()
         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"
index de0471b73dde899b853c1ac6a9e4bdbda3ff7e78..05e7b2a3f6c25b8aa2d3fab16a368cab9cd609cf 100644 (file)
@@ -28,7 +28,7 @@ bool TSIGTCPVerifier::check(const string& data, const MOADNSParser& mdp)
     }
 
     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;
index cc7621b3738c213121d463a3fef9d9048cde86ac..6392adb25d49bb7a13bfdad04930177688fc2f63 100644 (file)
@@ -444,7 +444,7 @@ bool UeberBackend::getAuth(const DNSName &target, const QType& qtype, SOAData* s
         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;
 
@@ -480,7 +480,7 @@ bool UeberBackend::getSOAUncached(const DNSName &domain, SOAData &sd)
         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;
 
index b3e95ad51f4c79a1609f6b6effd3dad9d4c7d395..26c0782e1c53f379dafe91cc77f009d9a416efc3 100644 (file)
@@ -78,7 +78,7 @@ int Utility::timed_connect( Utility::sock_t sock,
 
 
 
-void Utility::setBindAny(int af, sock_t sock)
+void Utility::setBindAny([[maybe_unused]] int af, [[maybe_unused]] sock_t sock)
 {
   const int one = 1;
 
@@ -199,9 +199,9 @@ Utility::pid_t Utility::getpid( )
 
 
 // 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.
index b37cebaec19cf84caeea51307ffad1086015963f..af4f9d69af542b0dc064471283857a4c064b3af0 100644 (file)
@@ -30,9 +30,9 @@ static bool isRevokedKey(const DNSKEYRecordContent& key)
   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)) {
@@ -88,22 +88,22 @@ static bool nsecProvesENT(const DNSName& name, const DNSName& begin, const DNSNa
 
 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;
 }
@@ -139,7 +139,7 @@ bool denialProvesNoDelegation(const DNSName& zone, const std::vector<DNSRecord>&
         continue;
       }
 
-      const string h = getHashFromNSEC3(zone, nsec3, cache);
+      const string h = getHashFromNSEC3(zone, *nsec3, cache);
       if (h.empty()) {
         return false;
       }
@@ -163,16 +163,16 @@ bool denialProvesNoDelegation(const DNSName& zone, const std::vector<DNSRecord>&
    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;
@@ -180,19 +180,19 @@ static bool isWildcardExpanded(const DNSName& owner, const std::vector<std::shar
 
   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;
@@ -200,12 +200,12 @@ static bool isWildcardExpandedOntoItself(const DNSName& owner, const std::vector
 
   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;
 
@@ -228,17 +228,17 @@ DNSName getNSECOwnerName(const DNSName& initialOwner, const std::vector<std::sha
   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();
 }
 
@@ -251,7 +251,7 @@ static bool provesNoDataWildCard(const DNSName& qname, const uint16_t qtype, con
     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;
         }
@@ -262,7 +262,7 @@ static bool provesNoDataWildCard(const DNSName& qname, const uint16_t qtype, con
         }
 
         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;
         }
@@ -298,7 +298,7 @@ static bool provesNoWildCard(const DNSName& qname, const uint16_t qtype, const D
     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;
         }
@@ -347,7 +347,7 @@ static bool provesNSEC3NoWildCard(const DNSName& closestEncloser, uint16_t const
     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;
         }
@@ -357,7 +357,7 @@ static bool provesNSEC3NoWildCard(const DNSName& closestEncloser, uint16_t const
           continue;
         }
 
-        string h = getHashFromNSEC3(wildcard, nsec3, cache);
+        string h = getHashFromNSEC3(wildcard, *nsec3, cache);
         if (h.empty()) {
           return false;
         }
@@ -377,13 +377,13 @@ static bool provesNSEC3NoWildCard(const DNSName& closestEncloser, uint16_t const
              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;
           }
@@ -402,7 +402,7 @@ static bool provesNSEC3NoWildCard(const DNSName& closestEncloser, uint16_t const
   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)) {
@@ -440,7 +440,7 @@ dState matchesNSEC(const DNSName& name, uint16_t qtype, const DNSName& nsecOwner
     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
@@ -454,10 +454,10 @@ dState matchesNSEC(const DNSName& name, uint16_t qtype, const DNSName& nsecOwner
     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;
     }
@@ -499,7 +499,7 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16
           continue;
         }
 
-        auto nsec = std::dynamic_pointer_cast<NSECRecordContent>(r);
+        auto nsec = std::dynamic_pointer_cast<const NSECRecordContent>(r);
         if (!nsec) {
           continue;
         }
@@ -526,7 +526,7 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16
            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);
@@ -541,7 +541,7 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16
 
         /* 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;
           }
@@ -642,7 +642,7 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16
     } 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;
         }
@@ -663,7 +663,7 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16
           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;
@@ -693,13 +693,13 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16
              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;
           }
@@ -747,7 +747,7 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16
         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;
             }
@@ -758,7 +758,7 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16
               continue;
             }
 
-            string h = getHashFromNSEC3(closestEncloser, nsec3, cache);
+            string h = getHashFromNSEC3(closestEncloser, *nsec3, cache);
             if (h.empty()) {
               return dState::INSECURE;
             }
@@ -768,7 +768,7 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16
             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;
               }
@@ -831,11 +831,11 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16
         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;
             }
@@ -896,19 +896,19 @@ dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16
   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 {
@@ -917,16 +917,16 @@ static bool checkSignatureWithKey(const DNSName& qname, time_t now, const shared
        - 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) {
@@ -936,7 +936,7 @@ static bool checkSignatureWithKey(const DNSName& qname, time_t now, const shared
   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;
@@ -960,7 +960,7 @@ vState validateWithKeySet(time_t now, const DNSName& name, const sortedRecords_t
     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) {
@@ -971,10 +971,10 @@ vState validateWithKeySet(time_t now, const DNSName& name, const sortedRecords_t
       }
       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;
         }
       }
@@ -1023,7 +1023,7 @@ cspmap_t harvestCSPFromRecs(const vector<DNSRecord>& recs)
       }
     }
     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;
@@ -1053,7 +1053,7 @@ bool haveNegativeTrustAnchor(const map<DNSName,std::string>& negAnchors, const D
   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
@@ -1114,10 +1114,9 @@ vState validateDNSKeysAgainstDS(time_t now, const DNSName& zone, const dsmap_t&
       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;
@@ -1204,7 +1203,7 @@ bool isSupportedDS(const DSRecordContent& ds, const OptLog& log)
   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) {
index 3226c2c3d8a06c8876bc93da3197651955dc099a..1660d98eac449dc046a57165b6500aaf96795ab6 100644 (file)
@@ -56,7 +56,7 @@ public:
 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;
@@ -64,47 +64,47 @@ typedef std::set<DSRecordContent> dsmap_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;
   }
 
index 0688323ac275081a5dc3e54515bee4f6fd571a39..89cec85aa3b82548337a36d3d1403391ef52e95e 100644 (file)
@@ -25,7 +25,7 @@ void pdns::ZoneMD::readRecords(ZoneParserTNG& zpt)
     }
     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;
@@ -53,14 +53,14 @@ void pdns::ZoneMD::readRecord(const DNSRecord& record)
   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");
       }
@@ -68,7 +68,7 @@ void pdns::ZoneMD::readRecord(const DNSRecord& 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");
       }
@@ -80,7 +80,7 @@ void pdns::ZoneMD::readRecord(const DNSRecord& 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");
       }
@@ -92,7 +92,7 @@ void pdns::ZoneMD::readRecord(const DNSRecord& 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");
       }
@@ -103,7 +103,7 @@ void pdns::ZoneMD::readRecord(const DNSRecord& 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");
       }
@@ -130,7 +130,7 @@ void pdns::ZoneMD::readRecord(const DNSRecord& 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");
       }
@@ -138,7 +138,7 @@ void pdns::ZoneMD::readRecord(const DNSRecord& 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");
       }
@@ -150,7 +150,7 @@ void pdns::ZoneMD::readRecord(const DNSRecord& 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;
 }
 
@@ -218,7 +218,7 @@ void pdns::ZoneMD::verify(bool& validationDone, bool& validationOK)
     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;
         }
@@ -241,7 +241,7 @@ void pdns::ZoneMD::verify(bool& validationDone, bool& validationOK)
       // 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;
index acb402d2503bf18485aead8dfe5589c1249a984d..3f20d52eaceb475c5295a8f6a44b6435ea81f936 100644 (file)
@@ -59,21 +59,21 @@ public:
   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);
     }
@@ -98,14 +98,14 @@ public:
     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
   {
@@ -122,11 +122,11 @@ private:
     }
   };
 
-  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;
   };
 
@@ -136,10 +136,10 @@ private:
   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;
index d0472e77f4c7decc0bdb62b5628c835832420bbc..515439d7bb5790209afd12255f96fddfe1aa4932 100755 (executable)
@@ -237,7 +237,26 @@ else:
 # 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
@@ -255,12 +274,7 @@ for try_number in range(0, 10):
 
 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...")
@@ -297,11 +311,6 @@ finally:
     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)
index bbcdb103e11795b7cdcac5765de1920bbf044f72..e9df7c8ba7f4ffb0798c27f9cff2c9c11f25642e 100644 (file)
@@ -60,6 +60,7 @@ web3.example.org.            3600 IN A    {prefix}.103
 
 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' }})"
 
@@ -83,21 +84,21 @@ all.example.org.             3600 IN LUA  A     "all({{'1.2.3.4','4.3.2.1'}})"
 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')                                "
@@ -327,6 +328,33 @@ createforward6.example.org.                 3600 IN NS   ns2.example.org.
         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
@@ -371,7 +399,7 @@ createforward6.example.org.                 3600 IN NS   ns2.example.org.
         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 = []
@@ -392,6 +420,34 @@ createforward6.example.org.                 3600 IN NS   ns2.example.org.
         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')]
 
index 06f71609fdd1ae939251d1647587f2b14e0f8b78..dfc6ead966b6e629a105f4518f3d4187dae7f09b 100644 (file)
@@ -58,7 +58,6 @@ class DNSDistTest(AssertEqualDNSMessageMixin, unittest.TestCase):
     _toResponderQueue = Queue()
     _fromResponderQueue = Queue()
     _queueTimeout = 1
-    _dnsdistStartupDelay = 2.0
     _dnsdist = None
     _responsesCounter = {}
     _config_template = """
@@ -73,6 +72,8 @@ class DNSDistTest(AssertEqualDNSMessageMixin, unittest.TestCase):
     _checkConfigExpectedOutput = None
     _verboseMode = False
     _skipListeningOnCL = False
+    _alternateListeningAddr = None
+    _alternateListeningPort = None
     _backgroundThreads = {}
     _UDPResponder = None
     _TCPResponder = None
@@ -146,7 +147,10 @@ class DNSDistTest(AssertEqualDNSMessageMixin, unittest.TestCase):
         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} ***")
@@ -170,7 +174,7 @@ class DNSDistTest(AssertEqualDNSMessageMixin, unittest.TestCase):
             return
         try:
             p.terminate()
-            for count in range(10):
+            for count in range(20):
                 x = p.poll()
                 if x is not None:
                     break
index 7fd3da7a79ad65f19bd5771e351f92c6010afacc..edfdb669ed329d009c7ced3c48a9b9738dd3eeda 100644 (file)
@@ -3,6 +3,7 @@ nose>=1.3.7
 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
index bf8684183bb708ddb5e26629f22126414cfbdd9b..60b9e54bc2d6a99c092fa84920cc9977cb9daf5f 100644 (file)
@@ -41,6 +41,15 @@ class APITestsBase(DNSDistTest):
                         '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):
 
@@ -768,6 +777,14 @@ class TestWebConcurrentConnections(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
index fc1f6eb7d9a82319bee5aad6f84e48b1bde1b61c..1a110e483dad7ba7162a7bf2f0a3a4a149ebbf9c 100644 (file)
@@ -414,6 +414,54 @@ class TestAdvancedGetLocalAddressOnAnyBind(DNSDistTest):
         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 = """
index f8b1f14041e72953fe94fdbb19afb30cc26a9c5a..df54c74e381515c769566e5655e46fcdd867e0d7 100644 (file)
@@ -356,7 +356,7 @@ class TestBackendDiscovery(DNSDistTest):
             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
@@ -365,8 +365,8 @@ class TestBackendDiscovery(DNSDistTest):
             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 = {
index 15cc8dc08b5777008c3fe68228b9f792d4fbc2c5..c67b983558c7083e558760c8488c53c3a35995fe 100644 (file)
@@ -29,8 +29,6 @@ class DNSCryptTest(DNSDistTest):
     _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)
index 9fcb4b52977a1753bb349a955144519b39c6725c..61936de4411da5b0393c804a620e161d85501a73 100644 (file)
@@ -1173,6 +1173,8 @@ class TestDOHFrontendLimits(DNSDistDOHTest):
     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):
         """
@@ -1258,7 +1260,7 @@ class TestProtocols(DNSDistDOHTest):
         self.checkQueryEDNSWithoutECS(expectedQuery, receivedQuery)
         self.assertEqual(response, receivedResponse)
 
-class TestDOHWithPCKS12Cert(DNSDistDOHTest):
+class TestDOHWithPKCS12Cert(DNSDistDOHTest):
     _serverCert = 'server.p12'
     _pkcs12Password = 'passw0rd'
     _serverName = 'tls.tests.dnsdist.org'
@@ -1274,7 +1276,7 @@ class TestDOHWithPCKS12Cert(DNSDistDOHTest):
 
     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)
index 5850d954258ca06fadaed616bf75680796a5b467..d907b1135463a25b1c12d15d8ac0e75e17b2899e 100644 (file)
@@ -39,6 +39,14 @@ class TestRuleMetrics(DNSDistTest):
     _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'
index ff2ef630cc8441deb9028f259b927e88f1582081..cefe7d26c4c26658e0ab11ec41045bd2f7a7e59d 100644 (file)
@@ -393,6 +393,8 @@ class TestTLSFrontendLimits(DNSDistTest):
     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):
         """
diff --git a/regression-tests.nobackend/lmdb-metadata-leak/command b/regression-tests.nobackend/lmdb-metadata-leak/command
new file mode 100755 (executable)
index 0000000..c4d9d02
--- /dev/null
@@ -0,0 +1,41 @@
+#!/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
diff --git a/regression-tests.nobackend/lmdb-metadata-leak/description b/regression-tests.nobackend/lmdb-metadata-leak/description
new file mode 100644 (file)
index 0000000..99a9783
--- /dev/null
@@ -0,0 +1,2 @@
+This test verifies that, with the LMDB-backend, pdnsutil set-meta and delete-zone do not leave old unreachable metadata items lying around
+
diff --git a/regression-tests.nobackend/lmdb-metadata-leak/expected_result b/regression-tests.nobackend/lmdb-metadata-leak/expected_result
new file mode 100644 (file)
index 0000000..d1be72c
--- /dev/null
@@ -0,0 +1,32 @@
+=== 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
index 81e2dcd5161143abd1f719c8ab3833e9ade22dbf..0139d4987db3e9a62a3163f9ef05302e1032e8e8 100755 (executable)
@@ -8,4 +8,5 @@ for zone in `cat ../regression-tests/named.conf | grep 'zone ' | cut -f 2 -d \"`
 do
        ${MD5SUM} ../regression-tests/zones/$zone
 done
+${MD5SUM} ../modules/tinydnsbackend/data
 ${MD5SUM} ../modules/tinydnsbackend/data.cdb
index bba64c82c866ed37be25153547c4593014ea0194..71c0ebda7acb097eeca62f8458096845f76364af 100644 (file)
@@ -4,7 +4,7 @@ e5e3ee998d151fe194b98997eaa36c53  ../regression-tests/zones/test.dyndns
 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
@@ -15,4 +15,5 @@ a98864b315f16bcf49ce577426063c42  ../regression-tests/zones/cdnskey-cds-test.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
index 165208b7926aed4ab3b0d9073a3814acb8640975..cf883fb4ee1dfbfcbdd9b8e85fa3910853305d4e 100644 (file)
@@ -50,10 +50,10 @@ daemon=no
 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
index 4f5afe9d85890b50c8196ee090d7e3889d5c7f06..3c15fe9ada80db73090a25b6cd71493a575f60c2 100644 (file)
@@ -2,6 +2,7 @@ dnspython>=1.11
 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
index 305ee05ca9866e795b477eff036558fbb624908c..2ff833efcd58efff054d0686a5e6daecb08c3559 100644 (file)
@@ -46,6 +46,27 @@ class AggressiveNSECCacheBase(RecursorTest):
 
         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()
 
@@ -72,7 +93,7 @@ class AggressiveNSECCacheBase(RecursorTest):
         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'
@@ -110,7 +131,7 @@ class AggressiveNSECCacheNSEC(AggressiveNSECCacheBase):
         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()
@@ -137,7 +158,7 @@ class AggressiveNSECCacheNSEC(AggressiveNSECCacheBase):
         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')
@@ -152,7 +173,7 @@ class AggressiveNSECCacheNSEC(AggressiveNSECCacheBase):
         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)
@@ -168,7 +189,7 @@ class AggressiveNSECCacheNSEC(AggressiveNSECCacheBase):
         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()
@@ -282,7 +303,7 @@ class AggressiveNSECCacheNSEC3(AggressiveNSECCacheBase):
         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()
@@ -315,7 +336,7 @@ class AggressiveNSECCacheNSEC3(AggressiveNSECCacheBase):
         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')
@@ -328,7 +349,7 @@ class AggressiveNSECCacheNSEC3(AggressiveNSECCacheBase):
         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)
@@ -342,7 +363,7 @@ class AggressiveNSECCacheNSEC3(AggressiveNSECCacheBase):
         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()
index d619bc6547ef8a0799f1ea1a583c6391f8c813f4..d4e5e9d72b435ad9d85a63808a0b30f9c639bb3c 100644 (file)
@@ -23,10 +23,10 @@ daemon=no
 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
index 9ef8a42404a06c3bb142d88e345f337817e61a7c..222c9181c1621db4bb6b1b179f89895aa150818f 100644 (file)
@@ -579,6 +579,7 @@ class PDNSRandomTest(RecursorTest):
     function preresolve (dq)
       dq.rcode = pdns.NOERROR
       dq:addAnswer(pdns.TXT, pdnsrandom())
+      dq.variable = true
       return true
     end
     """
index 6ff0ea346ff6b5ac1977fbd51a6d56fdfa082c47..689f346b72285eb06b479c2b9d2c199ceaee94d9 100644 (file)
@@ -70,6 +70,7 @@ f 3600 IN CNAME f            ; CNAME loop: dirty trick to get a ServFail in an a
         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)
index 35b6039558be149ce85e8508ddd9a958fd42cdb1..ba8c102ddde4b97e407817d65d22cdcc976817c4 100644 (file)
@@ -21,6 +21,7 @@ class PacketCacheRecursorTest(RecursorTest):
     _apiKey = 'secretapikey'
     _config_template = """
     packetcache-ttl=10
+    packetcache-negative-ttl=8
     packetcache-servfail-ttl=5
     auth-zones=example=configs/%s/example.zone
     webserver=yes
@@ -46,6 +47,7 @@ f 3600 IN CNAME f            ; CNAME loop: dirty trick to get a ServFail in an a
         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)
@@ -67,6 +69,7 @@ f 3600 IN CNAME f            ; CNAME loop: dirty trick to get a ServFail in an a
         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)
@@ -140,13 +143,13 @@ f 3600 IN CNAME f            ; CNAME loop: dirty trick to get a ServFail in an a
         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)
@@ -165,8 +168,8 @@ f 3600 IN CNAME f            ; CNAME loop: dirty trick to get a ServFail in an a
         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:
index d940d45c6a07a4f35dfe1bf11d37788c536670ce..85268e447232533cd2b4595f29bbf35a2d9be8a9 100644 (file)
@@ -366,6 +366,7 @@ webserver-port=%d
 webserver-address=127.0.0.1
 webserver-password=%s
 api-key=%s
+disable-packetcache
 """ % (_confdir, _wsPort, _wsPassword, _apiKey)
     _xfrDone = 0
 
index 21254b4db272ee38b28e82b5fc36e04d6ff87129..cb1133641b3e8114101e74931a407c23fd6a929c 100644 (file)
@@ -138,4 +138,4 @@ extended-resolution-errors
         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'))
index 5b7b1b82ff554188fa867437a7440a7f4e2ad92c..6d54618ae641f7aa1465d00bf2c13b025072a56e 100644 (file)
@@ -22,10 +22,10 @@ daemon=no
 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
index 7e6f67d3525e798f0754fe6512f2c8a0884f2076..e75817b5204d216841b54f4bda279c6178d22d93 100755 (executable)
@@ -31,7 +31,7 @@ rm -f recursor.pid pdns_recursor.pid
 <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
index 0bb54176b7f5cbf2bd870c0e27b6452a2ff2c100..048b3b17db7fb93b5912288cb5435afb61cdf8e1 100644 (file)
@@ -3,3 +3,4 @@ real_result
 *.out
 start
 step.*
+verify-dnssec-zone/allow-missing
index d831426e482d7021db15e3d741336b8db272ae2f..09e9dfaeb3b430c40f9d1c22de5130241bd5a6fb 100644 (file)
@@ -1,3 +1,4 @@
+*.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
index 4aac677664f62e07278bb8e7bd95b43672a79a2b..6930c4ce25921e2eee4e4702b022296dbf30397b 100644 (file)
@@ -1,3 +1,7 @@
+*.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
@@ -5,7 +9,7 @@ delegated.dnssec-parent.com.    3600    IN      RRSIG   NSEC 13 3 3600 [expiry] [inception] [
 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. ...
index 8b9d290b3ba66a46ad95d541e7a57c87d4a2fdcd..15b81621793007e1212b467a9ed4edfa08ad3d5c 100644 (file)
@@ -1,3 +1,7 @@
+*.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.
index c4da9a3352cc32d80b657a21fe8995e91aad2406..ad6ce2201f5e813bf44fde8e6492b6fe7b7019a2 100644 (file)
@@ -1,3 +1,7 @@
+*.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.
index 96aff471d89f3fd7328265e8e81a896c54f35d85..680fef8692f4be0dbd23a23f217e26c3cafa272b 100644 (file)
@@ -2,7 +2,7 @@
 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
index 6a7cb568584a981e133865c83eaa1cb5a3a5a01a..c9444d0f6c7daa0bae122ae8b3df6162a6ede963 100644 (file)
@@ -1,5 +1,5 @@
-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     
diff --git a/regression-tests/tests/nsec-at-delegation/command b/regression-tests/tests/nsec-at-delegation/command
new file mode 100755 (executable)
index 0000000..58ee8e8
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+cleandig secure-delegated1.dnssec-parent.com A dnssec
diff --git a/regression-tests/tests/nsec-at-delegation/description b/regression-tests/tests/nsec-at-delegation/description
new file mode 100644 (file)
index 0000000..d59bcc5
--- /dev/null
@@ -0,0 +1 @@
+Check that we generate the right NSECs when the NSEC name is a delegation point.
diff --git a/regression-tests/tests/nsec-at-delegation/expected_result b/regression-tests/tests/nsec-at-delegation/expected_result
new file mode 100644 (file)
index 0000000..19f980e
--- /dev/null
@@ -0,0 +1,9 @@
+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
diff --git a/regression-tests/tests/nsec-at-delegation/expected_result.narrow b/regression-tests/tests/nsec-at-delegation/expected_result.narrow
new file mode 100644 (file)
index 0000000..dafbed6
--- /dev/null
@@ -0,0 +1,9 @@
+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
diff --git a/regression-tests/tests/nsec-at-delegation/expected_result.nsec3 b/regression-tests/tests/nsec-at-delegation/expected_result.nsec3
new file mode 100644 (file)
index 0000000..e65ad7a
--- /dev/null
@@ -0,0 +1,9 @@
+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
diff --git a/regression-tests/tests/nsec-at-delegation/expected_result.nsec3-optout b/regression-tests/tests/nsec-at-delegation/expected_result.nsec3-optout
new file mode 100644 (file)
index 0000000..aee66de
--- /dev/null
@@ -0,0 +1,9 @@
+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
diff --git a/regression-tests/tests/nsec-at-delegation/skip.nodnssec b/regression-tests/tests/nsec-at-delegation/skip.nodnssec
new file mode 100644 (file)
index 0000000..e69de29
index 0800ccf1eba52b999fa95af63ecd47020c0ea81a..f32469bbf744be7b290ce567a55d22fbbd8197c5 100644 (file)
@@ -25,3 +25,4 @@ insecure-delegated.ent.ent.auth-ent   IN      NS      ns.example.com.
 something1.auth-ent    IN      A       1.1.2.3
 insecure               IN      NS      ns.example.com.
 www                    IN      CNAME   www.insecure
+*                      IN      CNAME   secure-delegated
index 36f39a1e099891b2a197082cae93e1fa84454e58..4608c6dd3c641dba645de7ed2eeb940f5a77b9f3 100644 (file)
--- a/tasks.py
+++ b/tasks.py
@@ -46,6 +46,7 @@ auth_build_deps = [    # FIXME: perhaps we should be stealing these from the deb
     'ruby-dev',
     'sqlite3',
     'unixodbc-dev',
+    'cmake',
 ]
 rec_build_deps = [
     'libcap-dev',
@@ -108,6 +109,7 @@ auth_test_deps = [   # FIXME: we should be generating some of these from shlibde
     'libsystemd0',
     'libyaml-cpp0.6',
     'libzmq3-dev',
+    'lmdb-utils',
     'prometheus',
     'ruby-bundler',
     'ruby-dev',
@@ -164,7 +166,8 @@ def install_libdecaf(c, product):
     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 '
@@ -301,9 +304,18 @@ def ci_docs_build_pdf(c):
 
 @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):
@@ -312,59 +324,122 @@ 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 = ''