]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Merge pull request #13387 from omoerbeek/rec-b-root-servers
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Thu, 16 Nov 2023 08:17:00 +0000 (09:17 +0100)
committerGitHub <noreply@github.com>
Thu, 16 Nov 2023 08:17:00 +0000 (09:17 +0100)
rec: Update new b-root-server.net addresses in built-in hints.

265 files changed:
.clang-tidy.full
.github/actions/spell-check/expect.txt
.github/scripts/clang-tidy.py
.github/scripts/git-filter.py
.github/scripts/helpers.py
.github/scripts/normalize_paths_in_compilation_database.py [deleted file]
.github/workflows/build-and-test-all.yml
.github/workflows/build-packages.yml
.github/workflows/codeql-analysis.yml
.github/workflows/misc-dailies.yml
.not-formatted
build-scripts/gh-actions-setup-inv
build-scripts/gh-actions-setup-inv-no-dist-upgrade
builder-support/dockerfiles/Dockerfile.recursor
builder-support/specs/dnsdist.spec
docs/backends/bind.rst
docs/backends/generic-sql.rst
docs/catalog.rst
docs/changelog/pre-4.0.rst
docs/dnssec/advice.rst
docs/dnssec/index.rst
docs/dnssec/intro.rst
docs/manpages/zone2sql.1.rst
docs/migration.rst
docs/secpoll.zone
docs/upgrading.rst
ext/lmdb-safe/lmdb-safe.cc
m4/ax_compare_version.m4 [new file with mode: 0644]
modules/bindbackend/bindbackend2.cc
modules/bindbackend/bindbackend2.hh
modules/bindbackend/binddnssec.cc
modules/geoipbackend/geoipbackend.cc
modules/gmysqlbackend/gmysqlbackend.cc
modules/godbcbackend/godbcbackend.cc
modules/gpgsqlbackend/gpgsqlbackend.cc
modules/gsqlite3backend/gsqlite3backend.cc
modules/ldapbackend/Makefile.am
modules/ldapbackend/OBJECTFILES
modules/ldapbackend/ldapbackend.hh
modules/ldapbackend/native.cc
modules/ldapbackend/primary.cc [moved from modules/ldapbackend/master.cc with 94% similarity]
modules/lmdbbackend/lmdbbackend.cc
modules/lmdbbackend/lmdbbackend.hh
modules/lua2backend/lua2api2.hh
modules/remotebackend/remotebackend.cc
modules/remotebackend/remotebackend.hh
modules/remotebackend/test-remotebackend-http.cc
modules/remotebackend/test-remotebackend-json.cc
modules/remotebackend/test-remotebackend-pipe.cc
modules/remotebackend/test-remotebackend-post.cc
modules/remotebackend/test-remotebackend-unix.cc
modules/remotebackend/test-remotebackend-zeromq.cc
modules/remotebackend/test-remotebackend.cc
modules/tinydnsbackend/tinydnsbackend.cc
modules/tinydnsbackend/tinydnsbackend.hh
pdns/Makefile.am
pdns/arguments.cc
pdns/auth-main.cc
pdns/auth-primarycommunicator.cc [moved from pdns/mastercommunicator.cc with 73% similarity]
pdns/auth-secondarycommunicator.cc [moved from pdns/slavecommunicator.cc with 58% similarity]
pdns/backends/gsql/gsqlbackend.cc
pdns/backends/gsql/gsqlbackend.hh
pdns/bindparser.yy
pdns/bindparserclasses.hh
pdns/cachecleaner.hh
pdns/communicator.cc
pdns/communicator.hh
pdns/dbdnsseckeeper.cc
pdns/dns.hh
pdns/dnsbackend.cc
pdns/dnsbackend.hh
pdns/dnsbulktest.cc
pdns/dnscrypt.cc
pdns/dnsdist-cache.cc
pdns/dnsdist-console.cc
pdns/dnsdist-dynblocks.hh
pdns/dnsdist-ecs.cc
pdns/dnsdist-idstate.hh
pdns/dnsdist-lua-actions.cc
pdns/dnsdist-lua-bindings-dnsquestion.cc
pdns/dnsdist-lua-inspection.cc
pdns/dnsdist-lua-rules.cc
pdns/dnsdist-lua.cc
pdns/dnsdist-tcp.cc
pdns/dnsdist-web.cc
pdns/dnsdist-xpf.cc
pdns/dnsdist.cc
pdns/dnsdist.hh
pdns/dnsdistdist/.gitignore
pdns/dnsdistdist/Makefile.am
pdns/dnsdistdist/configure.ac
pdns/dnsdistdist/dnsdist-backend.cc
pdns/dnsdistdist/dnsdist-discovery.cc
pdns/dnsdistdist/dnsdist-edns.cc
pdns/dnsdistdist/dnsdist-edns.hh
pdns/dnsdistdist/dnsdist-healthchecks.cc
pdns/dnsdistdist/dnsdist-lua-ffi-interface.h
pdns/dnsdistdist/dnsdist-lua-ffi.cc
pdns/dnsdistdist/dnsdist-metrics.cc
pdns/dnsdistdist/dnsdist-metrics.hh
pdns/dnsdistdist/dnsdist-nghttp2-in.cc
pdns/dnsdistdist/dnsdist-nghttp2-in.hh
pdns/dnsdistdist/dnsdist-nghttp2.cc
pdns/dnsdistdist/dnsdist-secpoll.cc
pdns/dnsdistdist/dnsdist-tcp-downstream.cc
pdns/dnsdistdist/dnsdist-tcp.hh
pdns/dnsdistdist/docs/advanced/tls-sessions-management.rst
pdns/dnsdistdist/docs/advanced/tuning.rst
pdns/dnsdistdist/docs/changelog.rst
pdns/dnsdistdist/docs/conf.py
pdns/dnsdistdist/docs/guides/webserver.rst
pdns/dnsdistdist/docs/install.rst
pdns/dnsdistdist/docs/reference/config.rst
pdns/dnsdistdist/docs/reference/dq.rst
pdns/dnsdistdist/docs/rules-actions.rst
pdns/dnsdistdist/docs/statistics.rst
pdns/dnsdistdist/doh.cc
pdns/dnsdistdist/doq.cc
pdns/dnsdistdist/html/index.html
pdns/dnsdistdist/html/local.js
pdns/dnsdistdist/m4/dnsdist_enable_doq.m4
pdns/dnsdistdist/m4/pdns_with_quiche.m4
pdns/dnsdistdist/test-dnsdist-dnsparser.cc
pdns/dnsdistdist/test-dnsdist-lua-ffi.cc
pdns/dnsdistdist/test-dnsdistnghttp2-in_cc.cc
pdns/dnsdistdist/test-dnsdistnghttp2_cc.cc
pdns/dnsparser.cc
pdns/dnsparser.hh
pdns/dnsscope.cc
pdns/dnsseckeeper.hh
pdns/dnssecsigner.cc
pdns/dnstap.cc
pdns/dnstcpbench.cc
pdns/dolog.hh
pdns/dynhandler.cc
pdns/histog.hh
pdns/iputils.hh
pdns/ixfrdist-stats.cc
pdns/ixfrdist-stats.hh
pdns/ixfrdist.cc
pdns/ixfrutils.cc
pdns/ixfrutils.hh
pdns/ixplore.cc
pdns/libssl.cc
pdns/logging.hh
pdns/lua-base4.cc
pdns/lua-record.cc
pdns/misc.cc
pdns/packethandler.cc
pdns/packethandler.hh
pdns/pdnsutil.cc
pdns/protozero.cc
pdns/recursordist/configure.ac
pdns/recursordist/docs/appendices/structuredlogging.rst [new file with mode: 0644]
pdns/recursordist/docs/changelog/4.9.rst
pdns/recursordist/docs/changelog/5.0.rst
pdns/recursordist/docs/upgrade.rst
pdns/recursordist/filterpo.cc
pdns/recursordist/lazy_allocator.hh
pdns/recursordist/lua-recursor4.cc
pdns/recursordist/m4/ax_compare_version.m4 [new symlink]
pdns/recursordist/m4/pdns_check_cargo.m4 [new file with mode: 0644]
pdns/recursordist/mtasker_fcontext.cc
pdns/recursordist/negcache.cc
pdns/recursordist/negcache.hh
pdns/recursordist/pdns_recursor.cc
pdns/recursordist/rec-lua-conf.cc
pdns/recursordist/rec-main.cc
pdns/recursordist/rec-tcpout.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.cc
pdns/recursordist/rpzloader.cc
pdns/recursordist/secpoll-recursor.cc
pdns/recursordist/settings/cxxsupport.cc
pdns/recursordist/settings/docs-new-preamble-in.rst
pdns/recursordist/settings/table.py
pdns/recursordist/syncres.cc
pdns/recursordist/test-filterpo_cc.cc
pdns/recursordist/test-negcache_cc.cc
pdns/recursordist/test-reczones-helpers.cc
pdns/recursordist/ws-recursor.cc
pdns/rfc2136handler.cc
pdns/speedtest.cc
pdns/tcpiohandler.cc
pdns/test-bindparser_cc.cc
pdns/test-common.hh
pdns/test-dns_random_hh.cc
pdns/test-dnsdistpacketcache_cc.cc
pdns/test-dnsrecordcontent.cc
pdns/test-dnsrecords_cc.cc
pdns/test-ixfr_cc.cc
pdns/test-signers.cc
pdns/test-ueberbackend_cc.cc
pdns/ueberbackend.cc
pdns/ueberbackend.hh
pdns/ws-auth.cc
pdns/zone2sql.cc
pdns/zonemd.cc
regression-tests.api/test_Zones.py
regression-tests.auth-py/requirements.txt
regression-tests.auth-py/runtests
regression-tests.auth-py/test_IXFR.py
regression-tests.auth-py/test_XFRIncomplete.py
regression-tests.dnsdist/test_API.py
regression-tests.dnsdist/test_EDE.py [new file with mode: 0644]
regression-tests.dnsdist/test_RulesActions.py
regression-tests.ixfrdist/test_IXFR.py
regression-tests.ixfrdist/test_Stats.py
regression-tests.nobackend/supermaster-signed/command
regression-tests.nobackend/supermaster-unsigned/command
regression-tests.recursor-dnssec/test_AggressiveNSECCache.py
regression-tests.recursor-dnssec/test_basicNSEC3.py
regression-tests.recursor/RPZ-Lua/expected_result
regression-tests.recursor/RPZ/command
regression-tests.recursor/RPZ/expected_result
regression-tests.recursor/answer-in-local-auth/command
regression-tests.recursor/answer-in-local-auth/expected_result
regression-tests.recursor/auth-zone-cname-wildcard/command
regression-tests.recursor/auth-zone-cname-wildcard/expected_result
regression-tests.recursor/auth-zone-delegation/command
regression-tests.recursor/auth-zone-delegation/expected_result
regression-tests.recursor/auth-zones/command
regression-tests.recursor/auth-zones/expected_result
regression-tests.recursor/cache-recursorcache-forward/command
regression-tests.recursor/cache-recursorcache-forward/expected_result
regression-tests.recursor/cname-to-a-nxdomain/command
regression-tests.recursor/cname-to-a-nxdomain/expected_result
regression-tests.recursor/cross-zone-cname-bogus-nxdomain/command
regression-tests.recursor/cross-zone-cname-bogus-nxdomain/expected_result
regression-tests.recursor/direct-cname-to-nxdomain/command
regression-tests.recursor/direct-cname-to-nxdomain/expected_result
regression-tests.recursor/direct-cname/command
regression-tests.recursor/direct-cname/expected_result
regression-tests.recursor/ghost-1/command
regression-tests.recursor/ghost-1/expected_result
regression-tests.recursor/ghost-2/command
regression-tests.recursor/ghost-2/expected_result
regression-tests.recursor/hijack-1/command
regression-tests.recursor/hijack-1/expected_result
regression-tests.recursor/in-zone-cname-bogus-nxdomain/command
regression-tests.recursor/in-zone-cname-bogus-nxdomain/expected_result
regression-tests.recursor/lame-noerror/command
regression-tests.recursor/simple-a/command
regression-tests.recursor/simple-a/expected_result
regression-tests.recursor/simple-cname-to-a/command
regression-tests.recursor/simple-cname-to-a/expected_result
regression-tests.recursor/simple-rawtypes/command
regression-tests.recursor/simple-rawtypes/expected_result
regression-tests.recursor/truncate-empty/command
regression-tests.recursor/txt-escaping/command
regression-tests.recursor/txt-escaping/expected_result
regression-tests/backends/bind-master
regression-tests/backends/bind-slave
regression-tests/backends/godbc_mssql-slave
regression-tests/backends/godbc_sqlite3-master
regression-tests/backends/gpgsql-slave
regression-tests/backends/gsql-common
regression-tests/backends/gsqlite3-slave
regression-tests/backends/lmdb-master
tasks.py

index f6ba38ee2e97f29339f9ddc5931219ef9d0e4da1..2b208a6996e64a3e5ec7fefd300b581f1f1eb433 100644 (file)
@@ -1,5 +1,5 @@
 ---
-Checks:          'clang-diagnostic-*,clang-analyzer-*,cppcoreguidelines-*,bugprone-*,concurrency-*,modernize-*,performance-*,portability-*,readability-*,-modernize-use-trailing-return-type,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-avoid-non-const-global-variables,-cppcoreguidelines-pro-type-vararg'
+Checks:          'clang-diagnostic-*,clang-analyzer-*,cppcoreguidelines-*,bugprone-*,concurrency-*,modernize-*,performance-*,portability-*,readability-*,-modernize-use-trailing-return-type,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-avoid-non-const-global-variables,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-avoid-do-while'
 WarningsAsErrors: ''
 HeaderFilterRegex: ''
 AnalyzeTemporaryDtors: false
index cfb44fd13b4a1b166cf76f4e94b0797f0e0e6e34..b5083a386db0492cf66d33e513ff43be071b9c83 100644 (file)
@@ -36,6 +36,7 @@ ansible
 ANSSI
 Antoin
 apikey
+apizones
 AQAB
 ARCHFLAGS
 arecord
@@ -345,6 +346,7 @@ domainname
 domainrelatedobject
 Donatas
 dontcare
+doq
 downsides
 downstreams
 dport
@@ -384,6 +386,7 @@ edu
 ejones
 Ekkelenkamp
 elgoog
+endbr
 Enden
 ent
 envoutput
@@ -741,6 +744,7 @@ luawrapper
 Lutter
 Luuk
 LYg
+Machard
 Maik
 Maikel
 MAILA
@@ -809,6 +813,7 @@ msphinx
 msrv
 mtasker
 mthread
+mtid
 Mulholland
 multimaster
 munmap
index 4fafc03e168ce1e6d2ef7bd5794bc71ef59526ae..d7867c830154995bcb472966d484691ac3bea6b2 100755 (executable)
@@ -45,6 +45,12 @@ def main():
         print("No diagnostics or warnings produced by clang-tidy")
         return 0
 
+    gh_step_summary = os.getenv('GITHUB_STEP_SUMMARY')
+    if gh_step_summary:
+        # Print Markdown summary
+        summaryFp = open(gh_step_summary, 'a', encoding='utf-8')
+        print('### clang-tidy summary', file=summaryFp)
+
     fixes = fixes["Diagnostics"]
     have_warnings = False
     for fix in fixes:
@@ -90,6 +96,9 @@ def main():
         # User-friendly printout
         print(f"{level}: {relative_filename}:{line}: {message} ({name})")
 
+        if gh_step_summary:
+            print(f'- **{relative_filename}:{line}** {message} (`{name}`)', file=summaryFp)
+
         have_warnings = True
 
     return 1 if have_warnings else 0
index aa05904f0a5e6de7638081f7c63d0df966feb9ac..32b4fd469128548629400a23dab7ffc3c9266369 100755 (executable)
@@ -7,35 +7,75 @@ the current directory.
 
 """
 
+import argparse
 import os
 import sys
+from pathlib import Path
 
 import helpers
 import unidiff
 
+def create_argument_parser():
+    """Create command-line argument parser."""
+    parser = argparse.ArgumentParser(
+        description="Filter git diff files that are not in the product"
+    )
+    parser.add_argument(
+        "--product",
+        type=str,
+        required=True,
+        help="Product (auth, dnsdist or rec)",
+    )
+    return parser.parse_args()
+
 
 def main():
     """Start the script."""
-    # It might be tempting to normalize the paths here instead of
-    # rewriting the compilation database, but then clang-tidy
-    # loses the depth of files in the repository, outputing for
-    # example "credentials.cc" instead of "pdns/credentials.cc"
+    args = create_argument_parser()
+    product = args.product
+
     compdb = helpers.load_compdb("compile_commands.json")
     compdb = helpers.index_compdb(compdb)
 
-    pdns_path = os.path.join("pdns", "")
-    cwd = os.getcwd()
-    root = helpers.get_repo_root()
+    cwd = Path(os.getcwd())
 
     diff = sys.stdin.read()
     patch_set = unidiff.PatchSet(diff)
     for patch in patch_set:
-        path = os.path.join(root, patch.path)
-        if path in compdb:
-            print(patch)
+        # We have to deal with several possible cases for input files, as shown by git:
+        # - in ext/: ext/lmdb-safe/lmdb-safe.cc
+        # - in modules/: modules/lmdbbackend/lmdbbackend.cc
+        # - files that live in the dnsdist or rec dir only: pdns/dnsdistdist/dnsdist-dnsparser.cc or pdns/recursordist/rec-tcp.cc
+        # - files that live in pdns/ and are used by several products (but possibly not with the same compilation flags, so
+        #   it is actually important that they are processed for all products: pdns/misc.cc
+        path = Path(patch.path)
+        if product == 'auth':
+            path = Path(cwd).joinpath(path)
         else:
-            msg = f"Skipping {path}: it is not in the compilation db"
-            print(msg, file=sys.stderr)
+            if str(path).startswith('modules'):
+                print(f'Skipping {path}: modules do not apply to {product}', file=sys.stderr)
+                continue
+
+            if str(path).startswith('ext'):
+                subpath = Path(cwd).joinpath(path)
+            else:
+                subpath = Path(cwd).joinpath(path.name)
+
+            if not subpath.exists():
+                print(f'Skipping {path}: does not exist for {product} ({subpath})', file=sys.stderr)
+                continue
+
+            path = subpath
+            if patch.source_file is not None:
+                patch.source_file = str(path)
+            patch.target_file = str(path)
+
+        if not str(path) in compdb:
+            print(f'Skipping {path}: it is not in the compilation db', file=sys.stderr)
+            continue
+
+        print(patch, file=sys.stderr)
+        print(patch)
 
     return 0
 
index 36969c8060f3cc1b217bab1c2b93339f8298a47c..cc170d1eed5ca2c027db400793ba277e29ada478 100644 (file)
@@ -1,9 +1,7 @@
 """Helpers for dealing with git, compilation databases, etc."""
 
-import pathlib
 import json
 import os
-import sys
 
 import git
 import yaml
@@ -48,28 +46,3 @@ def index_compdb(file_contents):
         filename = os.path.join(item["directory"], item["file"])
         result.add(filename)
     return result
-
-def normalize_dist_dir(version, distPath):
-    """Map the path of a source file from inside the dist directory
-       to its path in the git repository."""
-    # get rid of the distdir path, to get file paths as they are in the repository
-    repositoryPath = pathlib.Path(get_repo_root()).resolve()
-    distPath = pathlib.Path(distPath).resolve()
-    if f'pdns-{version}' in distPath.parts:
-        # authoritative or tool
-        authPath = repositoryPath.joinpath(f'pdns-{version}').resolve()
-        relativeToAuth = distPath.relative_to(authPath)
-        return str(repositoryPath.joinpath(relativeToAuth))
-
-    if f'pdns-recursor-{version}' in distPath.parts:
-        recPath = repositoryPath.joinpath('pdns', 'recursordist', f'pdns-recursor-{version}').resolve()
-        relativeToRec = distPath.relative_to(recPath)
-        return str(repositoryPath.joinpath('pdns', 'recursordist', relativeToRec).resolve())
-
-    if f'dnsdist-{version}' in distPath.parts:
-        dnsdistPath = repositoryPath.joinpath('pdns', 'dnsdistdist', f'dnsdist-{version}').resolve()
-        relativeToDist = distPath.relative_to(dnsdistPath)
-        return str(repositoryPath.joinpath('pdns', 'dnsdistdist', relativeToDist).resolve())
-
-    print(f'Unable to map {distPath}', file=sys.stderr)
-    return str(distPath)
diff --git a/.github/scripts/normalize_paths_in_compilation_database.py b/.github/scripts/normalize_paths_in_compilation_database.py
deleted file mode 100644 (file)
index f5645fb..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env python3
-
-import argparse
-import os
-
-import json
-
-import helpers
-
-def create_argument_parser():
-    """Create command-line argument parser."""
-    parser = argparse.ArgumentParser(
-        description="Normalize paths in compilation database"
-    )
-    parser.add_argument(
-        "--version",
-        type=str,
-        required=True,
-        help="Version number of the current build",
-    )
-    parser.add_argument('database')
-    return parser.parse_args()
-
-if __name__ == "__main__":
-    """Start the script."""
-    args = create_argument_parser()
-
-    compDB = helpers.load_compdb(args.database)
-    for entry in compDB:
-        for key in ['file', 'directory']:
-            if key in entry:
-                entry[key] = helpers.normalize_dist_dir(args.version, entry[key])
-
-    with open(args.database + '.temp', 'w', encoding='utf-8') as outputFile:
-        json.dump(compDB, outputFile, ensure_ascii=False, indent=2)
-
-    os.rename(args.database + '.temp', args.database)
index 528c882072a23391636e367855ac9543ad0725d0..f2fd15ab0e7d74dff00b1ea0fd00ba3ef1e0243d 100644 (file)
@@ -11,12 +11,15 @@ permissions: # least privileges, see https://docs.github.com/en/actions/using-wo
   contents: read
 
 env:
+  COMPILER: clang
   CLANG_VERSION: '13'
   # github.workspace variable points to the Runner home folder. Container home folder defined below.
   REPO_HOME: '/__w/pdns/pdns'
   BUILDER_VERSION: '0.0.0-git1'
   COVERAGE: yes
   LLVM_PROFILE_FILE: "/tmp/code-%p.profraw"
+  OPTIMIZATIONS: yes
+  DECAF_SUPPORT: yes
 
 jobs:
   build-auth:
@@ -35,8 +38,6 @@ jobs:
     defaults:
       run:
         working-directory: ./pdns-${{ env.BUILDER_VERSION }}
-    outputs:
-      clang-tidy-failed: ${{ steps.clang-tidy-annotations.outputs.failed }}
     steps:
       - uses: actions/checkout@v3
         with:
@@ -64,34 +65,6 @@ jobs:
         working-directory: .
       - run: inv ci-auth-configure
       - run: inv ci-auth-make-bear  # This runs under pdns-$BUILDER_VERSION/pdns/
-      - name: Normalize paths in compilation DB
-        working-directory: .
-        run: python3 .github/scripts/normalize_paths_in_compilation_database.py --version $BUILDER_VERSION pdns-$BUILDER_VERSION/pdns/compile_commands.json
-      - name: Copy the compilation DB
-        working-directory: .
-        run: cp pdns-$BUILDER_VERSION/pdns/compile_commands.json .
-      - run: ln -s .clang-tidy.full .clang-tidy
-        working-directory: .
-      - name: Run clang-tidy
-        working-directory: .
-        run: git diff -U0 HEAD^..HEAD | python3 .github/scripts/git-filter.py | python3 .github/scripts/clang-tidy-diff.py -clang-tidy-binary /usr/bin/clang-tidy-${CLANG_VERSION} -extra-arg=-ferror-limit=0 -p1 -export-fixes clang-tidy-auth.yml
-      - name: Print clang-tidy fixes YAML
-        working-directory: .
-        shell: bash
-        run: |
-          if [ -f clang-tidy-auth.yml ]; then
-            cat clang-tidy-auth.yml
-          fi
-      - name: Result annotations
-        id: clang-tidy-annotations
-        working-directory: .
-        shell: bash
-        run: |
-          if [ -f clang-tidy-auth.yml ]; then
-            set +e
-            python3 .github/scripts/clang-tidy.py --fixes-file clang-tidy-auth.yml
-            echo "failed=$?" >> $GITHUB_OUTPUT
-          fi
       - run: inv ci-auth-install-remotebackend-test-deps
       - run: inv ci-auth-run-unit-tests
       - run: inv generate-coverage-info ./testrunner $GITHUB_WORKSPACE
@@ -130,8 +103,6 @@ jobs:
     defaults:
       run:
         working-directory: ./pdns/recursordist/pdns-recursor-${{ env.BUILDER_VERSION }}
-    outputs:
-      clang-tidy-failed: ${{ steps.clang-tidy-annotations.outputs.failed }}
     steps:
       - uses: actions/checkout@v3
         with:
@@ -161,34 +132,6 @@ jobs:
         working-directory: ./pdns/recursordist/
       - run: inv ci-rec-configure
       - run: inv ci-rec-make-bear
-      - name: Normalize paths in compilation DB
-        working-directory: .
-        run: python3 .github/scripts/normalize_paths_in_compilation_database.py --version $BUILDER_VERSION ./pdns/recursordist/pdns-recursor-$BUILDER_VERSION/compile_commands.json
-      - name: Copy compilation DB
-        working-directory: .
-        run: cp ./pdns/recursordist/pdns-recursor-$BUILDER_VERSION/compile_commands.json .
-      - run: ln -s .clang-tidy.full .clang-tidy
-        working-directory: .
-      - name: Run clang-tidy
-        working-directory: .
-        run: git diff -U0 HEAD^..HEAD | python3 .github/scripts/git-filter.py | python3 .github/scripts/clang-tidy-diff.py -clang-tidy-binary /usr/bin/clang-tidy-${CLANG_VERSION} -extra-arg=-ferror-limit=0 -p1 -export-fixes clang-tidy-rec.yml
-      - name: Print clang-tidy fixes YAML
-        working-directory: .
-        shell: bash
-        run: |
-          if [ -f clang-tidy-rec.yml ]; then
-            cat clang-tidy-rec.yml
-          fi
-      - name: Result annotations
-        id: clang-tidy-annotations
-        working-directory: .
-        shell: bash
-        run: |
-          if [ -f clang-tidy-rec.yml ]; then
-            set +e
-            python .github/scripts/clang-tidy.py --fixes-file clang-tidy-rec.yml
-            echo "failed=$?" >> $GITHUB_OUTPUT
-          fi
       - run: inv ci-rec-run-unit-tests
       - run: inv generate-coverage-info ./testrunner $GITHUB_WORKSPACE
         if: ${{ matrix.sanitizers != 'tsan' }}
@@ -232,8 +175,6 @@ jobs:
     defaults:
       run:
         working-directory: ./pdns/dnsdistdist/dnsdist-${{ env.BUILDER_VERSION }}
-    outputs:
-      clang-tidy-failed: ${{ steps.clang-tidy-annotations.outputs.failed }}
     steps:
       - uses: actions/checkout@v3
         with:
@@ -265,34 +206,6 @@ jobs:
         working-directory: ./pdns/dnsdistdist/
       - run: inv ci-dnsdist-configure ${{ matrix.features }}
       - run: inv ci-dnsdist-make-bear
-      - name: Normalize paths in compilation DB
-        working-directory: .
-        run: python3 .github/scripts/normalize_paths_in_compilation_database.py --version $BUILDER_VERSION ./pdns/dnsdistdist/dnsdist-$BUILDER_VERSION/compile_commands.json
-      - name: Copy compilation DB
-        run: cp ./pdns/dnsdistdist/dnsdist-$BUILDER_VERSION/compile_commands.json  compile_commands.json
-        working-directory: .
-      - run: ln -s .clang-tidy.full .clang-tidy
-        working-directory: .
-      - name: Run clang-tidy
-        working-directory: .
-        run: git diff -U0 HEAD^..HEAD | python3 .github/scripts/git-filter.py | python3 .github/scripts/clang-tidy-diff.py -clang-tidy-binary /usr/bin/clang-tidy-${CLANG_VERSION} -extra-arg=-ferror-limit=0 -p1 -export-fixes clang-tidy-dnsdist.yml
-      - name: Print clang-tidy fixes YAML
-        working-directory: .
-        shell: bash
-        run: |
-          if [ -f clang-tidy-dnsdist.yml ]; then
-            cat clang-tidy-dnsdist.yml
-          fi
-      - name: Result annotations
-        id: clang-tidy-annotations
-        working-directory: .
-        shell: bash
-        run: |
-          if [ -f clang-tidy-dnsdist.yml ]; then
-            set +e
-            python .github/scripts/clang-tidy.py --fixes-file clang-tidy-dnsdist.yml
-            echo "failed=$?" >> $GITHUB_OUTPUT
-          fi
       - run: inv ci-dnsdist-run-unit-tests
       - run: inv generate-coverage-info ./testrunner $GITHUB_WORKSPACE
         if: ${{ matrix.sanitizers != 'tsan' }}
@@ -573,7 +486,7 @@ jobs:
         sanitizers: [ubsan+asan, tsan]
         dist_name: [debian]
         dist_release_name: [bullseye]
-        pdns_repo_version: ['45']
+        pdns_repo_version: ['48']
     container:
       image: ghcr.io/powerdns/base-pdns-ci-image/debian-11-pdns-base:master
       env:
@@ -708,25 +621,6 @@ jobs:
       - run: inv install-swagger-tools
       - run: inv swagger-syntax-check
 
-  check-clang-tidy:
-    needs: [build-auth, build-dnsdist, build-recursor]
-    runs-on: ubuntu-20.04
-    name: Check whether clang-tidy succeeded
-    steps:
-      - run: |
-          if [ "x${{ needs.build-auth.outputs.clang-tidy-failed }}" != "x" -a "${{ needs.build-auth.outputs.clang-tidy-failed }}" != "0" ]; then
-            echo "::error::Auth clang-tidy failed"
-            exit 1
-          fi
-          if [ "x${{needs.build-recursor.outputs.clang-tidy-failed}}" != "x" -a "${{needs.build-recursor.outputs.clang-tidy-failed}}" != "0" ]; then
-            echo "::error::Rec clang-tidy failed"
-            exit 1
-          fi
-          if [ "x${{ needs.build-dnsdist.outputs.clang-tidy-failed }}" != "x" -a "${{ needs.build-dnsdist.outputs.clang-tidy-failed }}" != "0" ]; then
-            echo "::error::dnsdist clang-tidy failed"
-            exit 1
-          fi
-
   collect:
     needs:
       - build-auth
@@ -740,7 +634,6 @@ jobs:
       - test-recursor-api
       - test-recursor-regression
       - test-recursor-bulk
-      - check-clang-tidy
     if: success() || failure()
     runs-on: ubuntu-20.04
     steps:
index e967a3e32f3b3a58cd3806f0c788d54c37e8f055..0c1eff5855362dbe66bf6659a46918a9631932d9 100644 (file)
@@ -158,7 +158,7 @@ jobs:
       actions: read   # To read the workflow path.
       id-token: write # To sign the provenance.
       contents: write # To be able to upload assets as release artifacts
-    uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.4.0
+    uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.9.0
     with:
       base64-subjects: "${{ needs.build.outputs[format('pkghashes-{0}', matrix.os)] }}"
       upload-assets: false
@@ -171,7 +171,7 @@ jobs:
       actions: read   # To read the workflow path.
       id-token: write # To sign the provenance.
       contents: write # To be able to upload assets as release artifacts
-    uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.4.0
+    uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.9.0
     with:
       base64-subjects: "${{ needs.build.outputs.srchashes }}"
       upload-assets: false
index b8c7047261e25724d30db3851bba883ad65f1946..3836440a34680602049f206bdad844427b753a35 100644 (file)
@@ -1,4 +1,4 @@
-name: "CodeQL"
+name: "CodeQL and clang-tidy"
 
 on:
   push:
@@ -9,11 +9,24 @@ on:
 permissions: # least privileges, see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions
   contents: read
 
+# clang-tidy fun:
+# We need to invoke clang-tidy from the correct directory, the one the product was compiled in, so that we get the correct include paths.
+# This means the root for the auth, pdns/recursordist for the rec and pdns/dnsdistdist for dnsdist
+# It is important that files that are used by more than one product are processed by all the products using them
+# because they might have difference compilation flags.
+# We have to use our own clang-tidy-diff.py because the line-filter flag only supports file names, not paths.
+# Finally the GH annotations that we generate from clang-tidy.py, have to be relative to the path in the git repository, so we need to
+# follow symlinks.
+# How does that work? We use git diff to get the list of diffs, and git-filter.py to get the right folder depending on the product.
+# Then we call clang-tidy-diff.py, which invokes clang-tidy on the correct file, deducing the line numbers from the diff, and
+# merging the results for all processed files to a YAML file. Finally clang-tidy.py converts the YAML output to GitHub annotations
+# (GitHub only supports 10 of these per job, the rest are not displayed) and to GitHub markdown step summary (which has no such limits).
+
 jobs:
   analyze:
     name: Analyze
     if: ${{ !github.event.schedule || vars.SCHEDULED_CODEQL_ANALYSIS }}
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-22.04
 
     permissions:
       actions: read # for github/codeql-action/init to get workflow details
@@ -30,6 +43,22 @@ jobs:
         # Learn more...
         # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
 
+    env:
+      COMPILER: gcc
+      UNIT_TESTS: yes
+      FUZZING_TARGETS: yes
+      COVERAGE: no
+      OPTIMIZATIONS: no
+      # for clang-tidy only, not compilation
+      CLANG_VERSION: '14'
+      REPO_HOME: ${{ github.workspace }}
+      DECAF_SUPPORT: no
+
+    outputs:
+      clang-tidy-annotations-auth: ${{ steps.clang-tidy-annotations-auth.outputs.failed }}
+      clang-tidy-annotations-dnsdist: ${{ steps.clang-tidy-annotations-dnsdist.outputs.failed }}
+      clang-tidy-annotations-rec: ${{ steps.clang-tidy-annotations-rec.outputs.failed }}
+
     steps:
     - uses: PowerDNS/pdns/set-ubuntu-mirror@meta
     - name: Checkout repository
@@ -39,11 +68,6 @@ jobs:
         # a pull request then we can checkout the head.
         fetch-depth: 2
 
-    # Python is required for building the Authoritative server
-    - uses: actions/setup-python@v4
-      with:
-        python-version: '3.8'
-
     # Initializes the CodeQL tools for scanning.
     - name: Initialize CodeQL
       uses: github/codeql-action/init@v2
@@ -53,7 +77,7 @@ jobs:
         # TODO: go through +security-and-quality (400 alerts) once, then see if we can upgrade to it
 
         # If you wish to specify custom queries, you can do so here or in a config file.
-        # By default, queries listed here will override any specified in a config file. 
+        # By default, queries listed here will override any specified in a config file.
         # Prefix the list here with "+" to use these queries and those in the config file.
         # queries: ./path/to/local/query, your-org/your-repo/queries@main
 
@@ -72,72 +96,173 @@ jobs:
     - name: Update repository metadata
       run: |
         sudo apt-get update
-    - name: Install dependencies
-      run: |
-        sudo apt-get -qq -y --no-install-recommends --allow-downgrades install \
-                bison \
-                default-libmysqlclient-dev \
-                flex \
-                libboost-all-dev \
-                libcap-dev \
-                libcdb-dev \
-                libcurl4-openssl-dev \
-                libedit-dev \
-                libfstrm-dev \
-                libgeoip-dev \
-                libgnutls28-dev \
-                libh2o-evloop-dev \
-                libkrb5-dev \
-                libldap2-dev \
-                liblmdb-dev \
-                liblua5.3-dev \
-                libmaxminddb-dev \
-                libnghttp2-dev \
-                libp11-kit-dev \
-                libpq-dev \
-                libre2-dev \
-                libsnmp-dev \
-                libsodium-dev \
-                libsqlite3-dev \
-                libssl-dev \
-                libsystemd-dev \
-                libwslay-dev \
-                libyaml-cpp-dev \
-                ragel \
-                rustc \
-                unixodbc-dev
 
+    - name: Install python invoke and needed libs
+      run: |
+        sudo apt-get -qq -y --no-install-recommends install python3 python3-pip python3-invoke python3-git python3-unidiff ccache
+
+    - name: Install clang-tidy tools
+      run: |
+        inv install-clang-tidy-tools
+
+    - name: Install dependencies for auth
+      if: matrix.product == 'auth'
+      run: |
+        inv install-auth-build-deps
+    - name: Autoreconf auth
+      if: matrix.product == 'auth'
+      run: |
+        inv ci-autoconf
+    - name: Configure auth
+      if: matrix.product == 'auth'
+      run: |
+        inv ci-auth-configure
     - name: Build auth
       if: matrix.product == 'auth'
       run: |
-        autoreconf -vfi
-        ./configure --with-modules='bind geoip gmysql godbc gpgsql gsqlite3 ldap lmdb lua2 pipe remote tinydns' --enable-tools --enable-ixfrdist --enable-dns-over-tls --enable-experimental-pkcs11 --with-libsodium --enable-lua-records CFLAGS='-O0' CXXFLAGS='-O0'
-        make -j8 -C ext
-        make -j8 -C modules
-        make -j8 -C pdns
+        inv ci-auth-make-bear
+    - run: ln -s .clang-tidy.full .clang-tidy
+      if: matrix.product == 'auth'
+    - name: Run clang-tidy for auth
+      if: matrix.product == 'auth'
+      run: git diff --no-prefix -U0 HEAD^..HEAD | python3 .github/scripts/git-filter.py --product auth | python3 .github/scripts/clang-tidy-diff.py -clang-tidy-binary /usr/bin/clang-tidy-${CLANG_VERSION} -extra-arg=-ferror-limit=0 -p0 -export-fixes clang-tidy-auth.yml
+    - name: Print clang-tidy fixes YAML for auth
+      if: matrix.product == 'auth'
+      shell: bash
+      run: |
+        if [ -f clang-tidy-auth.yml ]; then
+          cat clang-tidy-auth.yml
+        fi
+    - name: Result annotations for auth
+      if: matrix.product == 'auth'
+      id: clang-tidy-annotations-auth
+      shell: bash
+      run: |
+        if [ -f clang-tidy-auth.yml ]; then
+          set +e
+          python3 .github/scripts/clang-tidy.py --fixes-file clang-tidy-auth.yml
+          echo "failed=$?" >> $GITHUB_OUTPUT
+        fi
 
+    - name: Install dependencies for dnsdist
+      if: matrix.product == 'dnsdist'
+      run: |
+        inv install-dnsdist-build-deps
+    - name: Autoreconf dnsdist
+      if: matrix.product == 'dnsdist'
+      working-directory: ./pdns/dnsdistdist/
+      run: |
+        inv ci-autoconf
+    - run: inv ci-install-rust ${{ env.REPO_HOME }}
+      if: matrix.product == 'dnsdist'
+      working-directory: ./pdns/dnsdistdist/
+    - run: inv ci-build-and-install-quiche
+      if: matrix.product == 'dnsdist'
+      working-directory: ./pdns/dnsdistdist/
+    - name: Configure dnsdist
+      if: matrix.product == 'dnsdist'
+      working-directory: ./pdns/dnsdistdist/
+      run: |
+        inv ci-dnsdist-configure full
     - name: Build dnsdist
       if: matrix.product == 'dnsdist'
+      working-directory: ./pdns/dnsdistdist/
       run: |
-        cd pdns/dnsdistdist
-        autoreconf -vfi
-        ./configure --enable-unit-tests --enable-dnstap --enable-dnscrypt --enable-dns-over-tls --enable-dns-over-https --with-h2o LIBS=-lwslay CFLAGS='-O0' CXXFLAGS='-O0'
-        make -j8 -C ext/arc4random
-        make -j8 -C ext/ipcrypt
-        make -j8 -C ext/yahttp
-        make -j4 dnsdist
+        inv ci-dnsdist-make-bear
+    - run: ln -s ../../.clang-tidy.full .clang-tidy
+      if: matrix.product == 'dnsdist'
+      working-directory: ./pdns/dnsdistdist/
+    - name: Run clang-tidy for dnsdist
+      if: matrix.product == 'dnsdist'
+      working-directory: ./pdns/dnsdistdist/
+      run: git diff --no-prefix -U0 HEAD^..HEAD | python3 ../../.github/scripts/git-filter.py --product dnsdist | python3 ../../.github/scripts/clang-tidy-diff.py -clang-tidy-binary /usr/bin/clang-tidy-${CLANG_VERSION} -extra-arg=-ferror-limit=0 -p0 -export-fixes clang-tidy-dnsdist.yml
+    - name: Print clang-tidy fixes YAML for dnsdist
+      if: matrix.product == 'dnsdist'
+      working-directory: ./pdns/dnsdistdist/
+      shell: bash
+      run: |
+        if [ -f clang-tidy-dnsdist.yml ]; then
+          cat clang-tidy-dnsdist.yml
+        fi
+    - name: Result annotations for dnsdist
+      if: matrix.product == 'dnsdist'
+      id: clang-tidy-annotations-dnsdist
+      working-directory: ./pdns/dnsdistdist/
+      shell: bash
+      run: |
+        if [ -f clang-tidy-dnsdist.yml ]; then
+          set +e
+          python3 ../../.github/scripts/clang-tidy.py --fixes-file clang-tidy-dnsdist.yml
+          echo "failed=$?" >> $GITHUB_OUTPUT
+        fi
 
-    - name: Build recursor
+    - name: Install dependencies for rec
+      if: matrix.product == 'rec'
+      run: |
+        inv install-rec-build-deps
+    - run: inv ci-install-rust ${{ env.REPO_HOME }}
+      if: matrix.product == 'rec'
+      working-directory: ./pdns/recursordist/
+    - name: Autoreconf rec
       if: matrix.product == 'rec'
+      working-directory: ./pdns/recursordist/
       run: |
-        cd pdns/recursordist
-        autoreconf -vfi
-        ./configure --enable-unit-tests --enable-nod --enable-dnstap CFLAGS='-O0' CXXFLAGS='-O0'
-        make -j8 -C ext
-        make -j8 -C settings
-        make -j8 -C settings/rust
-        make htmlfiles.h
-        make -j4 pdns_recursor rec_control
+        inv ci-autoconf
+    - name: Configure rec
+      if: matrix.product == 'rec'
+      working-directory: ./pdns/recursordist/
+      run: |
+        inv ci-rec-configure
+    - name: Build rec
+      if: matrix.product == 'rec'
+      working-directory: ./pdns/recursordist/
+      run: |
+        CONCURRENCY=4 inv ci-rec-make-bear
+    - run: ln -s ../../.clang-tidy.full .clang-tidy
+      if: matrix.product == 'rec'
+      working-directory: ./pdns/recursordist/
+    - name: Run clang-tidy for rec
+      if: matrix.product == 'rec'
+      working-directory: ./pdns/recursordist/
+      run: git diff --no-prefix -U0 HEAD^..HEAD | python3 ../../.github/scripts/git-filter.py --product rec | python3 ../../.github/scripts/clang-tidy-diff.py -clang-tidy-binary /usr/bin/clang-tidy-${CLANG_VERSION} -extra-arg=-ferror-limit=0 -p0 -export-fixes clang-tidy-rec.yml
+    - name: Print clang-tidy fixes YAML for rec
+      if: matrix.product == 'rec'
+      working-directory: ./pdns/recursordist/
+      shell: bash
+      run: |
+        if [ -f clang-tidy-rec.yml ]; then
+          cat clang-tidy-rec.yml
+        fi
+    - name: Result annotations for rec
+      if: matrix.product == 'rec'
+      id: clang-tidy-annotations-rec
+      working-directory: ./pdns/recursordist/
+      shell: bash
+      run: |
+        if [ -f clang-tidy-rec.yml ]; then
+          set +e
+          python3 ../../.github/scripts/clang-tidy.py --fixes-file clang-tidy-rec.yml
+          echo "failed=$?" >> $GITHUB_OUTPUT
+        fi
 
     - name: Perform CodeQL Analysis
       uses: github/codeql-action/analyze@v2
+
+  check-clang-tidy:
+    needs: analyze
+    runs-on: ubuntu-20.04
+    name: Check whether clang-tidy succeeded
+    steps:
+      - run: |
+          if [ "x${{ needs.analyze.outputs.clang-tidy-annotations-auth }}" != "x" -a "${{ needs.analyze.outputs.clang-tidy-annotations-auth }}" != "0" ]; then
+            echo "::error::Auth clang-tidy failed"
+            exit 1
+          fi
+          if [ "x${{ needs.analyze.outputs.clang-tidy-annotations-dnsdist }}" != "x" -a "${{ needs.analyze.outputs.clang-tidy-annotations-dnsdist }}" != "0" ]; then
+            echo "::error::DNSdist clang-tidy failed"
+            exit 1
+          fi
+          if [ "x${{needs.analyze.outputs.clang-tidy-annotations-rec }}" != "x" -a "${{needs.analyze.outputs.clang-tidy-annotations-rec }}" != "0" ]; then
+            echo "::error::Rec clang-tidy failed"
+            exit 1
+          fi
index 60d66abe821acca2376e5bf8fcf9b0bdd83d9bbc..07f50aa52a7c207222a1544e40572800e334fd57 100644 (file)
@@ -86,6 +86,8 @@ jobs:
       - run: inv coverity-clang-configure
       - run: inv ci-autoconf
         working-directory: ./pdns/dnsdistdist/
+      - run: inv ci-build-and-install-quiche
+        working-directory: ./pdns/dnsdistdist/
       - run: inv ci-dnsdist-configure full
         working-directory: ./pdns/dnsdistdist/
       - run: inv coverity-make
index c4d86e3d296482d1d61fbae0b3b67d7b14f322af..b9e7246b8a37aeffbee76bf79b2d1c5e341990f2 100644 (file)
 ./pdns/lua-record.cc
 ./pdns/malloctrace.cc
 ./pdns/malloctrace.hh
-./pdns/mastercommunicator.cc
+./pdns/auth-primarycommunicator.cc
 ./pdns/minicurl.cc
 ./pdns/minicurl.hh
 ./pdns/misc.cc
 ./pdns/signingpipe.cc
 ./pdns/signingpipe.hh
 ./pdns/sillyrecords.cc
-./pdns/slavecommunicator.cc
 ./pdns/snmp-agent.cc
 ./pdns/snmp-agent.hh
 ./pdns/sodcrypto.cc
 ./pdns/tsigutils.hh
 ./pdns/tsigverifier.cc
 ./pdns/tsigverifier.hh
-./pdns/ueberbackend.cc
-./pdns/ueberbackend.hh
 ./pdns/unix_semaphore.cc
 ./pdns/unix_utility.cc
 ./pdns/utility.hh
index 50d11f607c77a4d46baf6033ebc56c26e707379d..189461af67f6e8ef45ef754d1489dbab6d086f62 100755 (executable)
@@ -11,7 +11,4 @@ sudo dpkg --purge --force-all grub-efi-amd64-signed && sudo dpkg --purge --force
 sudo dpkg --purge --force-all firefox
 sudo apt-get autoremove
 sudo apt-get -qq -y --allow-downgrades dist-upgrade
-sudo apt-get -qq -y --no-install-recommends install python3-pip
-sudo pip3 install git+https://github.com/pyinvoke/invoke@faa5728a6f76199a3da1750ed952e7efee17c1da
-sudo pip3 install gitpython
-sudo pip3 install unidiff
+sudo apt-get -qq -y --no-install-recommends install python3-pip python3-invoke
index 49fe23a919f76e1e177d68d1b7ebf7636c7ca1cd..fc31dfee2ef5ebc714702163ca8fbd48f844c7f2 100755 (executable)
@@ -7,5 +7,3 @@ EOF
 sudo chmod 755 /usr/sbin/policy-rc.d
 sudo apt-get update
 sudo apt-get -qq -y --no-install-recommends install python3-pip python3-invoke
-sudo pip3 install gitpython
-sudo pip3 install unidiff
index 2a37f3e9bc8d5c986b96ec0e727ccbc4490f5bc7..088df9710c23bd80b0c037fb74abc886d078a22b 100644 (file)
@@ -12,6 +12,9 @@ ADD builder/helpers/set-configure-ac-version.sh /pdns-recursor/builder/helpers/
 ADD builder-support/gen-version /pdns-recursor/pdns/recursordist/builder-support/gen-version
 WORKDIR /pdns-recursor/pdns/recursordist
 
+ADD builder-support/helpers/ /pdns/builder-support/helpers/
+RUN /pdns/builder-support/helpers/install_rust.sh
+
 RUN mkdir /sdist
 
 ARG BUILDER_VERSION
index 920cb4aebb78278fd31d50166316a265458186ba..1893a10fcc4080dc09bb28ece28dbe6a102d6cb2 100644 (file)
@@ -88,18 +88,20 @@ export RANLIB=gcc-ranlib
   --enable-systemd --with-systemd=%{_unitdir} \
   --without-net-snmp
 %endif
-%if 0%{?rhel} >= 7
-  --enable-dnscrypt \
+%if 0%{?rhel} >= 7 || 0%{?amzn} == 2023
   --enable-dnstap \
   --enable-dns-over-https \
   --enable-systemd --with-systemd=%{_unitdir} \
   --with-gnutls \
   --with-libcap \
-  --with-libsodium \
   --with-lua=%{lua_implementation} \
-  --with-net-snmp \
   --with-re2 \
-%if 0%{?rhel} >= 8
+%if 0%{?amzn} != 2023
+  --enable-dnscrypt \
+  --with-libsodium \
+  --with-net-snmp \
+%endif
+%if 0%{?rhel} >= 8 || 0%{?amzn} == 2023
   --enable-dns-over-quic \
   --with-quiche \
 %endif
@@ -114,7 +116,7 @@ make %{?_smp_mflags} check || (cat test-suite.log && false)
 %install
 %make_install
 install -d %{buildroot}/%{_sysconfdir}/dnsdist
-%if 0%{?rhel} >= 8
+%if 0%{?rhel} >= 8 || 0%{?amzn} == 2023
 install -Dm644 /usr/lib/libdnsdist-quiche.so %{buildroot}/%{_libdir}/libdnsdist-quiche.so
 %endif
 %{__mv} %{buildroot}%{_sysconfdir}/dnsdist/dnsdist.conf-dist %{buildroot}%{_sysconfdir}/dnsdist/dnsdist.conf
@@ -156,7 +158,8 @@ systemctl daemon-reload ||:
 %{!?_licensedir:%global license %%doc}
 %doc README.md
 %{_bindir}/*
-%if 0%{?rhel} >= 8
+%if 0%{?rhel} >= 8 || 0%{?amzn} == 2023
+%define __requires_exclude libdnsdist-quiche\\.so
 %{_libdir}/libdnsdist-quiche.so
 %endif
 %{_mandir}/man1/*
index 19d7021606f252c98e03918a1330e86769a4fea8..20273920062e6ef91e0bbbbc71518ed824aa17b3 100644 (file)
@@ -108,10 +108,17 @@ Store DNSSEC keys and metadata storage in another backend. See the
 Setting this option to ``yes`` makes PowerDNS ignore out of zone records
 when loading zone files.
 
-.. _setting-bind-supermasters:
+Autoprimary support (experimental)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-``bind-supermasters``
-~~~~~~~~~~~~~~~~~~~~~
+.. _setting-bind-autoprimaries:
+
+``bind-autoprimaries``
+~~~~~~~~~~~~~~~~~~~~~~
+
+.. versionchanged:: 4.9.0
+
+  This was called ``bind-supermasters`` before 4.9.0.
 
 Specifies file where to read list of autoprimaries.
 BIND backend only checks IP address of primary server.
@@ -120,20 +127,28 @@ 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:
+.. _setting-bind-autoprimary-config:
 
-``bind-supermaster-config``
+``bind-autoprimary-config``
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+.. versionchanged:: 4.9.0
+
+  This was called ``bind-supermaster-config`` before 4.9.0.
+
 When a new zone is configured via the autosecondary mechanism, bindbackend *writes* a zone entry to this file.
 
 Your ``bind-config`` file should have an ``include`` statement to make sure this file is read on startup.
 
-.. _setting-bind-supermaster-destdir:
+.. _setting-bind-autoprimary-destdir:
 
-``bind-supermaster-destdir``
+``bind-autoprimary-destdir``
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+.. versionchanged:: 4.9.0
+
+  This was called ``bind-supermaster-destdir`` before 4.9.0.
+
 Each new zone configured via the autosecondary mechanism gets a zone file in this directory.
 This directory must be writable.
 
index 3a18a4b5df2c7f2ca06babe05efc9d3296bfdfac..09f049c2217eaedd8c5305891fe665475f150f99 100644 (file)
@@ -29,23 +29,23 @@ To add a domain, issue the following::
 
 Records can now be added using ``pdnsutil add-record`` or ``pdnsutil edit-zone``.
 
-Slave operation
-^^^^^^^^^^^^^^^
+Secondary operation
+^^^^^^^^^^^^^^^^^^^
 
-These backends are fully slave capable. To become a slave of the
-'example.com' domain, using 198.51.100.6 as the master execute this::
+These backends are fully secondary capable. To become a secondary of the
+'example.com' domain, using 198.51.100.6 as the primary execute this::
 
-   pdnsutil create-slave-zone example.com 198.51.100.6
+   pdnsutil create-secondary-zone example.com 198.51.100.6
 
 And wait a while for PowerDNS to pick up the addition - which happens
 within one minute (this is determined by the
-:ref:`setting-slave-cycle-interval`
+:ref:`setting-xfr-cycle-interval`
 setting). There is no need to inform PowerDNS that a new domain was
 added. Typical output is::
 
-  Apr 09 13:34:29 All slave domains are fresh
-  Apr 09 13:35:29 1 slave domain needs checking
-  Apr 09 13:35:29 Domain example.com is stale, master serial 1, our serial 0
+  Apr 09 13:34:29 All secondary domains are fresh
+  Apr 09 13:35:29 1 secondary domain needs checking
+  Apr 09 13:35:29 Domain example.com is stale, primary serial 1, our serial 0
   Apr 09 13:35:30 [gPgSQLBackend] Connected to database
   Apr 09 13:35:30 AXFR started for 'example.com'
   Apr 09 13:35:30 AXFR done for 'example.com'
@@ -56,37 +56,37 @@ will respond accordingly for queries within that zone.
 
 Periodically, PowerDNS schedules checks to see if domains are still
 fresh. The default
-:ref:`setting-slave-cycle-interval` is 60
+:ref:`setting-xfr-cycle-interval` is 60
 seconds, large installations may need to raise this value. Once a domain
 has been checked, it will not be checked before its SOA refresh timer
 has expired. Domains whose status is unknown get checked every 60
 seconds by default.
 
-PowerDNS has support for multiple masters per zone, and also port numbers for these masters::
+PowerDNS has support for multiple primaries per zone, and also port numbers for these primaries::
 
-   pdnsutil create-slave-zone example.com 198.51.100.6 2001:0DB8:15:4AF::4
-   pdnsutil create-slave-zone example.net 198.51.100.20:5301 '[2001:0DB8:11:6E::4]:54'
+   pdnsutil create-secondary-zone example.com 198.51.100.6 2001:0DB8:15:4AF::4
+   pdnsutil create-secondary-zone example.net 198.51.100.20:5301 '[2001:0DB8:11:6E::4]:54'
 
-Superslave operation
-^^^^^^^^^^^^^^^^^^^^
+Autoprimary operation
+^^^^^^^^^^^^^^^^^^^^^
 
-To configure a :ref:`supermaster <supermaster-operation>` with IP address 203.0.113.53 which lists this
-installation as 'autoslave.example.com', issue the following::
+To configure a :ref:`autoprimary <supermaster-operation>` with IP address 203.0.113.53 which lists this
+installation as 'autosecondary.example.com', issue the following::
 
-    pdnsutil add-supermaster 203.0.113.53 autoslave.example.com internal
+    pdnsutil add-autoprimary 203.0.113.53 autosecondary.example.com internal
 
 From now on, valid notifies from 203.0.113.53 for which the zone lists an NS record
-containing 'autoslave.example.com' will lead to the provisioning of a
-slave domain under the account 'internal'. See :ref:`supermaster-operation`
+containing 'autosecondary.example.com' will lead to the provisioning of a
+secondary domain under the account 'internal'. See :ref:`autoprimary-operation`
 for details.
 
-Master operation
-^^^^^^^^^^^^^^^^
+Primary operation
+^^^^^^^^^^^^^^^^^
 
-The generic SQL backend is fully master capable with automatic discovery
+The generic SQL backend is fully primary capable with automatic discovery
 of serial changes. Raising the serial number of a domain suffices to
 trigger PowerDNS to send out notifications. To configure a domain for
-master operation instead of the default native replication, issue::
+primary operation instead of the default native replication, issue::
 
     pdnsutil create-zone example.com
     pdnsutil set-kind example.com MASTER
@@ -105,8 +105,8 @@ This value cannot be set with ``pdnsutil``.
 
 Effects: the record (or domain, respectively) will not be visible to DNS
 clients. The REST API will still see the record (or domain). Even if a
-domain is disabled, slaving still works. Slaving considers a disabled
-domain to have a serial of 0; this implies that a slaved domain will not
+domain is disabled, xfr still works. A secondary considers a disabled
+domain to have a serial of 0; this implies that a secondary domain will not
 stay disabled.
 
 .. _generic-sql-handling-dnssec-signed-zones:
@@ -300,37 +300,31 @@ Domain and zone manipulation
    a zone.
 -  ``remove-domain-key-query``: Called to remove a crypto key.
 
-Master/slave queries
-^^^^^^^^^^^^^^^^^^^^
+Primary/secondary queries
+^^^^^^^^^^^^^^^^^^^^^^^^^
 
-These queries are used to manipulate the master/slave information in the
+These queries are used to manipulate the primary/secondary information in the
 database. Most installations will have zero need to change the following
 queries.
 
-On masters
-~~~~~~~~~~
+On primaries
+~~~~~~~~~~~~
 
--  ``info-all-master-query``: Called to get data on all domains for
-   which the server is master.
--  ``update-serial-query`` Called to update the last notified serial of
-   a master domain.
+-  ``info-all-primary-query``: Called to get data on all domains for which the server is primary.
+-  ``update-serial-query`` Called to update the last notified serial of a primary domain.
 
-On slaves
-~~~~~~~~~
+On secondaries
+~~~~~~~~~~~~~~
 
--  ``info-all-slaves-query``: Called to retrieve all slave domains.
--  ``update-lastcheck-query``: Called to update the last time a slave
-   domain was successfully checked for freshness.
--  ``update-master-query``: Called to update the master address of a
-   domain.
+-  ``info-all-secondaries-query``: Called to retrieve all secondary domains.
+-  ``update-lastcheck-query``: Called to update the last time a secondary domain was successfully checked for freshness.
+-  ``update-primary-query``: Called to update the primary address of a domain.
 
-On superslaves
+On autoprimary
 ~~~~~~~~~~~~~~
 
--  ``supermaster-query``: Called to determine if a certain host is a
-   supermaster for a certain domain name.
--  ``supermaster-name-to-ips``: Called to the IP and account for a
-   supermaster.
+-  ``autoprimary-query``: Called to determine if a certain host is a autoprimary for a certain domain name.
+-  ``autoprimary-name-to-ips``: Called to the IP and account for a autoprimary.
 
 TSIG
 ^^^^
index e98aa1fa5528ac32354820143a9fbce20704d570..744bdd33071beac90cbb215327f72997feb4e1d0 100644 (file)
@@ -104,7 +104,7 @@ In the example below ``example.com`` is the member and ``catalog.example`` is th
 
 Setting catalog values is supported in the :doc:`API <http-api/zone>`, by setting the ``catalog`` property in the zone properties.
 
-Each member zone may have one or more additional properties as defined in the draft.
+Each member zone may have one or more additional properties as defined in the RFC.
 PowerDNS currently supports the following properties:
 
 - coo - A single DNSName
index 3a73eb4ddd73c7ec92eff66ba5f2c405ae51c003..8282b79e42c7723b0aa67941e8d9001cf01e5cc4 100644 (file)
@@ -263,7 +263,7 @@ lot of improvements and bug fixes and tremendously increases compliance.
 We want to explicitly thank Kees Monshouwer for digging up all the
 DNSSEC improvements and porting them back to this release.
 
-When upgrading, please run "pdnssec rectify-all-zones" and trigger an
+When upgrading, please run ``pdnssec rectify-all-zones`` and trigger an
 AXFR for all DNSSEC zones to make sure you benefit from all the
 compliance improvements present in this version.
 
@@ -1010,7 +1010,7 @@ Changes since 3.3
 -  `commit a7aa9be <https://github.com/PowerDNS/pdns/commit/a7aa9be>`__:
    Replace hardcoded make with variable
 -  `commit e4fe901 <https://github.com/PowerDNS/pdns/commit/e4fe901>`__:
-   make sure to run PKG\_PROG\_PKG\_CONFIG before the first PKG\_\*
+   make sure to run ``PKG_PROG_PKG_CONFIG`` before the first ``PKG_*``
    usage
 -  `commit 29bf169 <https://github.com/PowerDNS/pdns/commit/29bf169>`__:
    fix hmac-md5 TSIG key lookup
@@ -1103,7 +1103,7 @@ catering to their needs beyond the specifications.
 **Warning**: Version 3.3 of the PowerDNS Authoritative Server is a major
 upgrade if you are coming from 2.9.x. There are also some important
 changes if you are coming from 3.0, 3.1 or 3.2. Please refer to the
-`Upgrade documentation <authoritative/upgrading.md>`__ for important
+`Upgrade documentation <../upgrading.rst>`__ for important
 information on correct and stable operation, as well as notes on
 performance and memory use.
 
@@ -2179,7 +2179,7 @@ Changes between RC1 and RC2
 -  We imported the TinyDNS backend by Ruben d'Arco. Code mostly in
    `commit
    2559 <http://wiki.powerdns.com/projects/trac/changeset/2559>`__. See
-   `TinyDNS Backend <authoritative/backend-tinydns.md>`__.
+   `TinyDNS Backend <../backends/tinydns.rst>`__.
 -  Overriding C(XX)FLAGS is easier now. Problem pointed out by Jose
    Arthur Benetasso Villanova and others, fix suggested by Sten Spans.
    Patch in `commit
@@ -2748,13 +2748,10 @@ important protocol is among the easiest to use available. In addition,
 all important algorithms are supported.
 
 Complete detail can be found in `Serving authoritative DNSSEC
-data <authoritative/dnssec.md>`__. The goal of 'PowerDNSSEC' is to allow
-existing PowerDNS installations to start serving DNSSEC with as little
-hassle as possible, while maintaining performance and achieving high
-levels of security.
-
-Tutorials and examples of how to use DNSSEC in PowerDNS can be found
-linked from http://powerdnssec.org.
+data <../dnssec/intro.rst>`__. The goal of PowerDNS's DNSSEC support
+is to allow existing PowerDNS installations to start serving DNSSEC with
+as little hassle as possible, while maintaining performance and
+achieving high levels of security.
 
 PowerDNS Authoritative Server 3.0 development has been made possible by
 the financial and moral support of
@@ -2764,7 +2761,6 @@ the financial and moral support of
    DNS <http://www.ipcom.at/en/dns/rcodezero_anycast/>`__, a subsidiary
    of NIC.AT, the Austrian registry
 -  `SIDN, the Dutch registry <http://www.sidn.nl/>`__
--  .. (awaiting details) ..
 
 This release has received exceptional levels of community support, and
 we'd like to thank the following people in addition to those mentioned
@@ -4187,7 +4183,7 @@ job, and to let us know the results.
 
 Additionally, the bind2backend is almost ready to replace the stock bind
 backend. If you run with Bind zones, you are cordially invited to
-substitute 'launch=bind2' for 'launch=bind'. This will happen
+substitute ``launch=bind2`` for ``launch=bind``. This will happen
 automatically in 2.9.19!
 
 In other news, the entire Wikipedia constellation now runs on PowerDNS
@@ -4263,7 +4259,7 @@ Improvements
 Recursor improvements and fixes.
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-See `Recursion <authoritative/recursion.md>`__ for details. The changes
+See `Recursion <../guides/recursion.rst>`__ for details. The changes
 below mean that all of the caveats listed for the recursor have now been
 addressed.
 
@@ -4502,7 +4498,7 @@ Improvements
 -  PostgreSQL now only depends on the C API and not on the deprecated
    C++ one
 -  PowerDNS can now fully overrule external zones when doing recursion.
-   See `Recursion <authoritative/recursion.md>`__.
+   See `Recursion <../guides/recursion.rst>`__.
 
 Version 2.9.13
 --------------
@@ -4853,7 +4849,7 @@ However, this turns out to not be that bad at all. The recursor can now
 be restarted without having to restart the rest of the nameserver, for
 example. Cooperation between the both halves of PowerDNS is also almost
 seamless. As a result, 'non-lazy recursion' has been dropped. See
-`Recursion <authoritative/recursion.md>`__ for more details.
+`Recursion <../guides/recursion.rst>`__ for more details.
 
 Furthermore, the recursor only works on Linux, Windows and Solaris (not
 entirely). FreeBSD does not support the required functions. If you know
@@ -4945,7 +4941,7 @@ From this, it is apparent that far more people are interested in
 PowerDNS than yet know about it. So spread the word!
 
 In other news, we now have a security page at
-`Security <security/index.md>`__. Furthermore, Maurice Nonnekes
+`Security <../security.rst>`__. Furthermore, Maurice Nonnekes
 contributed an OpenBSD port! See `his
 page <http://www.codeninja.nl/openbsd/powerdns/>`__ for more details!
 
@@ -5069,9 +5065,9 @@ instructions. Without instructions, the right things also happen, but
 the operator is in charge.
 
 For more about all this coolness, see
-`“pdns\_control” <authoritative/running.md#pdnscontrol>`__ and
+`“pdns\_control” <running.rst#pdnscontrol>`__ and
 `“pdns\_control
-commands” <authoritative/backend-bind.md#bind-control-commands>`__.
+commands” <backends/bind.rst#bind-control-commands>`__.
 
 **Warning**: Again some changes in compilation instructions. The hybrid
 pgmysql backend has been split up into 'gmysql' and 'gpgsql', sharing a
@@ -5423,7 +5419,7 @@ release fixing a huge memory leak in the new Query Cache.
 
 Developers: this version needs the new pdns-2.5.1 development kit,
 available on http://downloads.powerdns.com/releases/dev. See also
-`Backend writers' guide <appendix/backend-writers-guide.md>`__.
+`Backend writers' guide <../appendices/backend-writers-guide.rst>`__.
 
 And some small changes
 
@@ -5480,7 +5476,7 @@ New features
    The webserver also displays the efficiency of the new Query Cache.
 
    The old Packet Cache is still there (and useful) but see
-   `Authoritative Server Performance <authoritative/performance.md>`__
+   `Authoritative Server Performance <../performance.rst>`__
    for more details.
 
 -  There is now the ability to shut off some logging at a very early
@@ -5538,7 +5534,7 @@ Version 2.4
 
 Developers: this version is compatible with the pdns-2.1 development
 kit, available on http://downloads.powerdns.com/releases/dev. See also
-`*Backend writers' guide* <appendix/backend-writers-guide.md>`__.
+`*Backend writers' guide* <../appendices/backend-writers-guide.rst>`__.
 
 This version fixes some stability issues with malformed or malcrafted
 packets. An upgrade is advised. Furthermore, there are interesting new
@@ -5585,7 +5581,7 @@ Version 2.3
 
 Developers: this version is compatible with the pdns-2.1 development
 kit, available on http://downloads.powerdns.com/releases/dev. See also
-`Backend writers' guide <appendix/backend-writers-guide.md>`__
+`Backend writers' guide <../appendices/backend-writers-guide.rst>`__
 
 This release adds the Generic MySQL backend which allows full
 master/slave semantics with MySQL and InnoDB tables (or other tables
@@ -5627,7 +5623,7 @@ Version 2.2
 
 Developers: this version is compatible with the pdns-2.1 development
 kit, available on http://downloads.powerdns.com/releases/dev. See also
-`Backend writers' guide <appendix/backend-writers-guide.md>`__
+`Backend writers' guide <../appendices/backend-writers-guide.rst>`__
 
 Again a big release. PowerDNS is seeing some larger deployments in more
 demanding environments and these are helping shake out remaining issues,
@@ -5668,12 +5664,12 @@ New features
 -  **pdns\_control purge** can now also purge based on suffix, allowing
    operators to purge an entire domain from the packet cache instead of
    only specific records. See also
-   `pdns\_control <authoritative/running.md#pdnscontrol>`__ Thanks to
+   `pdns\_control <running.rst#pdnscontrol>`__ Thanks to
    Mike Benoit for this suggestion.
 -  **soa-serial-offset** for installations with small SOA serial numbers
    wishing to register .DE domains with DENIC which demands six-figure
    SOA serial numbers. See also `Chapter 21, *Index of all Authoritative
-   Server settings* <authoritative/settings.md>`__.
+   Server settings* <../settings.rst>`__.
 
 Version 2.1
 -----------
@@ -5724,7 +5720,7 @@ Unexpected behaviour
    with user expectations. If a recursive question can be answered
    entirely from local data, it is. To restore old behaviour, disable
    **lazy-recursion**. Also see
-   `Recursion <authoritative/recursion.md>`__.
+   `Recursion <../guides/recursion.rst>`__.
 
 Features
 ^^^^^^^^
@@ -5737,13 +5733,13 @@ Features
 -  Zone2sql now accepts ^^transactions to wrap zones in a transaction
    for PostgreSQL and Oracle output. This is a major speedup and also
    makes for better isolation of inserts. See
-   `Zone2sql <authoritative/migration.md#zone2sql>`__.
+   `Zone2sql <migration.rst#zone2sql>`__.
 -  **pdns\_control** now has the ability to purge the PowerDNS cache or
    parts of it. This enables operators to raise the TTL of the Packet
    Cache to huge values and only to invalidate the cache when changes
    are made. See also `Authoritative Server
-   Performance <authoritative/performance.md>`__ and
-   `pdns\_control <authoritative/running.md#pdnscontrol>`__.
+   Performance <../performance.rst>`__ and
+   `pdns\_control <../running.rst#pdnscontrol>`__.
 
 Version 2.0.1
 -------------
@@ -5929,15 +5925,15 @@ Features
 ^^^^^^^^
 
 -  pdns\_control (see
-   `pdns\_control <authoritative/running.md#pdnscontrol>`__) now opens
+   `pdns\_control <running.rst#pdnscontrol>`__) now opens
    the local end of its socket in ``/tmp`` instead of next to the remote
    socket (by default ``/var/run``). This eases the way for allowing
    non-root access to pdns\_control. When running chrooted (see
    `Chapter 7, *Security settings &
-   considerations* <common/security.md>`__), the local socket again
+   considerations* <../security.rst>`__), the local socket again
    moves back to ``/var/run``.
 -  pdns\_control now has a 'version' command. See `Section 1.1,
-   “pdns\_control” <authoritative/running.md#pdnscontrol>`__.
+   “pdns\_control” <../running.rst#pdnscontrol>`__.
 
 Version 1.99.11 Prerelease
 --------------------------
@@ -6049,7 +6045,7 @@ Features
    `Supermaster automatic provisioning of
    slaves <authoritative/modes-of-operation.md#supermaster>`__.
 -  Recursing backend can now live on a non-standard (!=53) port. See
-   `Recursion <authoritative/recursion.md>`__.
+   `Recursion <../guides/recursion.rst>`__.
 -  Slave zone retrieval is now queued instead of immediate, which scales
    better and is more resilient to temporary failures.
 -  **max-queue-length** parameter. If this many packets are queued for
@@ -6097,17 +6093,17 @@ Bugs fixed
 Feature enhancements
 ^^^^^^^^^^^^^^^^^^^^
 
--  Recursing backend. See `Recursion <authoritative/recursion.md>`__.
+-  Recursing backend. See `Recursion <../guides/recursion.rst>`__.
    Allows recursive and authoritative DNS on the same IP address.
--  `NAPTR support <types.md#naptr>`__, which is especially useful for
+-  `NAPTR support <appendices/types.rst#naptr>`__, which is especially useful for
    the ENUM/E.164 community.
 -  Zone transfers can now be allowed per `netmask instead of only per IP
-   address <authoritative/settings.md#allow-axfr-ips>`__.
+   address <../settings.rst#allow-axfr-ips>`__.
 -  Preliminary support for slave operation included. Only for the
    adventurous right now! See `Slave
-   operation <authoritative/modes-of-operation.md>`__
+   operation <../modes-of-operation.rst>`__
 -  All record types now documented, see `Supported record types and
-   their storage <types.md>`__.
+   their storage <../appendices/types.rst>`__.
 
 Known bugs
 ^^^^^^^^^^
index 8f155e9533a48dff3dcc41c5ce7b71c67249c601..f43b1741e0fdf23f0111a58ba89179e86e392de8 100644 (file)
@@ -4,7 +4,7 @@ DNSSEC advice & precautions
 DNSSEC is a major change in the way DNS works. Furthermore, there is a
 bewildering array of settings that can be configured.
 
-It is well possible to configure DNSSEC in such a way that your domain
+It is easy to (mis)configure DNSSEC in such a way that your domain
 will not operate reliably, or even, at all. We advise operators to stick
 to the keying defaults of ``pdnsutil secure-zone``.
 
index 1851d317a8438d2161b9a3b36fd5b57544e7c21f..7855c45d3ca198681c079bbd8441f9b0551f0825 100644 (file)
@@ -88,4 +88,4 @@ many people. We would like to thank:
 -  Morten Stevens
 -  Pieter Lexis
 
-This list is far from complete yet ..
+and everyone else who contributed to making this possible.
index 239b67460a8f5d02c3ce92fac7b8c9454e02ee4f..2b2a0fc0fef776a6ad922d583d9c48540508399a 100644 (file)
@@ -4,9 +4,9 @@ A brief introduction to DNSSEC
 DNSSEC is a complicated subject, but it is not required to know all the
 ins and outs of this protocol to be able to use PowerDNS. In this
 section, we explain the core concepts that are needed to operate a
-PowerDNSSEC installation.
+PowerDNS installation with DNSSEC.
 
-Zone material is enhanced with signatures using 'keys'. Such a signature
+Zone material is enhanced with signatures using ``keys``. Such a signature
 (called an RRSIG) is a cryptographic guarantee that the data served is
 the original data. DNSSEC keys are asymmetric (RSA, DSA, ECSDA or GOST),
 the public part is published in DNS and is called a DNSKEY record, and
@@ -24,29 +24,29 @@ Once the parent zone has the DS, and the zone is signed with the DNSSEC
 key, we are done in theory.
 
 However, for a variety of reasons, most DNSSEC operations run with
-another layer of keys. The so called 'Key Signing Key' is sent to the
+another layer of keys. The so called ``Key Signing Key`` is sent to the
 parent zone, and this Key Signing Key is used to sign a new set of keys
 called the Zone Signing Keys.
 
 This setup allows us to change our keys without having to tell the zone
 operator about it.
 
-A final challenge is how to DNSSEC sign the answer 'no such domain'. In
-the language of DNS, the way to say 'there is no such domain' (NXDOMAIN)
+A final challenge is how to DNSSEC sign the answer *no such domain*. In
+the language of DNS, the way to say *there is no such domain* (``NXDOMAIN``)
 or there is no such record type is to send an empty answer. Such empty
 answers are universal, and can't be signed.
 
-In DNSSEC parlance we therefore sign a record that says 'there are no
-domains between A.powerdnssec.org and C.powerdnssec.org'. This securely
-tells the world that B.powerdnssec.org does not exist. This solution is
-called NSEC, and is simple but has downsides - it also tells the world
+In DNSSEC parlance we therefore sign a record that says *there are no
+domains between* ``A.powerdnssec.org`` *and* ``C.powerdnssec.org``. This securely
+tells the world that ``B.powerdnssec.org`` does not exist. This solution is
+called ``NSEC``, and is simple but has downsides - it also tells the world
 exactly which records DO exist.
 
 So alternatively, we can say that if a certain mathematical operation
-(an 'iterated salted hash') is performed on a question, that no valid
+(an *iterated salted hash*) is performed on a question, that no valid
 answers exist that have as outcome of this operation an answer between
-two very large numbers. This leads to the same 'proof of non-existence'.
-This solution is called NSEC3.
+two very large numbers. This leads to the same *proof of non-existence*.
+This solution is called ``NSEC3``.
 
-A PowerDNS zone can either be operated in NSEC or in one of two NSEC3
-modes ('inclusive' and 'narrow').
+A PowerDNS zone can either be operated in ``NSEC`` or in one of two ``NSEC3``
+modes (``inclusive`` and ``narrow``).
index 77be30811aaf94d49b782a8e3a57c9ef023bd845..92beab49c54478facafa46a8110d7e3fd09722d1 100644 (file)
@@ -66,7 +66,7 @@ OTHER Options
     List all options
 --on-error-resume-next
     Ignore missing zone files during parsing. Dangerous.
---slave
+--secondary
     Maintain slave status of zones listed in named.conf as being slaves.
     The default behaviour is to convert all zones to native operation.
 --verbose
index 6d01d5aa5d841db391274ae6f25327573329eccb..55786b4c947154bd313473bb1ed6d39a35979695 100644 (file)
@@ -112,7 +112,7 @@ For backends supporting slave operation, there is also an option to keep
 slave zones as slaves, and not convert them to native operation.
 
 ``zone2sql`` can generate SQL for nearly all the Generic SQL backends.
-See `its manpage <manpages/zone2sql.1>` for more information.
+See :doc:`its manpage <manpages/zone2sql.1>` for more information.
 
 An example call to ``zone2sql`` could be:
 
index b8983a8cc42fe25be5f0bfb5f23c16bcf100bb0c..4f78338b4cd4207886e7ba9da460070c45372afa 100644 (file)
@@ -1,4 +1,4 @@
-@       86400   IN  SOA pdns-public-ns1.powerdns.com. peter\.van\.dijk.powerdns.com. 2023101701 10800 3600 604800 10800
+@       86400   IN  SOA pdns-public-ns1.powerdns.com. peter\.van\.dijk.powerdns.com. 2023111000 10800 3600 604800 10800
 @       3600    IN  NS  pdns-public-ns1.powerdns.com.
 @       3600    IN  NS  pdns-public-ns2.powerdns.com.
 
@@ -359,8 +359,10 @@ recursor-4.9.0-beta1.security-status                    60 IN TXT "2 Unsupported
 recursor-4.9.0-rc1.security-status                      60 IN TXT "2 Unsupported pre-release"
 recursor-4.9.0.security-status                          60 IN TXT "1 OK"
 recursor-4.9.1.security-status                          60 IN TXT "1 OK"
+recursor-4.9.2.security-status                          60 IN TXT "1 OK"
 recursor-5.0.0-alpha1.security-status                   60 IN TXT "2 Unsupported pre-release"
-recursor-5.0.0-alpha2.security-status                   60 IN TXT "1 Unsupported pre-release"
+recursor-5.0.0-alpha2.security-status                   60 IN TXT "2 Unsupported pre-release"
+recursor-5.0.0-beta1.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/"
@@ -520,4 +522,6 @@ dnsdist-1.8.0-rc3.security-status                          60 IN TXT "3 Unsuppor
 dnsdist-1.8.0.security-status                              60 IN TXT "3 Upgrade now, see https://blog.cloudflare.com/technical-breakdown-http2-rapid-reset-ddos-attack/"
 dnsdist-1.8.1.security-status                              60 IN TXT "3 Upgrade now, see https://blog.cloudflare.com/technical-breakdown-http2-rapid-reset-ddos-attack/"
 dnsdist-1.8.2.security-status                              60 IN TXT "1 OK"
-dnsdist-1.9.0-alpha1.security-status                       60 IN TXT "1 Unsupported pre-release (known vulnerabilities)"
+dnsdist-1.9.0-alpha1.security-status                       60 IN TXT "3 Unsupported pre-release (known vulnerabilities)"
+dnsdist-1.9.0-alpha2.security-status                       60 IN TXT "1 Unsupported pre-release (no known vulnerabilities)"
+dnsdist-1.9.0-alpha3.security-status                       60 IN TXT "1 Unsupported pre-release (no known vulnerabilities)"
index fc65427a014880bfcc7e0c2e7986e2556be83660..f1fed5ace31e60e25c1912a6fd0964fa05c473f1 100644 (file)
@@ -8,6 +8,45 @@ 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.
 
+4.8.0 to 4.9.0
+--------------
+
+Removed options
+^^^^^^^^^^^^^^^
+
+Various settings, deprecated since 4.5.0, have been removed.
+
+* :ref:`setting-allow-unsigned-supermaster` is now :ref:`setting-allow-unsigned-autoprimary`
+* :ref:`setting-master` is now :ref:`setting-primary`
+* :ref:`setting-slave-cycle-interval` is now :ref:`setting-xfr-cycle-interval`
+* :ref:`setting-slave-renotify` is now :ref:`setting-secondary-do-renotify`
+* :ref:`setting-slave` is now :ref:`setting-secondary`
+* :ref:`setting-superslave` is now :ref:`setting-autosecondary`
+
+Renamed options
+^^^^^^^^^^^^^^^
+
+Bind backend
+~~~~~~~~~~~~
+
+Various experimental autoprimary settings have been renamed.
+
+* ``supermaster-config`` is now ``autoprimary-config``
+* ``supermasters`` is now ``autoprimaries``
+* ``supermaster-destdir`` is now ``autoprimary-destdir``
+
+Gsql backends
+~~~~~~~~~~~~~
+
+Various custom queries have been renamed.
+
+* ``info-all-slaves-query`` is now ``info-all-secondaries-query``
+* ``supermaster-query`` is now ``autoprimary-query``
+* ``supermaster-name-to-ips`` is now ``autoprimary-name-to-ips``
+* ``supermaster-add`` is now ``autoprimary-add``
+* ``update-master-query`` is now ``update-primary-query``
+* ``info-all-master-query`` is now ``info-all-primary-query``
+
 any version to 4.8.x
 --------------------
 
index 6b93b3b7cfaf1bd994b02ff19475b420130a27b6..67292869efea591cbce9a86100806cc432411a8a 100644 (file)
@@ -78,7 +78,7 @@ namespace LMDBLS {
 
 #endif /* #ifndef DNSDIST */
 
-MDBDbi::MDBDbi(MDB_env* env, MDB_txn* txn, const string_view dbname, int flags)
+MDBDbi::MDBDbi(MDB_env* /* env */, MDB_txn* txn, const string_view dbname, int flags) : d_dbi(-1)
 {
   // A transaction that uses this function must finish (either commit or abort) before any other transaction in the process may use this function.
 
diff --git a/m4/ax_compare_version.m4 b/m4/ax_compare_version.m4
new file mode 100644 (file)
index 0000000..ffb4997
--- /dev/null
@@ -0,0 +1,177 @@
+# ===========================================================================
+#    https://www.gnu.org/software/autoconf-archive/ax_compare_version.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_COMPARE_VERSION(VERSION_A, OP, VERSION_B, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
+#
+# DESCRIPTION
+#
+#   This macro compares two version strings. Due to the various number of
+#   minor-version numbers that can exist, and the fact that string
+#   comparisons are not compatible with numeric comparisons, this is not
+#   necessarily trivial to do in a autoconf script. This macro makes doing
+#   these comparisons easy.
+#
+#   The six basic comparisons are available, as well as checking equality
+#   limited to a certain number of minor-version levels.
+#
+#   The operator OP determines what type of comparison to do, and can be one
+#   of:
+#
+#    eq  - equal (test A == B)
+#    ne  - not equal (test A != B)
+#    le  - less than or equal (test A <= B)
+#    ge  - greater than or equal (test A >= B)
+#    lt  - less than (test A < B)
+#    gt  - greater than (test A > B)
+#
+#   Additionally, the eq and ne operator can have a number after it to limit
+#   the test to that number of minor versions.
+#
+#    eq0 - equal up to the length of the shorter version
+#    ne0 - not equal up to the length of the shorter version
+#    eqN - equal up to N sub-version levels
+#    neN - not equal up to N sub-version levels
+#
+#   When the condition is true, shell commands ACTION-IF-TRUE are run,
+#   otherwise shell commands ACTION-IF-FALSE are run. The environment
+#   variable 'ax_compare_version' is always set to either 'true' or 'false'
+#   as well.
+#
+#   Examples:
+#
+#     AX_COMPARE_VERSION([3.15.7],[lt],[3.15.8])
+#     AX_COMPARE_VERSION([3.15],[lt],[3.15.8])
+#
+#   would both be true.
+#
+#     AX_COMPARE_VERSION([3.15.7],[eq],[3.15.8])
+#     AX_COMPARE_VERSION([3.15],[gt],[3.15.8])
+#
+#   would both be false.
+#
+#     AX_COMPARE_VERSION([3.15.7],[eq2],[3.15.8])
+#
+#   would be true because it is only comparing two minor versions.
+#
+#     AX_COMPARE_VERSION([3.15.7],[eq0],[3.15])
+#
+#   would be true because it is only comparing the lesser number of minor
+#   versions of the two values.
+#
+#   Note: The characters that separate the version numbers do not matter. An
+#   empty string is the same as version 0. OP is evaluated by autoconf, not
+#   configure, so must be a string, not a variable.
+#
+#   The author would like to acknowledge Guido Draheim whose advice about
+#   the m4_case and m4_ifvaln functions make this macro only include the
+#   portions necessary to perform the specific comparison specified by the
+#   OP argument in the final configure script.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Tim Toolan <toolan@ele.uri.edu>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 13
+
+dnl #########################################################################
+AC_DEFUN([AX_COMPARE_VERSION], [
+  AC_REQUIRE([AC_PROG_AWK])
+
+  # Used to indicate true or false condition
+  ax_compare_version=false
+
+  # Convert the two version strings to be compared into a format that
+  # allows a simple string comparison.  The end result is that a version
+  # string of the form 1.12.5-r617 will be converted to the form
+  # 0001001200050617.  In other words, each number is zero padded to four
+  # digits, and non digits are removed.
+  AS_VAR_PUSHDEF([A],[ax_compare_version_A])
+  A=`echo "$1" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \
+                     -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \
+                     -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \
+                     -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \
+                     -e 's/[[^0-9]]//g'`
+
+  AS_VAR_PUSHDEF([B],[ax_compare_version_B])
+  B=`echo "$3" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \
+                     -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \
+                     -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \
+                     -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \
+                     -e 's/[[^0-9]]//g'`
+
+  dnl # In the case of le, ge, lt, and gt, the strings are sorted as necessary
+  dnl # then the first line is used to determine if the condition is true.
+  dnl # The sed right after the echo is to remove any indented white space.
+  m4_case(m4_tolower($2),
+  [lt],[
+    ax_compare_version=`echo "x$A
+x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/false/;s/x${B}/true/;1q"`
+  ],
+  [gt],[
+    ax_compare_version=`echo "x$A
+x$B" | sed 's/^ *//' | sort | sed "s/x${A}/false/;s/x${B}/true/;1q"`
+  ],
+  [le],[
+    ax_compare_version=`echo "x$A
+x$B" | sed 's/^ *//' | sort | sed "s/x${A}/true/;s/x${B}/false/;1q"`
+  ],
+  [ge],[
+    ax_compare_version=`echo "x$A
+x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"`
+  ],[
+    dnl Split the operator from the subversion count if present.
+    m4_bmatch(m4_substr($2,2),
+    [0],[
+      # A count of zero means use the length of the shorter version.
+      # Determine the number of characters in A and B.
+      ax_compare_version_len_A=`echo "$A" | $AWK '{print(length)}'`
+      ax_compare_version_len_B=`echo "$B" | $AWK '{print(length)}'`
+
+      # Set A to no more than B's length and B to no more than A's length.
+      A=`echo "$A" | sed "s/\(.\{$ax_compare_version_len_B\}\).*/\1/"`
+      B=`echo "$B" | sed "s/\(.\{$ax_compare_version_len_A\}\).*/\1/"`
+    ],
+    [[0-9]+],[
+      # A count greater than zero means use only that many subversions
+      A=`echo "$A" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"`
+      B=`echo "$B" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"`
+    ],
+    [.+],[
+      AC_WARNING(
+        [invalid OP numeric parameter: $2])
+    ],[])
+
+    # Pad zeros at end of numbers to make same length.
+    ax_compare_version_tmp_A="$A`echo $B | sed 's/./0/g'`"
+    B="$B`echo $A | sed 's/./0/g'`"
+    A="$ax_compare_version_tmp_A"
+
+    # Check for equality or inequality as necessary.
+    m4_case(m4_tolower(m4_substr($2,0,2)),
+    [eq],[
+      test "x$A" = "x$B" && ax_compare_version=true
+    ],
+    [ne],[
+      test "x$A" != "x$B" && ax_compare_version=true
+    ],[
+      AC_WARNING([invalid OP parameter: $2])
+    ])
+  ])
+
+  AS_VAR_POPDEF([A])dnl
+  AS_VAR_POPDEF([B])dnl
+
+  dnl # Execute ACTION-IF-TRUE / ACTION-IF-FALSE.
+  if test "$ax_compare_version" = "true" ; then
+    m4_ifvaln([$4],[$4],[:])dnl
+    m4_ifvaln([$5],[else $5])dnl
+  fi
+]) dnl AX_COMPARE_VERSION
index f9e53a64ecf40a0b58aafa580d001ca6469e59ce..481658453c72701fa1374a89396e0ec76b38e94d 100644 (file)
@@ -78,7 +78,7 @@ SharedLockGuarded<Bind2Backend::state_t> Bind2Backend::s_state;
 int Bind2Backend::s_first = 1;
 bool Bind2Backend::s_ignore_broken_records = false;
 
-std::mutex Bind2Backend::s_supermaster_config_lock; // protects writes to config file
+std::mutex Bind2Backend::s_autosecondary_config_lock; // protects writes to config file
 std::mutex Bind2Backend::s_startup_lock;
 string Bind2Backend::s_binddirectory;
 
@@ -235,8 +235,8 @@ bool Bind2Backend::startTransaction(const DNSName& qname, int id)
     fd = -1;
 
     *d_of << "; Written by PowerDNS, don't edit!" << endl;
-    *d_of << "; Zone '" << bbd.d_name << "' retrieved from master " << endl
-          << "; at " << nowTime() << endl; // insert master info here again
+    *d_of << "; Zone '" << bbd.d_name << "' retrieved from primary " << endl
+          << "; at " << nowTime() << endl; // insert primary info here again
 
     return true;
   }
@@ -298,7 +298,7 @@ bool Bind2Backend::feedRecord(const DNSResourceRecord& rr, const DNSName& /* ord
     throw DBException("out-of-zone data '" + rr.qname.toLogString() + "' during AXFR of zone '" + d_transaction_qname.toLogString() + "'");
   }
 
-  shared_ptr<DNSRecordContent> drc(DNSRecordContent::mastermake(rr.qtype.getCode(), QClass::IN, rr.content));
+  shared_ptr<DNSRecordContent> drc(DNSRecordContent::make(rr.qtype.getCode(), QClass::IN, rr.content));
   string content = drc->getZoneRepresentation();
 
   // SOA needs stripping too! XXX FIXME - also, this should not be here I think
@@ -318,14 +318,14 @@ bool Bind2Backend::feedRecord(const DNSResourceRecord& rr, const DNSName& /* ord
   return true;
 }
 
-void Bind2Backend::getUpdatedMasters(vector<DomainInfo>& changedDomains, std::unordered_set<DNSName>& /* catalogs */, CatalogHashMap& /* catalogHashes */)
+void Bind2Backend::getUpdatedPrimaries(vector<DomainInfo>& changedDomains, std::unordered_set<DNSName>& /* catalogs */, CatalogHashMap& /* catalogHashes */)
 {
   vector<DomainInfo> consider;
   {
     auto state = s_state.read_lock();
 
     for (const auto& i : *state) {
-      if (i.d_kind != DomainInfo::Master && this->alsoNotify.empty() && i.d_also_notify.empty())
+      if (i.d_kind != DomainInfo::Primary && this->alsoNotify.empty() && i.d_also_notify.empty())
         continue;
 
       DomainInfo di;
@@ -334,7 +334,7 @@ void Bind2Backend::getUpdatedMasters(vector<DomainInfo>& changedDomains, std::un
       di.last_check = i.d_lastcheck;
       di.notified_serial = i.d_lastnotified;
       di.backend = this;
-      di.kind = DomainInfo::Master;
+      di.kind = DomainInfo::Primary;
       consider.push_back(std::move(di));
     }
   }
@@ -377,7 +377,7 @@ void Bind2Backend::getAllDomains(vector<DomainInfo>* domains, bool getSerial, bo
       di.zone = i.d_name;
       di.last_check = i.d_lastcheck;
       di.kind = i.d_kind;
-      di.masters = i.d_masters;
+      di.primaries = i.d_primaries;
       di.backend = this;
       domains->push_back(std::move(di));
     };
@@ -399,22 +399,22 @@ void Bind2Backend::getAllDomains(vector<DomainInfo>* domains, bool getSerial, bo
   }
 }
 
-void Bind2Backend::getUnfreshSlaveInfos(vector<DomainInfo>* unfreshDomains)
+void Bind2Backend::getUnfreshSecondaryInfos(vector<DomainInfo>* unfreshDomains)
 {
   vector<DomainInfo> domains;
   {
     auto state = s_state.read_lock();
     domains.reserve(state->size());
     for (const auto& i : *state) {
-      if (i.d_kind != DomainInfo::Slave)
+      if (i.d_kind != DomainInfo::Secondary)
         continue;
       DomainInfo sd;
       sd.id = i.d_id;
       sd.zone = i.d_name;
-      sd.masters = i.d_masters;
+      sd.primaries = i.d_primaries;
       sd.last_check = i.d_lastcheck;
       sd.backend = this;
-      sd.kind = DomainInfo::Slave;
+      sd.kind = DomainInfo::Secondary;
       domains.push_back(std::move(sd));
     }
   }
@@ -444,7 +444,7 @@ bool Bind2Backend::getDomainInfo(const DNSName& domain, DomainInfo& di, bool get
 
   di.id = bbd.d_id;
   di.zone = domain;
-  di.masters = bbd.d_masters;
+  di.primaries = bbd.d_primaries;
   di.last_check = bbd.d_lastcheck;
   di.backend = this;
   di.kind = bbd.d_kind;
@@ -624,19 +624,19 @@ static void printDomainExtendedStatus(ostringstream& ret, const BB2DomainInfo& i
   ret << "\t On-disk file: " << info.d_filename << " (" << info.d_ctime << ")" << std::endl;
   ret << "\t Kind: ";
   switch (info.d_kind) {
-  case DomainInfo::Master:
-    ret << "Master";
+  case DomainInfo::Primary:
+    ret << "Primary";
     break;
-  case DomainInfo::Slave:
-    ret << "Slave";
+  case DomainInfo::Secondary:
+    ret << "Secondary";
     break;
   default:
     ret << "Native";
   }
   ret << std::endl;
-  ret << "\t Masters: " << std::endl;
-  for (const auto& master : info.d_masters) {
-    ret << "\t\t - " << master.toStringWithPort() << std::endl;
+  ret << "\t Primaries: " << std::endl;
+  for (const auto& primary : info.d_primaries) {
+    ret << "\t\t - " << primary.toStringWithPort() << std::endl;
   }
   ret << "\t Also Notify: " << std::endl;
   for (const auto& also : info.d_also_notify) {
@@ -955,17 +955,17 @@ void Bind2Backend::loadConfig(string* status) // NOLINT(readability-function-cog
       // overwrite what we knew about the domain
       bbd.d_name = domain.name;
       bool filenameChanged = (bbd.d_filename != domain.filename);
-      bool addressesChanged = (bbd.d_masters != domain.masters || bbd.d_also_notify != domain.alsoNotify);
+      bool addressesChanged = (bbd.d_primaries != domain.primaries || bbd.d_also_notify != domain.alsoNotify);
       bbd.d_filename = domain.filename;
-      bbd.d_masters = domain.masters;
+      bbd.d_primaries = domain.primaries;
       bbd.d_also_notify = domain.alsoNotify;
 
       DomainInfo::DomainKind kind = DomainInfo::Native;
       if (domain.type == "primary" || domain.type == "master") {
-        kind = DomainInfo::Master;
+        kind = DomainInfo::Primary;
       }
       if (domain.type == "secondary" || domain.type == "slave") {
-        kind = DomainInfo::Slave;
+        kind = DomainInfo::Secondary;
       }
 
       bool kindChanged = (bbd.d_kind != kind);
@@ -992,7 +992,7 @@ void Bind2Backend::loadConfig(string* status) // NOLINT(readability-function-cog
         catch (std::system_error& ae) {
           ostringstream msg;
           if (ae.code().value() == ENOENT && isNew && domain.type == "slave")
-            msg << " error at " + nowTime() << " no file found for new slave domain '" << domain.name << "'. Has not been AXFR'd yet";
+            msg << " error at " + nowTime() << " no file found for new secondary domain '" << domain.name << "'. Has not been AXFR'd yet";
           else
             msg << " error at " + nowTime() + " parsing '" << domain.name << "' from file '" << domain.filename << "': " << ae.what();
 
@@ -1197,7 +1197,7 @@ void Bind2Backend::lookup(const QType& qtype, const DNSName& qname, int zoneId,
 
   if (!bbd.d_loaded) {
     d_handle.reset();
-    throw DBException("Zone for '" + d_handle.domain.toLogString() + "' in '" + bbd.d_filename + "' not loaded (file missing, corrupt or master dead)"); // fsck
+    throw DBException("Zone for '" + d_handle.domain.toLogString() + "' in '" + bbd.d_filename + "' not loaded (file missing, corrupt or primary dead)"); // fsck
   }
 
   d_handle.d_records = bbd.d_records.get();
@@ -1331,12 +1331,12 @@ bool Bind2Backend::handle::get_list(DNSResourceRecord& r)
 
 bool Bind2Backend::autoPrimariesList(std::vector<AutoPrimary>& primaries)
 {
-  if (getArg("supermaster-config").empty())
+  if (getArg("autoprimary-config").empty())
     return false;
 
-  ifstream c_if(getArg("supermasters"), std::ios::in);
+  ifstream c_if(getArg("autoprimaries"), std::ios::in);
   if (!c_if) {
-    g_log << Logger::Error << "Unable to open supermasters file for read: " << stringerror() << endl;
+    g_log << Logger::Error << "Unable to open autoprimaries file for read: " << stringerror() << endl;
     return false;
   }
 
@@ -1354,15 +1354,15 @@ bool Bind2Backend::autoPrimariesList(std::vector<AutoPrimary>& primaries)
   return true;
 }
 
-bool Bind2Backend::superMasterBackend(const string& ip, const DNSName& /* domain */, const vector<DNSResourceRecord>& /* nsset */, string* /* nameserver */, string* account, DNSBackend** db)
+bool Bind2Backend::autoPrimaryBackend(const string& ip, const DNSName& /* domain */, const vector<DNSResourceRecord>& /* nsset */, string* /* nameserver */, string* account, DNSBackend** db)
 {
   // Check whether we have a configfile available.
-  if (getArg("supermaster-config").empty())
+  if (getArg("autoprimary-config").empty())
     return false;
 
-  ifstream c_if(getArg("supermasters").c_str(), std::ios::in); // this was nocreate?
+  ifstream c_if(getArg("autoprimaries").c_str(), std::ios::in); // this was nocreate?
   if (!c_if) {
-    g_log << Logger::Error << "Unable to open supermasters file for read: " << stringerror() << endl;
+    g_log << Logger::Error << "Unable to open autoprimaries file for read: " << stringerror() << endl;
     return false;
   }
 
@@ -1382,7 +1382,7 @@ bool Bind2Backend::superMasterBackend(const string& ip, const DNSName& /* domain
   if (sip != ip) // ip not found in authorization list - reject
     return false;
 
-  // ip authorized as supermaster - accept
+  // ip authorized as autoprimary - accept
   *db = this;
   if (saccount.length() > 0)
     *account = saccount.c_str();
@@ -1413,25 +1413,25 @@ BB2DomainInfo Bind2Backend::createDomainEntry(const DNSName& domain, const strin
   return bbd;
 }
 
-bool Bind2Backend::createSlaveDomain(const string& ip, const DNSName& domain, const string& /* nameserver */, const string& account)
+bool Bind2Backend::createSecondaryDomain(const string& ip, const DNSName& domain, const string& /* nameserver */, const string& account)
 {
-  string filename = getArg("supermaster-destdir") + '/' + domain.toStringNoDot();
+  string filename = getArg("autoprimary-destdir") + '/' + domain.toStringNoDot();
 
   g_log << Logger::Warning << d_logprefix
         << " Writing bind config zone statement for superslave zone '" << domain
-        << "' from supermaster " << ip << endl;
+        << "' from autoprimary " << ip << endl;
 
   {
-    std::lock_guard<std::mutex> l2(s_supermaster_config_lock);
+    std::lock_guard<std::mutex> l2(s_autosecondary_config_lock);
 
-    ofstream c_of(getArg("supermaster-config").c_str(), std::ios::app);
+    ofstream c_of(getArg("autoprimary-config").c_str(), std::ios::app);
     if (!c_of) {
-      g_log << Logger::Error << "Unable to open supermaster configfile for append: " << stringerror() << endl;
-      throw DBException("Unable to open supermaster configfile for append: " + stringerror());
+      g_log << Logger::Error << "Unable to open autoprimary configfile for append: " << stringerror() << endl;
+      throw DBException("Unable to open autoprimary configfile for append: " + stringerror());
     }
 
     c_of << endl;
-    c_of << "# Superslave zone '" << domain.toString() << "' (added: " << nowTime() << ") (account: " << account << ')' << endl;
+    c_of << "# AutoSecondary zone '" << domain.toString() << "' (added: " << nowTime() << ") (account: " << account << ')' << endl;
     c_of << "zone \"" << domain.toStringNoDot() << "\" {" << endl;
     c_of << "\ttype secondary;" << endl;
     c_of << "\tfile \"" << filename << "\";" << endl;
@@ -1441,15 +1441,15 @@ bool Bind2Backend::createSlaveDomain(const string& ip, const DNSName& domain, co
   }
 
   BB2DomainInfo bbd = createDomainEntry(domain, filename);
-  bbd.d_kind = DomainInfo::Slave;
-  bbd.d_masters.push_back(ComboAddress(ip, 53));
+  bbd.d_kind = DomainInfo::Secondary;
+  bbd.d_primaries.push_back(ComboAddress(ip, 53));
   bbd.setCtime();
   safePutBBDomainInfo(bbd);
 
   return true;
 }
 
-bool Bind2Backend::searchRecords(const string& pattern, int maxResults, vector<DNSResourceRecord>& result)
+bool Bind2Backend::searchRecords(const string& pattern, size_t maxResults, vector<DNSResourceRecord>& result)
 {
   SimpleMatch sm(pattern, true);
   static bool mustlog = ::arg().mustDo("query-logging");
@@ -1471,7 +1471,7 @@ bool Bind2Backend::searchRecords(const string& pattern, int maxResults, vector<D
 
       shared_ptr<const recordstorage_t> rhandle = h.d_records.get();
 
-      for (recordstorage_t::const_iterator ri = rhandle->begin(); result.size() < static_cast<vector<DNSResourceRecord>::size_type>(maxResults) && ri != rhandle->end(); ri++) {
+      for (recordstorage_t::const_iterator ri = rhandle->begin(); result.size() < maxResults && ri != rhandle->end(); ri++) {
         DNSName name = ri->qname.empty() ? i.d_name : (ri->qname + i.d_name);
         if (sm.match(name) || sm.match(ri->content)) {
           DNSResourceRecord r;
@@ -1501,9 +1501,9 @@ public:
     declare(suffix, "ignore-broken-records", "Ignore records that are out-of-bound for the zone.", "no");
     declare(suffix, "config", "Location of named.conf", "");
     declare(suffix, "check-interval", "Interval for zonefile changes", "0");
-    declare(suffix, "supermaster-config", "Location of (part of) named.conf where pdns can write zone-statements to", "");
-    declare(suffix, "supermasters", "List of IP-addresses of supermasters", "");
-    declare(suffix, "supermaster-destdir", "Destination directory for newly added slave zones", ::arg()["config-dir"]);
+    declare(suffix, "autoprimary-config", "Location of (part of) named.conf where pdns can write zone-statements to", "");
+    declare(suffix, "autoprimaries", "List of IP-addresses of autoprimaries", "");
+    declare(suffix, "autoprimary-destdir", "Destination directory for newly added secondary zones", ::arg()["config-dir"]);
     declare(suffix, "dnssec-db", "Filename to store & access our DNSSEC metadatabase, empty for none", "");
     declare(suffix, "dnssec-db-journal-mode", "SQLite3 journal mode", "WAL");
     declare(suffix, "hybrid", "Store DNSSEC metadata in other backend", "no");
index 7bd14f7d0bf6a34b8381f5b3629037407e84b34a..b61202267746f5375802860faec66167f8b8c1d8 100644 (file)
@@ -153,12 +153,12 @@ public:
   DomainInfo::DomainKind d_kind{DomainInfo::Native}; //!< the kind of domain
   string d_filename; //!< full absolute filename of the zone on disk
   string d_status; //!< message describing status of a domain, for human consumption
-  vector<ComboAddress> d_masters; //!< IP address of the master of this domain
+  vector<ComboAddress> d_primaries; //!< IP address of the primary of this domain
   set<string> d_also_notify; //!< IP list of hosts to also notify
   LookButDontTouch<recordstorage_t> d_records; //!< the actual records belonging to this domain
   time_t d_ctime{0}; //!< last known ctime of the file on disk
   time_t d_lastcheck{0}; //!< last time domain was checked for freshness
-  uint32_t d_lastnotified{0}; //!< Last serial number we notified our slaves of
+  uint32_t d_lastnotified{0}; //!< Last serial number we notified our secondaries of
   unsigned int d_id{0}; //!< internal id of the domain
   mutable bool d_checknow; //!< if this domain has been flagged for a check
   bool d_loaded{false}; //!< if a domain is loaded
@@ -183,8 +183,8 @@ class Bind2Backend : public DNSBackend
 public:
   Bind2Backend(const string& suffix = "", bool loadZones = true);
   ~Bind2Backend();
-  void getUnfreshSlaveInfos(vector<DomainInfo>* unfreshDomains) override;
-  void getUpdatedMasters(vector<DomainInfo>& changedDomains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes) override;
+  void getUnfreshSecondaryInfos(vector<DomainInfo>* unfreshDomains) override;
+  void getUpdatedPrimaries(vector<DomainInfo>& changedDomains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes) override;
   bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial = true) override;
   time_t getCtime(const string& fname);
   // DNSSEC
@@ -205,7 +205,7 @@ public:
   bool commitTransaction() override;
   bool abortTransaction() override;
   void alsoNotifies(const DNSName& domain, set<string>* ips) override;
-  bool searchRecords(const string& pattern, int maxResults, vector<DNSResourceRecord>& result) override;
+  bool searchRecords(const string& pattern, size_t maxResults, vector<DNSResourceRecord>& result) override;
 
   // the DNSSEC related (getDomainMetadata has broader uses too)
   bool getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string>>& meta) override;
@@ -236,9 +236,9 @@ public:
 
   // for autoprimary support
   bool autoPrimariesList(std::vector<AutoPrimary>& primaries) override;
-  bool superMasterBackend(const string& ip, const DNSName& domain, const vector<DNSResourceRecord>& nsset, string* nameserver, string* account, DNSBackend** db) override;
-  static std::mutex s_supermaster_config_lock;
-  bool createSlaveDomain(const string& ip, const DNSName& domain, const string& nameserver, const string& account) override;
+  bool autoPrimaryBackend(const string& ip, const DNSName& domain, const vector<DNSResourceRecord>& nsset, string* nameserver, string* account, DNSBackend** db) override;
+  static std::mutex s_autosecondary_config_lock;
+  bool createSecondaryDomain(const string& ip, const DNSName& domain, const string& nameserver, const string& account) override;
 
 private:
   void setupDNSSEC();
index c5b9bc7a4424e9d3cbc4e191f9d2bb94877c2b44..1cbeee24760e26e7e800b0dfef9e55466694b472 100644 (file)
@@ -230,7 +230,7 @@ bool Bind2Backend::getNSEC3PARAMuncached(const DNSName& name, NSEC3PARAMRecordCo
 
   static int maxNSEC3Iterations = ::arg().asNum("max-nsec3-iterations");
   if (ns3p) {
-    auto tmp = std::dynamic_pointer_cast<NSEC3PARAMRecordContent>(DNSRecordContent::mastermake(QType::NSEC3PARAM, 1, value));
+    auto tmp = std::dynamic_pointer_cast<NSEC3PARAMRecordContent>(DNSRecordContent::make(QType::NSEC3PARAM, 1, value));
     *ns3p = *tmp;
 
     if (ns3p->d_iterations > maxNSEC3Iterations) {
index 2d0523158b38c049403d98d346513c9e015e5f78..1f8e997663b4ca231aa3b1871449864473120d2d 100644 (file)
 #include <fstream>
 #include <filesystem>
 #include <utility>
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
 #include <yaml-cpp/yaml.h>
+#pragma GCC diagnostic pop
 
 ReadWriteLock GeoIPBackend::s_state_lock;
 
@@ -82,12 +85,11 @@ GeoIPBackend::GeoIPBackend(const string& suffix)
   WriteLock writeLock(&s_state_lock);
   setArgPrefix("geoip" + suffix);
   if (!getArg("dnssec-keydir").empty()) {
-    DIR* dir = opendir(getArg("dnssec-keydir").c_str());
-    if (dir == nullptr) {
+    auto dirHandle = std::unique_ptr<DIR, decltype(&closedir)>(opendir(getArg("dnssec-keydir").c_str()), closedir);
+    if (!dirHandle) {
       throw PDNSException("dnssec-keydir " + getArg("dnssec-keydir") + " does not exist");
     }
     d_dnssec = true;
-    closedir(dir);
   }
   if (s_rc == 0) { // first instance gets to open everything
     initialize();
index b908df5c6832fba2e5e0c27c1c28f5aade7de913..cd3d62595dccfa720532638d9bc4dfe2927309cc 100644 (file)
@@ -103,10 +103,10 @@ public:
 
     declare(suffix, "info-zone-query", "", "select id,name,master,last_check,notified_serial,type,options,catalog,account from domains where name=?");
 
-    declare(suffix, "info-all-slaves-query", "", "select domains.id, domains.name, domains.type, domains.master, domains.last_check, records.content from domains LEFT JOIN records ON records.domain_id=domains.id AND records.type='SOA' AND records.name=domains.name where domains.type in ('SLAVE', 'CONSUMER')");
-    declare(suffix, "supermaster-query", "", "select account from supermasters where ip=? and nameserver=?");
-    declare(suffix, "supermaster-name-to-ips", "", "select ip,account from supermasters where nameserver=? and account=?");
-    declare(suffix, "supermaster-add", "", "insert into supermasters (ip, nameserver, account) values (?,?,?)");
+    declare(suffix, "info-all-secondaries-query", "", "select domains.id, domains.name, domains.type, domains.master, domains.last_check, records.content from domains LEFT JOIN records ON records.domain_id=domains.id AND records.type='SOA' AND records.name=domains.name where domains.type in ('SLAVE', 'CONSUMER')");
+    declare(suffix, "autoprimary-query", "", "select account from supermasters where ip=? and nameserver=?");
+    declare(suffix, "autoprimary-name-to-ips", "", "select ip,account from supermasters where nameserver=? and account=?");
+    declare(suffix, "autoprimary-add", "", "insert into supermasters (ip, nameserver, account) values (?,?,?)");
     declare(suffix, "autoprimary-remove", "", "delete from supermasters where ip = ? and nameserver = ?");
     declare(suffix, "list-autoprimaries", "", "select ip,nameserver,account from supermasters");
 
@@ -125,14 +125,14 @@ public:
     declare(suffix, "nullify-ordername-and-update-auth-query", "DNSSEC nullify ordername and update auth for a qname query", "update records set ordername=NULL,auth=? where domain_id=? and name=? and disabled=0");
     declare(suffix, "nullify-ordername-and-update-auth-type-query", "DNSSEC nullify ordername and update auth for a rrset query", "update records set ordername=NULL,auth=? where domain_id=? and name=? and type=? and disabled=0");
 
-    declare(suffix, "update-master-query", "", "update domains set master=? where name=?");
+    declare(suffix, "update-primary-query", "", "update domains set master=? where name=?");
     declare(suffix, "update-kind-query", "", "update domains set type=? where name=?");
     declare(suffix, "update-options-query", "", "update domains set options=? where name=?");
     declare(suffix, "update-catalog-query", "", "update domains set catalog=? where name=?");
     declare(suffix, "update-account-query", "", "update domains set account=? where name=?");
     declare(suffix, "update-serial-query", "", "update domains set notified_serial=? where id=?");
     declare(suffix, "update-lastcheck-query", "", "update domains set last_check=? where id=?");
-    declare(suffix, "info-all-master-query", "", "select d.id, d.name, d.type, d.notified_serial,d.options, d.catalog,r.content from records r join domains d on r.domain_id=d.id and r.name=d.name where r.type='SOA' and r.disabled=0 and d.type in ('MASTER', 'PRODUCER')");
+    declare(suffix, "info-all-primary-query", "", "select d.id, d.name, d.type, d.notified_serial,d.options, d.catalog,r.content from records r join domains d on r.domain_id=d.id and r.name=d.name where r.type='SOA' and r.disabled=0 and d.type in ('MASTER', 'PRODUCER')");
     declare(suffix, "info-producer-members-query", "", "select domains.id, domains.name, domains.options from records join domains on records.domain_id=domains.id and records.name=domains.name where domains.type='MASTER' and domains.catalog=? and records.type='SOA' and records.disabled=0");
     declare(suffix, "info-consumer-members-query", "", "select id, name, options, master from domains where type='SLAVE' and catalog=?");
     declare(suffix, "delete-domain-query", "", "delete from domains where name=?");
index 6d0cc6b5856f9b564a876aff5855084f93095d16..f34e8beb1108c80a71951b1a432c40e02e032529 100644 (file)
@@ -83,10 +83,10 @@ public:
 
     declare(suffix, "info-zone-query", "", "select id,name,master,last_check,notified_serial,type,options,catalog,account from domains where name=?");
 
-    declare(suffix, "info-all-slaves-query", "", "select domains.id, domains.name, domains.type, domains.master, domains.last_check, records.content from domains LEFT JOIN records ON records.domain_id=domains.id AND records.type='SOA' AND records.name=domains.name where domains.type in ('SLAVE', 'CONSUMER')");
-    declare(suffix, "supermaster-query", "", "select account from supermasters where ip=? and nameserver=?");
-    declare(suffix, "supermaster-name-to-ips", "", "select ip,account from supermasters where nameserver=? and account=?");
-    declare(suffix, "supermaster-add", "", "insert into supermasters (ip, nameserver, account) values (?,?,?)");
+    declare(suffix, "info-all-secondaries-query", "", "select domains.id, domains.name, domains.type, domains.master, domains.last_check, records.content from domains LEFT JOIN records ON records.domain_id=domains.id AND records.type='SOA' AND records.name=domains.name where domains.type in ('SLAVE', 'CONSUMER')");
+    declare(suffix, "autoprimary-query", "", "select account from supermasters where ip=? and nameserver=?");
+    declare(suffix, "autoprimary-name-to-ips", "", "select ip,account from supermasters where nameserver=? and account=?");
+    declare(suffix, "autoprimary-add", "", "insert into supermasters (ip, nameserver, account) values (?,?,?)");
     declare(suffix, "autoprimary-remove", "", "delete from supermasters where ip = ? and nameserver = ?");
     declare(suffix, "list-autoprimaries", "", "select ip,nameserver,account from supermasters");
 
@@ -105,14 +105,14 @@ public:
     declare(suffix, "nullify-ordername-and-update-auth-query", "DNSSEC nullify ordername and update auth for a qname query", "update records set ordername=NULL,auth=? where domain_id=? and name=? and disabled=0");
     declare(suffix, "nullify-ordername-and-update-auth-type-query", "DNSSEC nullify ordername and update auth for a rrset query", "update records set ordername=NULL,auth=? where domain_id=? and name=? and type=? and disabled=0");
 
-    declare(suffix, "update-master-query", "", "update domains set master=? where name=?");
+    declare(suffix, "update-primary-query", "", "update domains set master=? where name=?");
     declare(suffix, "update-kind-query", "", "update domains set type=? where name=?");
     declare(suffix, "update-options-query", "", "update domains set options=? where name=?");
     declare(suffix, "update-catalog-query", "", "update domains set catalog=? where name=?");
     declare(suffix, "update-account-query", "", "update domains set account=? where name=?");
     declare(suffix, "update-serial-query", "", "update domains set notified_serial=? where id=?");
     declare(suffix, "update-lastcheck-query", "", "update domains set last_check=? where id=?");
-    declare(suffix, "info-all-master-query", "", "select domains.id, domains.name, domains.type, domains.notified_serial, domains.options, domains.catalog, records.content from records join domains on records.domain_id=domains.id and records.name=domains.name where records.type='SOA' and records.disabled=0 and domains.type in ('MASTER', 'PRODUCER')");
+    declare(suffix, "info-all-primary-query", "", "select domains.id, domains.name, domains.type, domains.notified_serial, domains.options, domains.catalog, records.content from records join domains on records.domain_id=domains.id and records.name=domains.name where records.type='SOA' and records.disabled=0 and domains.type in ('MASTER', 'PRODUCER')");
     declare(suffix, "info-producer-members-query", "", "select domains.id, domains.name, domains.options from records join domains on records.domain_id=domains.id and records.name=domains.name where domains.type='MASTER' and domains.catalog=? and records.type='SOA' and records.disabled=0");
     declare(suffix, "info-consumer-members-query", "", "select id, name, options, master from domains where type='SLAVE' and catalog=?");
     declare(suffix, "delete-domain-query", "", "delete from domains where name=?");
index e6a346fe4a54706c55783cd00cac6ed19508149b..c343855b16ab5c9f04698d3aea3986e269bc1191 100644 (file)
@@ -110,10 +110,10 @@ public:
 
     declare(suffix, "info-zone-query", "", "select id,name,master,last_check,notified_serial,type,options,catalog,account from domains where name=$1");
 
-    declare(suffix, "info-all-slaves-query", "", "select domains.id, domains.name, domains.type, domains.master, domains.last_check, records.content from domains LEFT JOIN records ON records.domain_id=domains.id AND records.type='SOA' AND records.name=domains.name where domains.type in ('SLAVE', 'CONSUMER')");
-    declare(suffix, "supermaster-query", "", "select account from supermasters where ip=$1 and nameserver=$2");
-    declare(suffix, "supermaster-name-to-ips", "", "select ip,account from supermasters where nameserver=$1 and account=$2");
-    declare(suffix, "supermaster-add", "", "insert into supermasters (ip, nameserver, account) values ($1,$2,$3)");
+    declare(suffix, "info-all-secondaries-query", "", "select domains.id, domains.name, domains.type, domains.master, domains.last_check, records.content from domains LEFT JOIN records ON records.domain_id=domains.id AND records.type='SOA' AND records.name=domains.name where domains.type in ('SLAVE', 'CONSUMER')");
+    declare(suffix, "autoprimary-query", "", "select account from supermasters where ip=$1 and nameserver=$2");
+    declare(suffix, "autoprimary-name-to-ips", "", "select ip,account from supermasters where nameserver=$1 and account=$2");
+    declare(suffix, "autoprimary-add", "", "insert into supermasters (ip, nameserver, account) values ($1,$2,$3)");
     declare(suffix, "autoprimary-remove", "", "delete from supermasters where ip = $1 and nameserver = $2");
     declare(suffix, "list-autoprimaries", "", "select ip,nameserver,account from supermasters");
 
@@ -132,14 +132,14 @@ public:
     declare(suffix, "nullify-ordername-and-update-auth-query", "DNSSEC nullify ordername and update auth for a qname query", "update records set ordername=NULL,auth=$1 where domain_id=$2 and name=$3 and disabled=false");
     declare(suffix, "nullify-ordername-and-update-auth-type-query", "DNSSEC nullify ordername and update auth for a rrset query", "update records set ordername=NULL,auth=$1 where domain_id=$2 and name=$3 and type=$4 and disabled=false");
 
-    declare(suffix, "update-master-query", "", "update domains set master=$1 where name=$2");
+    declare(suffix, "update-primary-query", "", "update domains set master=$1 where name=$2");
     declare(suffix, "update-kind-query", "", "update domains set type=$1 where name=$2");
     declare(suffix, "update-options-query", "", "update domains set options=$1 where name=$2");
     declare(suffix, "update-catalog-query", "", "update domains set catalog=$1 where name=$2");
     declare(suffix, "update-account-query", "", "update domains set account=$1 where name=$2");
     declare(suffix, "update-serial-query", "", "update domains set notified_serial=$1 where id=$2");
     declare(suffix, "update-lastcheck-query", "", "update domains set last_check=$1 where id=$2");
-    declare(suffix, "info-all-master-query", "", "select domains.id, domains.name, domains.type, domains.notified_serial, domains.options, domains.catalog, records.content from records join domains on records.domain_id=domains.id and records.name=domains.name where records.type='SOA' and records.disabled=false and domains.type in ('MASTER', 'PRODUCER')");
+    declare(suffix, "info-all-primary-query", "", "select domains.id, domains.name, domains.type, domains.notified_serial, domains.options, domains.catalog, records.content from records join domains on records.domain_id=domains.id and records.name=domains.name where records.type='SOA' and records.disabled=false and domains.type in ('MASTER', 'PRODUCER')");
     declare(suffix, "info-producer-members-query", "", "select domains.id, domains.name, domains.options from records join domains on records.domain_id=domains.id and records.name=domains.name where domains.type='MASTER' and domains.catalog=$1 and records.type='SOA' and records.disabled=false");
     declare(suffix, "info-consumer-members-query", "", "select id, name, options, master from domains where type='SLAVE' and catalog=$1");
     declare(suffix, "delete-domain-query", "", "delete from domains where name=$1");
index f183cec37c642d772a51bab37b70e11bf397bd21..b67f4f0e59d9012d2b1d52d2532f314142a25517 100644 (file)
@@ -96,14 +96,14 @@ public:
 
     declare(suffix, "info-zone-query", "", "select id,name,master,last_check,notified_serial,type,options,catalog,account from domains where name=:domain");
 
-    declare(suffix, "info-all-slaves-query", "", "select domains.id, domains.name, domains.type, domains.master, domains.last_check, records.content from domains LEFT JOIN records ON records.domain_id=domains.id AND records.type='SOA' AND records.name=domains.name where domains.type in ('SLAVE', 'CONSUMER')");
-    declare(suffix, "supermaster-query", "", "select account from supermasters where ip=:ip and nameserver=:nameserver");
-    declare(suffix, "supermaster-name-to-ips", "", "select ip,account from supermasters where nameserver=:nameserver and account=:account");
-    declare(suffix, "supermaster-add", "", "insert into supermasters (ip, nameserver, account) values (:ip,:nameserver,:account)");
+    declare(suffix, "info-all-secondaries-query", "", "select domains.id, domains.name, domains.type, domains.master, domains.last_check, records.content from domains LEFT JOIN records ON records.domain_id=domains.id AND records.type='SOA' AND records.name=domains.name where domains.type in ('SLAVE', 'CONSUMER')");
+    declare(suffix, "autoprimary-query", "", "select account from supermasters where ip=:ip and nameserver=:nameserver");
+    declare(suffix, "autoprimary-name-to-ips", "", "select ip,account from supermasters where nameserver=:nameserver and account=:account");
+    declare(suffix, "autoprimary-add", "", "insert into supermasters (ip, nameserver, account) values (:ip,:nameserver,:account)");
     declare(suffix, "autoprimary-remove", "", "delete from supermasters where ip = :ip and nameserver = :nameserver");
     declare(suffix, "list-autoprimaries", "", "select ip,nameserver,account from supermasters");
 
-    declare(suffix, "insert-zone-query", "", "insert into domains (type,name,master,account,last_check,notified_serial) values(:type, :domain, :masters, :account, null, null)");
+    declare(suffix, "insert-zone-query", "", "insert into domains (type,name,master,account,last_check,notified_serial) values(:type, :domain, :primaries, :account, null, null)");
 
     declare(suffix, "insert-record-query", "", "insert into records (content,ttl,prio,type,domain_id,disabled,name,ordername,auth) values (:content,:ttl,:priority,:qtype,:domain_id,:disabled,:qname,:ordername,:auth)");
     declare(suffix, "insert-empty-non-terminal-order-query", "insert empty non-terminal in zone", "insert into records (type,domain_id,disabled,name,ordername,auth,ttl,prio,content) values (null,:domain_id,0,:qname,:ordername,:auth,null,null,null)");
@@ -118,14 +118,14 @@ public:
     declare(suffix, "nullify-ordername-and-update-auth-query", "DNSSEC nullify ordername and update auth for a qname query", "update records set ordername=NULL,auth=:auth where domain_id=:domain_id and name=:qname and disabled=0");
     declare(suffix, "nullify-ordername-and-update-auth-type-query", "DNSSEC nullify ordername and update auth for a rrset query", "update records set ordername=NULL,auth=:auth where domain_id=:domain_id and name=:qname and type=:qtype and disabled=0");
 
-    declare(suffix, "update-master-query", "", "update domains set master=:master where name=:domain");
+    declare(suffix, "update-primary-query", "", "update domains set master=:master where name=:domain");
     declare(suffix, "update-kind-query", "", "update domains set type=:kind where name=:domain");
     declare(suffix, "update-options-query", "", "update domains set options=:options where name=:domain");
     declare(suffix, "update-catalog-query", "", "update domains set catalog=:catalog where name=:domain");
     declare(suffix, "update-account-query", "", "update domains set account=:account where name=:domain");
     declare(suffix, "update-serial-query", "", "update domains set notified_serial=:serial where id=:domain_id");
     declare(suffix, "update-lastcheck-query", "", "update domains set last_check=:last_check where id=:domain_id");
-    declare(suffix, "info-all-master-query", "", "select domains.id, domains.name, domains.type, domains.notified_serial, domains.options, domains.catalog, records.content from records join domains on records.domain_id=domains.id and records.name=domains.name where records.type='SOA' and records.disabled=0 and domains.type in ('MASTER', 'PRODUCER')");
+    declare(suffix, "info-all-primary-query", "", "select domains.id, domains.name, domains.type, domains.notified_serial, domains.options, domains.catalog, records.content from records join domains on records.domain_id=domains.id and records.name=domains.name where records.type='SOA' and records.disabled=0 and domains.type in ('MASTER', 'PRODUCER')");
     declare(suffix, "info-producer-members-query", "", "select domains.id, domains.name, domains.options from records join domains on records.domain_id=domains.id and records.name=domains.name where domains.type='MASTER' and domains.catalog=:catalog and records.type='SOA' and records.disabled=0");
     declare(suffix, "info-consumer-members-query", "", "select id, name, options, master from domains where type='SLAVE' and catalog=:catalog");
     declare(suffix, "delete-domain-query", "", "delete from domains where name=:domain");
index 5feed38d93c5bf212952ed686e4ce84e91163115..ae2fb7a6b6977ba40a7e454d75492e3da8dcc724 100644 (file)
@@ -17,9 +17,9 @@ libldapbackend_la_SOURCES = \
        ldapauthenticator.hh ldapauthenticator_p.hh ldapauthenticator.cc \
        ldapbackend.cc ldapbackend.hh \
        ldaputils.hh ldaputils.cc \
-       master.cc \
        native.cc \
        powerldap.cc powerldap.hh \
+       primary.cc \
        utils.hh
 
 libldapbackend_la_LDFLAGS = -module -avoid-version
index d9864867e79fb7de3e9f759c242144729dd80ed9..739ed4d5a252077f87978f5181c7a44e134a4776 100644 (file)
@@ -1 +1 @@
-ldapbackend.lo master.lo native.lo powerldap.lo ldaputils.lo ldapauthenticator.lo
+ldapbackend.lo native.lo powerldap.lo primary.lo ldaputils.lo ldapauthenticator.lo
index 23e77c8795af892b29a5ec806b1a82684f935cfb..f460ebd84935e618c39d14947c86756413813e67 100644 (file)
@@ -176,7 +176,7 @@ public:
 
   bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial = true) override;
 
-  // Master backend
-  void getUpdatedMasters(vector<DomainInfo>& domains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes) override;
+  // Primary backend
+  void getUpdatedPrimaries(vector<DomainInfo>& domains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes) override;
   void setNotified(uint32_t id, uint32_t serial) override;
 };
index 82ddebf06071099337bed97e6aeba4f720daefac..48421ea99ce474353d753f31fd19a26d9809e64a 100644 (file)
@@ -383,15 +383,15 @@ bool LdapBackend::getDomainInfo(const DNSName& domain, DomainInfo& di, bool /* g
 
     if (result.count("PdnsDomainMaster") && !result["PdnsDomainMaster"].empty()) {
       for (const auto& m : result["PdnsDomainMaster"])
-        di.masters.emplace_back(m, 53);
+        di.primaries.emplace_back(m, 53);
     }
 
     if (result.count("PdnsDomainType") && !result["PdnsDomainType"].empty()) {
       string kind = result["PdnsDomainType"][0];
       if (kind == "master")
-        di.kind = DomainInfo::Master;
+        di.kind = DomainInfo::Primary;
       else if (kind == "slave")
-        di.kind = DomainInfo::Slave;
+        di.kind = DomainInfo::Secondary;
       else
         di.kind = DomainInfo::Native;
     }
similarity index 94%
rename from modules/ldapbackend/master.cc
rename to modules/ldapbackend/primary.cc
index 1ab28f0d3ad79b20ab6991960611604a7108b296..13c112d14fef73314428b4fbb44c6ca5c7617c02 100644 (file)
@@ -24,7 +24,7 @@
 #include "ldapbackend.hh"
 #include <cstdlib>
 
-void LdapBackend::getUpdatedMasters(vector<DomainInfo>& domains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes)
+void LdapBackend::getUpdatedPrimaries(vector<DomainInfo>& domains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes)
 {
   string filter;
   PowerLDAP::SearchResult::Ptr search;
@@ -34,7 +34,7 @@ void LdapBackend::getUpdatedMasters(vector<DomainInfo>& domains, std::unordered_
     NULL};
 
   try {
-    // First get all domains on which we are master.
+    // First get all domains on which we are primary.
     filter = strbind(":target:", "&(SOARecord=*)(PdnsDomainId=*)", getArg("filter-axfr"));
     search = d_pldap->search(getArg("basedn"), LDAP_SCOPE_SUBTREE, filter, attronly);
   }
@@ -45,7 +45,7 @@ void LdapBackend::getUpdatedMasters(vector<DomainInfo>& domains, std::unordered_
   catch (LDAPNoConnection& lnc) {
     g_log << Logger::Warning << d_myname << " Connection to LDAP lost, trying to reconnect" << endl;
     if (reconnect())
-      this->getUpdatedMasters(domains, catalogs, catalogHashes);
+      this->getUpdatedPrimaries(domains, catalogs, catalogHashes);
     else
       throw PDNSException("Failed to reconnect to LDAP server");
   }
index 60a05cac1d099e35ea0bdda84e8bc833cd867589..3cfbf8c4da1de8d0db1651692d569316966e1179 100644 (file)
@@ -819,7 +819,7 @@ namespace serialization
     ar& g.zone;
     ar& g.last_check;
     ar& g.account;
-    ar& g.masters;
+    ar& g.primaries;
     ar& g.id;
     ar& g.notified_serial;
     ar& g.kind;
@@ -833,7 +833,7 @@ namespace serialization
     ar& g.zone;
     ar& g.last_check;
     ar& g.account;
-    ar& g.masters;
+    ar& g.primaries;
     ar& g.id;
     ar& g.notified_serial;
     ar& g.kind;
@@ -948,7 +948,7 @@ void serFromString(const string_view& str, vector<LMDBBackend::LMDBResourceRecor
 
 static std::string serializeContent(uint16_t qtype, const DNSName& domain, const std::string& content)
 {
-  auto drc = DNSRecordContent::mastermake(qtype, QClass::IN, content);
+  auto drc = DNSRecordContent::make(qtype, QClass::IN, content);
   return drc->serialize(domain, false);
 }
 
@@ -1661,14 +1661,14 @@ bool LMDBBackend::setAccount(const DNSName& domain, const std::string& account)
   });
 }
 
-bool LMDBBackend::setMasters(const DNSName& domain, const vector<ComboAddress>& masters)
+bool LMDBBackend::setPrimaries(const DNSName& domain, const vector<ComboAddress>& primaries)
 {
-  return genChangeDomain(domain, [&masters](DomainInfo& di) {
-    di.masters = masters;
+  return genChangeDomain(domain, [&primaries](DomainInfo& di) {
+    di.primaries = primaries;
   });
 }
 
-bool LMDBBackend::createDomain(const DNSName& domain, const DomainInfo::DomainKind kind, const vector<ComboAddress>& masters, const string& account)
+bool LMDBBackend::createDomain(const DNSName& domain, const DomainInfo::DomainKind kind, const vector<ComboAddress>& primaries, const string& account)
 {
   DomainInfo di;
 
@@ -1680,7 +1680,7 @@ bool LMDBBackend::createDomain(const DNSName& domain, const DomainInfo::DomainKi
 
     di.zone = domain;
     di.kind = kind;
-    di.masters = masters;
+    di.primaries = primaries;
     di.account = account;
 
     txn.put(di, 0, d_random_ids);
@@ -1754,7 +1754,7 @@ void LMDBBackend::getAllDomains(vector<DomainInfo>* domains, bool /* doSerial */
   });
 }
 
-void LMDBBackend::getUnfreshSlaveInfos(vector<DomainInfo>* domains)
+void LMDBBackend::getUnfreshSecondaryInfos(vector<DomainInfo>* domains)
 {
   uint32_t serial;
   time_t now = time(0);
@@ -1799,7 +1799,7 @@ void LMDBBackend::setFresh(uint32_t domain_id)
   });
 }
 
-void LMDBBackend::getUpdatedMasters(vector<DomainInfo>& updatedDomains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes)
+void LMDBBackend::getUpdatedPrimaries(vector<DomainInfo>& updatedDomains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes)
 {
   CatalogInfo ci;
 
@@ -1848,14 +1848,14 @@ bool LMDBBackend::getCatalogMembers(const DNSName& catalog, vector<CatalogInfo>&
 
   try {
     getAllDomainsFiltered(&scratch, [&catalog, &members, &type](DomainInfo& di) {
-      if ((type == CatalogInfo::CatalogType::Producer && di.kind != DomainInfo::Master) || (type == CatalogInfo::CatalogType::Consumer && di.kind != DomainInfo::Slave) || di.catalog != catalog) {
+      if ((type == CatalogInfo::CatalogType::Producer && di.kind != DomainInfo::Primary) || (type == CatalogInfo::CatalogType::Consumer && di.kind != DomainInfo::Secondary) || di.catalog != catalog) {
         return false;
       }
 
       CatalogInfo ci;
       ci.d_id = di.id;
       ci.d_zone = di.zone;
-      ci.d_primaries = di.masters;
+      ci.d_primaries = di.primaries;
       try {
         ci.fromJson(di.options, type);
       }
index 781a7c7c9a3d2f6071fd62313455445ad30cd04a..e75b564c55a6bd80c80d0ee0c895126381d1f266 100644 (file)
@@ -65,7 +65,7 @@ public:
   bool list(const DNSName& target, int id, bool include_disabled) override;
 
   bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getserial = true) override;
-  bool createDomain(const DNSName& domain, const DomainInfo::DomainKind kind, const vector<ComboAddress>& masters, const string& account) override;
+  bool createDomain(const DNSName& domain, const DomainInfo::DomainKind kind, const vector<ComboAddress>& primaries, const string& account) override;
 
   bool startTransaction(const DNSName& domain, int domain_id = -1) override;
   bool commitTransaction() override;
@@ -82,12 +82,12 @@ public:
   bool get(DNSZoneRecord& dzr) override;
 
   // secondary support
-  void getUnfreshSlaveInfos(vector<DomainInfo>* domains) override;
+  void getUnfreshSecondaryInfos(vector<DomainInfo>* domains) override;
   void setStale(uint32_t domain_id) override;
   void setFresh(uint32_t domain_id) override;
 
   // primary support
-  void getUpdatedMasters(vector<DomainInfo>& updatedDomains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes) override;
+  void getUpdatedPrimaries(vector<DomainInfo>& updatedDomains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes) override;
   void setNotified(uint32_t id, uint32_t serial) override;
 
   // catalog zones
@@ -95,7 +95,7 @@ public:
   bool setOptions(const DNSName& domain, const std::string& options) override;
   bool setCatalog(const DNSName& domain, const DNSName& options) override;
 
-  bool setMasters(const DNSName& domain, const vector<ComboAddress>& masters) override;
+  bool setPrimaries(const DNSName& domain, const vector<ComboAddress>& primaries) override;
   bool setKind(const DNSName& domain, const DomainInfo::DomainKind kind) override;
   bool getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string>>& meta) override;
   bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector<std::string>& meta) override
index 649a808f1149c27d8c9b41eee34d3819b90e66cc..73b4baf678219c5466912061be2b78554224b3d2 100644 (file)
@@ -255,8 +255,8 @@ public:
       else if (item.first == "last_check")
         di.last_check = static_cast<time_t>(boost::get<long>(item.second));
       else if (item.first == "masters")
-        for (const auto& master : boost::get<vector<string>>(item.second))
-          di.masters.push_back(ComboAddress(master, 53));
+        for (const auto& primary : boost::get<vector<string>>(item.second))
+          di.primaries.push_back(ComboAddress(primary, 53));
       else if (item.first == "id")
         di.id = static_cast<int>(boost::get<long>(item.second));
       else if (item.first == "notified_serial")
index 8fa086ab6b4cf4f814193a2b36a8f0745b15c59e..2cb6d5f9301b4a1d8431ad68df547455c3ae2db1 100644 (file)
@@ -19,6 +19,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
+#include <limits>
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -591,8 +592,8 @@ void RemoteBackend::parseDomainInfo(const Json& obj, DomainInfo& di)
 {
   di.id = intFromJson(obj, "id", -1);
   di.zone = DNSName(stringFromJson(obj, "zone"));
-  for (const auto& master : obj["masters"].array_items()) {
-    di.masters.emplace_back(master.string_value(), 53);
+  for (const auto& primary : obj["masters"].array_items()) {
+    di.primaries.emplace_back(primary.string_value(), 53);
   }
 
   di.notified_serial = static_cast<unsigned int>(doubleFromJson(obj, "notified_serial", 0));
@@ -604,10 +605,10 @@ void RemoteBackend::parseDomainInfo(const Json& obj, DomainInfo& di)
     kind = stringFromJson(obj, "kind");
   }
   if (kind == "master") {
-    di.kind = DomainInfo::Master;
+    di.kind = DomainInfo::Primary;
   }
   else if (kind == "slave") {
-    di.kind = DomainInfo::Slave;
+    di.kind = DomainInfo::Secondary;
   }
   else {
     di.kind = DomainInfo::Native;
@@ -646,7 +647,7 @@ void RemoteBackend::setNotified(uint32_t id, uint32_t serial)
   }
 }
 
-bool RemoteBackend::superMasterBackend(const string& ip, const DNSName& domain, const vector<DNSResourceRecord>& nsset, string* nameserver, string* account, DNSBackend** ddb)
+bool RemoteBackend::autoPrimaryBackend(const string& ip, const DNSName& domain, const vector<DNSResourceRecord>& nsset, string* nameserver, string* account, DNSBackend** ddb)
 {
   Json::array rrset;
 
@@ -683,7 +684,7 @@ bool RemoteBackend::superMasterBackend(const string& ip, const DNSName& domain,
   return true;
 }
 
-bool RemoteBackend::createSlaveDomain(const string& ip, const DNSName& domain, const string& nameserver, const string& account)
+bool RemoteBackend::createSecondaryDomain(const string& ip, const DNSName& domain, const string& nameserver, const string& account)
 {
   Json query = Json::object{
     {"method", "createSlaveDomain"},
@@ -830,11 +831,16 @@ string RemoteBackend::directBackendCmd(const string& querystr)
   return asString(answer["result"]);
 }
 
-bool RemoteBackend::searchRecords(const string& pattern, int maxResults, vector<DNSResourceRecord>& result)
+bool RemoteBackend::searchRecords(const string& pattern, size_t maxResults, vector<DNSResourceRecord>& result)
 {
+  const auto intMax = static_cast<decltype(maxResults)>(std::numeric_limits<int>::max());
+  if (maxResults > intMax) {
+    throw std::out_of_range("Remote backend: length of list of result (" + std::to_string(maxResults) + ") is larger than what the JSON library supports for serialization (" + std::to_string(intMax) + ")");
+  }
+
   Json query = Json::object{
     {"method", "searchRecords"},
-    {"parameters", Json::object{{"pattern", pattern}, {"maxResults", maxResults}}}};
+    {"parameters", Json::object{{"pattern", pattern}, {"maxResults", static_cast<int>(maxResults)}}}};
 
   Json answer;
   if (!this->send(query) || !this->recv(answer)) {
@@ -866,7 +872,7 @@ bool RemoteBackend::searchRecords(const string& pattern, int maxResults, vector<
   return true;
 }
 
-bool RemoteBackend::searchComments(const string& /* pattern */, int /* maxResults */, vector<Comment>& /* result */)
+bool RemoteBackend::searchComments(const string& /* pattern */, size_t /* maxResults */, vector<Comment>& /* result */)
 {
   // FIXME: Implement Comment API
   return false;
@@ -894,7 +900,7 @@ void RemoteBackend::getAllDomains(vector<DomainInfo>* domains, bool /* getSerial
   }
 }
 
-void RemoteBackend::getUpdatedMasters(vector<DomainInfo>& domains, std::unordered_set<DNSName>& /* catalogs */, CatalogHashMap& /* catalogHashes */)
+void RemoteBackend::getUpdatedPrimaries(vector<DomainInfo>& domains, std::unordered_set<DNSName>& /* catalogs */, CatalogHashMap& /* catalogHashes */)
 {
   Json query = Json::object{
     {"method", "getUpdatedMasters"},
@@ -917,7 +923,7 @@ void RemoteBackend::getUpdatedMasters(vector<DomainInfo>& domains, std::unordere
   }
 }
 
-void RemoteBackend::getUnfreshSlaveInfos(vector<DomainInfo>* domains)
+void RemoteBackend::getUnfreshSecondaryInfos(vector<DomainInfo>* domains)
 {
   Json query = Json::object{
     {"method", "getUnfreshSlaveInfos"},
index 23c7be638a0c4f29addfc391865483383e6345c4..a435465173944cbd901be27a0971567e22f3443a 100644 (file)
@@ -186,8 +186,8 @@ public:
   bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial = true) override;
   void setNotified(uint32_t id, uint32_t serial) override;
   bool doesDNSSEC() override;
-  bool superMasterBackend(const string& ip, const DNSName& domain, const vector<DNSResourceRecord>& nsset, string* nameserver, string* account, DNSBackend** ddb) override;
-  bool createSlaveDomain(const string& ip, const DNSName& domain, const string& nameserver, const string& account) override;
+  bool autoPrimaryBackend(const string& ip, const DNSName& domain, const vector<DNSResourceRecord>& nsset, string* nameserver, string* account, DNSBackend** ddb) override;
+  bool createSecondaryDomain(const string& ip, const DNSName& domain, const string& nameserver, const string& account) override;
   bool replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector<DNSResourceRecord>& rrset) override;
   bool feedRecord(const DNSResourceRecord& r, const DNSName& ordername, bool ordernameIsNSEC3 = false) override;
   bool feedEnts(int domain_id, map<DNSName, bool>& nonterm) override;
@@ -199,11 +199,11 @@ public:
   bool deleteTSIGKey(const DNSName& name) override;
   bool getTSIGKeys(std::vector<struct TSIGKey>& keys) override;
   string directBackendCmd(const string& querystr) override;
-  bool searchRecords(const string& pattern, int maxResults, vector<DNSResourceRecord>& result) override;
-  bool searchComments(const string& pattern, int maxResults, vector<Comment>& result) override;
+  bool searchRecords(const string& pattern, size_t maxResults, vector<DNSResourceRecord>& result) override;
+  bool searchComments(const string& pattern, size_t maxResults, vector<Comment>& result) override;
   void getAllDomains(vector<DomainInfo>* domains, bool getSerial, bool include_disabled) override;
-  void getUpdatedMasters(vector<DomainInfo>& domains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes) override;
-  void getUnfreshSlaveInfos(vector<DomainInfo>* domains) override;
+  void getUpdatedPrimaries(vector<DomainInfo>& domains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes) override;
+  void getUnfreshSecondaryInfos(vector<DomainInfo>* domains) override;
   void setStale(uint32_t domain_id) override;
   void setFresh(uint32_t domain_id) override;
 
index 824db562037c254ffeb7e8d46c5ca45229003bfb..d7b967009a5a53cb551993a3bb54a7aad9abc9e0 100644 (file)
@@ -20,6 +20,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#include <memory>
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -52,7 +53,7 @@ public:
   RemoteLoader();
 };
 
-DNSBackend* be;
+std::unique_ptr<DNSBackend> backendUnderTest;
 
 #define BOOST_TEST_DYN_LINK
 #define BOOST_TEST_MAIN
@@ -67,7 +68,7 @@ struct RemotebackendSetup
 {
   RemotebackendSetup()
   {
-    be = nullptr;
+    backendUnderTest = nullptr;
     try {
       // setup minimum arguments
       ::arg().set("module-dir") = "./.libs";
@@ -76,7 +77,7 @@ struct RemotebackendSetup
       // then get us a instance of it
       ::arg().set("remote-connection-string") = "http:url=http://localhost:62434/dns";
       ::arg().set("remote-dnssec") = "yes";
-      be = BackendMakers().all()[0];
+      backendUnderTest = std::move(BackendMakers().all()[0]);
     }
     catch (PDNSException& ex) {
       BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason);
index 48d023ed829900ac58ba88fe83eab3903db9912e..7291d45e459e2ec500eb43f8d392a65656808fe9 100644 (file)
@@ -51,7 +51,7 @@ public:
   RemoteLoader();
 };
 
-DNSBackend* be;
+std::unique_ptr<DNSBackend> backendUnderTest;
 
 #define BOOST_TEST_DYN_LINK
 #define BOOST_TEST_MAIN
@@ -66,7 +66,7 @@ struct RemotebackendSetup
 {
   RemotebackendSetup()
   {
-    be = nullptr;
+    backendUnderTest = nullptr;
     try {
       // setup minimum arguments
       ::arg().set("module-dir") = "./.libs";
@@ -75,7 +75,7 @@ struct RemotebackendSetup
       // then get us a instance of it
       ::arg().set("remote-connection-string") = "http:url=http://localhost:62434/dns/endpoint.json,post=1,post_json=1";
       ::arg().set("remote-dnssec") = "yes";
-      be = BackendMakers().all()[0];
+      backendUnderTest = std::move(BackendMakers().all()[0]);
     }
     catch (PDNSException& ex) {
       BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason);
index 6ad872c2812759c45b5709f295c6d80cb75f6ac3..c643533d461e474185e7d1ee27aaf99b4eb57ded 100644 (file)
@@ -60,13 +60,13 @@ public:
   RemoteLoader();
 };
 
-DNSBackend* be;
+std::unique_ptr<DNSBackend> backendUnderTest;
 
 struct RemotebackendSetup
 {
   RemotebackendSetup()
   {
-    be = nullptr;
+    backendUnderTest = nullptr;
     try {
       // setup minimum arguments
       ::arg().set("module-dir") = "./.libs";
@@ -75,7 +75,7 @@ struct RemotebackendSetup
       // then get us a instance of it
       ::arg().set("remote-connection-string") = "pipe:command=unittest_pipe.rb";
       ::arg().set("remote-dnssec") = "yes";
-      be = BackendMakers().all()[0];
+      backendUnderTest = std::move(BackendMakers().all()[0]);
       // load few record types to help out
       SOARecordContent::report();
       NSRecordContent::report();
index fe129623f16c8a51f593b6387e6d0ad449afc920..fcae528e377735d32910c4ade56959e9143301de 100644 (file)
@@ -51,7 +51,7 @@ public:
   RemoteLoader();
 };
 
-DNSBackend* be;
+std::unique_ptr<DNSBackend> backendUnderTest;
 
 #define BOOST_TEST_DYN_LINK
 #define BOOST_TEST_MAIN
@@ -66,7 +66,7 @@ struct RemotebackendSetup
 {
   RemotebackendSetup()
   {
-    be = nullptr;
+    backendUnderTest = nullptr;
     try {
       // setup minimum arguments
       ::arg().set("module-dir") = "./.libs";
@@ -75,7 +75,7 @@ struct RemotebackendSetup
       // then get us a instance of it
       ::arg().set("remote-connection-string") = "http:url=http://localhost:62434/dns,post=1";
       ::arg().set("remote-dnssec") = "yes";
-      be = BackendMakers().all()[0];
+      backendUnderTest = std::move(BackendMakers().all()[0]);
     }
     catch (PDNSException& ex) {
       BOOST_TEST_MESSAGE("Cannot start remotebackend: " << ex.reason);
index fd2c1b15a6aa9bc78bb30cbdde01bf6081ecc602..5c16564e3e440e92035ce212eba3b7c212cb14d9 100644 (file)
@@ -60,13 +60,13 @@ public:
   RemoteLoader();
 };
 
-DNSBackend* be;
+std::unique_ptr<DNSBackend> backendUnderTest;
 
 struct RemotebackendSetup
 {
   RemotebackendSetup()
   {
-    be = nullptr;
+    backendUnderTest = nullptr;
     try {
       // setup minimum arguments
       ::arg().set("module-dir") = "./.libs";
@@ -75,7 +75,7 @@ struct RemotebackendSetup
       // then get us a instance of it
       ::arg().set("remote-connection-string") = "unix:path=/tmp/remotebackend.sock";
       ::arg().set("remote-dnssec") = "yes";
-      be = BackendMakers().all()[0];
+      backendUnderTest = std::move(BackendMakers().all()[0]);
       // load few record types to help out
       SOARecordContent::report();
       NSRecordContent::report();
index bccf0768372d43b6eb7f7519a56131e58664d256..e7f65cda1d0de8aaab5a97fe3e301cf8fc6a64a5 100644 (file)
@@ -59,7 +59,7 @@ public:
   RemoteLoader();
 };
 
-DNSBackend* be;
+std::unique_ptr<DNSBackend> backendUnderTest;
 
 #ifdef REMOTEBACKEND_ZEROMQ
 #include <boost/test/unit_test.hpp>
@@ -68,7 +68,7 @@ struct RemotebackendSetup
 {
   RemotebackendSetup()
   {
-    be = nullptr;
+    backendUnderTest = nullptr;
     try {
       // setup minimum arguments
       ::arg().set("module-dir") = "./.libs";
@@ -77,7 +77,7 @@ struct RemotebackendSetup
       // then get us a instance of it
       ::arg().set("remote-connection-string") = "zeromq:endpoint=ipc:///tmp/remotebackend.0";
       ::arg().set("remote-dnssec") = "yes";
-      be = BackendMakers().all()[0];
+      backendUnderTest = std::move(BackendMakers().all()[0]);
       // load few record types to help out
       SOARecordContent::report();
       NSRecordContent::report();
index e4a43208bf9ddad6d495ae37a4c75cb99afadfff..566390aa915d21b5a391b6511ae584286c3f06b2 100644 (file)
 
 #include "test-remotebackend-keys.hh"
 
-extern DNSBackend* be;
+extern std::unique_ptr<DNSBackend> backendUnderTest;
 
 BOOST_AUTO_TEST_SUITE(test_remotebackend_so)
 
 BOOST_AUTO_TEST_CASE(test_method_lookup)
 {
   BOOST_TEST_MESSAGE("Testing lookup method");
-  DNSResourceRecord rr;
-  be->lookup(QType(QType::SOA), DNSName("unit.test."));
+  DNSResourceRecord resourceRecord;
+  backendUnderTest->lookup(QType(QType::SOA), DNSName("unit.test."));
   // then try to get()
-  BOOST_CHECK(be->get(rr)); // and this should be TRUE.
+  BOOST_CHECK(backendUnderTest->get(resourceRecord)); // and this should be TRUE.
   // then we check rr contains what we expect
-  BOOST_CHECK_EQUAL(rr.qname.toString(), "unit.test.");
-  BOOST_CHECK_MESSAGE(rr.qtype == QType::SOA, "returned qtype was not SOA");
-  BOOST_CHECK_EQUAL(rr.content, "ns.unit.test. hostmaster.unit.test. 1 2 3 4 5");
-  BOOST_CHECK_EQUAL(rr.ttl, 300);
+  BOOST_CHECK_EQUAL(resourceRecord.qname.toString(), "unit.test.");
+  BOOST_CHECK_MESSAGE(resourceRecord.qtype == QType::SOA, "returned qtype was not SOA");
+  BOOST_CHECK_EQUAL(resourceRecord.content, "ns.unit.test. hostmaster.unit.test. 1 2 3 4 5");
+  BOOST_CHECK_EQUAL(resourceRecord.ttl, 300);
 }
 
 BOOST_AUTO_TEST_CASE(test_method_lookup_empty)
 {
   BOOST_TEST_MESSAGE("Testing lookup method with empty result");
-  DNSResourceRecord rr;
-  be->lookup(QType(QType::SOA), DNSName("empty.unit.test."));
+  DNSResourceRecord resourceRecord;
+  backendUnderTest->lookup(QType(QType::SOA), DNSName("empty.unit.test."));
   // then try to get()
-  BOOST_CHECK(!be->get(rr)); // and this should be FALSE
+  BOOST_CHECK(!backendUnderTest->get(resourceRecord)); // and this should be FALSE
 }
 
 BOOST_AUTO_TEST_CASE(test_method_list)
 {
   int record_count = 0;
-  DNSResourceRecord rr;
+  DNSResourceRecord resourceRecord;
 
   BOOST_TEST_MESSAGE("Testing list method");
-  be->list(DNSName("unit.test."), -1);
-  while (be->get(rr)) {
+  backendUnderTest->list(DNSName("unit.test."), -1);
+  while (backendUnderTest->get(resourceRecord)) {
     record_count++;
   }
 
@@ -85,7 +85,7 @@ BOOST_AUTO_TEST_CASE(test_method_list)
 BOOST_AUTO_TEST_CASE(test_method_doesDNSSEC)
 {
   BOOST_TEST_MESSAGE("Testing doesDNSSEC method");
-  BOOST_CHECK(be->doesDNSSEC()); // should be true
+  BOOST_CHECK(backendUnderTest->doesDNSSEC()); // should be true
 }
 
 BOOST_AUTO_TEST_CASE(test_method_setDomainMetadata)
@@ -93,27 +93,27 @@ BOOST_AUTO_TEST_CASE(test_method_setDomainMetadata)
   std::vector<std::string> meta;
   meta.emplace_back("VALUE");
   BOOST_TEST_MESSAGE("Testing setDomainMetadata method");
-  BOOST_CHECK(be->setDomainMetadata(DNSName("unit.test."), "TEST", meta));
+  BOOST_CHECK(backendUnderTest->setDomainMetadata(DNSName("unit.test."), "TEST", meta));
 }
 
 BOOST_AUTO_TEST_CASE(test_method_alsoNotifies)
 {
-  BOOST_CHECK(be->setDomainMetadata(DNSName("unit.test."), "ALSO-NOTIFY", {"192.0.2.1"}));
+  BOOST_CHECK(backendUnderTest->setDomainMetadata(DNSName("unit.test."), "ALSO-NOTIFY", {"192.0.2.1"}));
   std::set<std::string> alsoNotifies;
   BOOST_TEST_MESSAGE("Testing alsoNotifies method");
-  be->alsoNotifies(DNSName("unit.test."), &alsoNotifies);
+  backendUnderTest->alsoNotifies(DNSName("unit.test."), &alsoNotifies);
   BOOST_CHECK_EQUAL(alsoNotifies.size(), 1);
   if (!alsoNotifies.empty()) {
     BOOST_CHECK_EQUAL(alsoNotifies.count("192.0.2.1"), 1);
   }
-  BOOST_CHECK(be->setDomainMetadata(DNSName("unit.test."), "ALSO-NOTIFY", std::vector<std::string>()));
+  BOOST_CHECK(backendUnderTest->setDomainMetadata(DNSName("unit.test."), "ALSO-NOTIFY", std::vector<std::string>()));
 }
 
 BOOST_AUTO_TEST_CASE(test_method_getDomainMetadata)
 {
   std::vector<std::string> meta;
   BOOST_TEST_MESSAGE("Testing getDomainMetadata method");
-  be->getDomainMetadata(DNSName("unit.test."), "TEST", meta);
+  backendUnderTest->getDomainMetadata(DNSName("unit.test."), "TEST", meta);
   BOOST_CHECK_EQUAL(meta.size(), 1);
   // in case we got more than one value, which would be unexpected
   // but not fatal
@@ -126,7 +126,7 @@ BOOST_AUTO_TEST_CASE(test_method_getAllDomainMetadata)
 {
   std::map<std::string, std::vector<std::string>> meta;
   BOOST_TEST_MESSAGE("Testing getAllDomainMetadata method");
-  be->getAllDomainMetadata(DNSName("unit.test."), meta);
+  backendUnderTest->getAllDomainMetadata(DNSName("unit.test."), meta);
   BOOST_CHECK_EQUAL(meta.size(), 1);
   // in case we got more than one value, which would be unexpected
   // but not fatal
@@ -138,11 +138,11 @@ BOOST_AUTO_TEST_CASE(test_method_getAllDomainMetadata)
 BOOST_AUTO_TEST_CASE(test_method_addDomainKey)
 {
   BOOST_TEST_MESSAGE("Testing addDomainKey method");
-  int64_t id = 0;
-  be->addDomainKey(DNSName("unit.test."), k1, id);
-  BOOST_CHECK_EQUAL(id, 1);
-  be->addDomainKey(DNSName("unit.test."), k2, id);
-  BOOST_CHECK_EQUAL(id, 2);
+  int64_t keyID = 0;
+  backendUnderTest->addDomainKey(DNSName("unit.test."), k1, keyID);
+  BOOST_CHECK_EQUAL(keyID, 1);
+  backendUnderTest->addDomainKey(DNSName("unit.test."), k2, keyID);
+  BOOST_CHECK_EQUAL(keyID, 2);
 }
 
 BOOST_AUTO_TEST_CASE(test_method_getDomainKeys)
@@ -150,18 +150,18 @@ BOOST_AUTO_TEST_CASE(test_method_getDomainKeys)
   std::vector<DNSBackend::KeyData> keys;
   BOOST_TEST_MESSAGE("Testing getDomainKeys method");
   // we expect to get two keys
-  be->getDomainKeys(DNSName("unit.test."), keys);
+  backendUnderTest->getDomainKeys(DNSName("unit.test."), keys);
   BOOST_CHECK_EQUAL(keys.size(), 2);
   // in case we got more than 2 keys, which would be unexpected
   // but not fatal
   if (keys.size() > 1) {
     // check that we have two keys
-    for (DNSBackend::KeyData& kd : keys) {
-      BOOST_CHECK(kd.id > 0);
-      BOOST_CHECK(kd.flags == 256 || kd.flags == 257);
-      BOOST_CHECK(kd.active == true);
-      BOOST_CHECK(kd.published == true);
-      BOOST_CHECK(kd.content.size() > 500);
+    for (DNSBackend::KeyData& keyData : keys) {
+      BOOST_CHECK(keyData.id > 0);
+      BOOST_CHECK(keyData.flags == 256 || keyData.flags == 257);
+      BOOST_CHECK(keyData.active == true);
+      BOOST_CHECK(keyData.published == true);
+      BOOST_CHECK(keyData.content.size() > 500);
     }
   }
 }
@@ -169,19 +169,19 @@ BOOST_AUTO_TEST_CASE(test_method_getDomainKeys)
 BOOST_AUTO_TEST_CASE(test_method_deactivateDomainKey)
 {
   BOOST_TEST_MESSAGE("Testing deactivateDomainKey method");
-  BOOST_CHECK(be->deactivateDomainKey(DNSName("unit.test."), 1));
+  BOOST_CHECK(backendUnderTest->deactivateDomainKey(DNSName("unit.test."), 1));
 }
 
 BOOST_AUTO_TEST_CASE(test_method_activateDomainKey)
 {
   BOOST_TEST_MESSAGE("Testing activateDomainKey method");
-  BOOST_CHECK(be->activateDomainKey(DNSName("unit.test."), 1));
+  BOOST_CHECK(backendUnderTest->activateDomainKey(DNSName("unit.test."), 1));
 }
 
 BOOST_AUTO_TEST_CASE(test_method_removeDomainKey)
 {
-  BOOST_CHECK(be->removeDomainKey(DNSName("unit.test."), 2));
-  BOOST_CHECK(be->removeDomainKey(DNSName("unit.test."), 1));
+  BOOST_CHECK(backendUnderTest->removeDomainKey(DNSName("unit.test."), 2));
+  BOOST_CHECK(backendUnderTest->removeDomainKey(DNSName("unit.test."), 1));
 }
 
 BOOST_AUTO_TEST_CASE(test_method_getBeforeAndAfterNamesAbsolute)
@@ -191,7 +191,7 @@ BOOST_AUTO_TEST_CASE(test_method_getBeforeAndAfterNamesAbsolute)
   DNSName after;
   BOOST_TEST_MESSAGE("Testing getBeforeAndAfterNamesAbsolute method");
 
-  be->getBeforeAndAfterNamesAbsolute(-1, DNSName("middle.unit.test."), unhashed, before, after);
+  backendUnderTest->getBeforeAndAfterNamesAbsolute(-1, DNSName("middle.unit.test."), unhashed, before, after);
   BOOST_CHECK_EQUAL(unhashed.toString(), "middle.");
   BOOST_CHECK_EQUAL(before.toString(), "begin.");
   BOOST_CHECK_EQUAL(after.toString(), "stop.");
@@ -202,7 +202,7 @@ BOOST_AUTO_TEST_CASE(test_method_setTSIGKey)
   std::string algorithm;
   std::string content;
   BOOST_TEST_MESSAGE("Testing setTSIGKey method");
-  BOOST_CHECK_MESSAGE(be->setTSIGKey(DNSName("unit.test."), DNSName("hmac-md5."), "kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys="), "did not return true");
+  BOOST_CHECK_MESSAGE(backendUnderTest->setTSIGKey(DNSName("unit.test."), DNSName("hmac-md5."), "kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys="), "did not return true");
 }
 
 BOOST_AUTO_TEST_CASE(test_method_getTSIGKey)
@@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE(test_method_getTSIGKey)
   DNSName algorithm;
   std::string content;
   BOOST_TEST_MESSAGE("Testing getTSIGKey method");
-  be->getTSIGKey(DNSName("unit.test."), algorithm, content);
+  backendUnderTest->getTSIGKey(DNSName("unit.test."), algorithm, content);
   BOOST_CHECK_EQUAL(algorithm.toString(), "hmac-md5.");
   BOOST_CHECK_EQUAL(content, "kp4/24gyYsEzbuTVJRUMoqGFmN3LYgVDzJ/3oRSP7ys=");
 }
@@ -220,14 +220,14 @@ BOOST_AUTO_TEST_CASE(test_method_deleteTSIGKey)
   std::string algorithm;
   std::string content;
   BOOST_TEST_MESSAGE("Testing deleteTSIGKey method");
-  BOOST_CHECK_MESSAGE(be->deleteTSIGKey(DNSName("unit.test.")), "did not return true");
+  BOOST_CHECK_MESSAGE(backendUnderTest->deleteTSIGKey(DNSName("unit.test.")), "did not return true");
 }
 
 BOOST_AUTO_TEST_CASE(test_method_getTSIGKeys)
 {
   std::vector<struct TSIGKey> keys;
   BOOST_TEST_MESSAGE("Testing getTSIGKeys method");
-  be->getTSIGKeys(keys);
+  backendUnderTest->getTSIGKeys(keys);
   BOOST_CHECK(!keys.empty());
   if (!keys.empty()) {
     BOOST_CHECK_EQUAL(keys[0].name.toString(), "test.");
@@ -239,159 +239,159 @@ BOOST_AUTO_TEST_CASE(test_method_getTSIGKeys)
 BOOST_AUTO_TEST_CASE(test_method_setNotified)
 {
   BOOST_TEST_MESSAGE("Testing setNotified method");
-  be->setNotified(1, 2);
+  backendUnderTest->setNotified(1, 2);
   BOOST_CHECK(true); // we check this on next step
 }
 
 BOOST_AUTO_TEST_CASE(test_method_getDomainInfo)
 {
-  DomainInfo di;
+  DomainInfo domainInfo;
   BOOST_TEST_MESSAGE("Testing getDomainInfo method");
-  be->getDomainInfo(DNSName("unit.test."), di);
-  BOOST_CHECK_EQUAL(di.zone.toString(), "unit.test.");
-  BOOST_CHECK_EQUAL(di.serial, 2);
-  BOOST_CHECK_EQUAL(di.notified_serial, 2);
-  BOOST_CHECK_EQUAL(di.kind, DomainInfo::Native);
-  BOOST_CHECK_EQUAL(di.backend, be);
+  backendUnderTest->getDomainInfo(DNSName("unit.test."), domainInfo);
+  BOOST_CHECK_EQUAL(domainInfo.zone.toString(), "unit.test.");
+  BOOST_CHECK_EQUAL(domainInfo.serial, 2);
+  BOOST_CHECK_EQUAL(domainInfo.notified_serial, 2);
+  BOOST_CHECK_EQUAL(domainInfo.kind, DomainInfo::Native);
+  BOOST_CHECK_EQUAL(domainInfo.backend, backendUnderTest.get());
 }
 
 BOOST_AUTO_TEST_CASE(test_method_getAllDomains)
 {
-  DomainInfo di;
+  DomainInfo domainInfo;
   BOOST_TEST_MESSAGE("Testing getAllDomains method");
   vector<DomainInfo> result;
 
-  be->getAllDomains(&result, true, true);
+  backendUnderTest->getAllDomains(&result, true, true);
 
   BOOST_REQUIRE(!result.empty());
-  di = result.at(0);
-  BOOST_CHECK_EQUAL(di.zone.toString(), "unit.test.");
-  BOOST_CHECK_EQUAL(di.serial, 2);
-  BOOST_CHECK_EQUAL(di.notified_serial, 2);
-  BOOST_CHECK_EQUAL(di.kind, DomainInfo::Native);
-  BOOST_CHECK_EQUAL(di.backend, be);
+  domainInfo = result.at(0);
+  BOOST_CHECK_EQUAL(domainInfo.zone.toString(), "unit.test.");
+  BOOST_CHECK_EQUAL(domainInfo.serial, 2);
+  BOOST_CHECK_EQUAL(domainInfo.notified_serial, 2);
+  BOOST_CHECK_EQUAL(domainInfo.kind, DomainInfo::Native);
+  BOOST_CHECK_EQUAL(domainInfo.backend, backendUnderTest.get());
 }
 
-BOOST_AUTO_TEST_CASE(test_method_superMasterBackend)
+BOOST_AUTO_TEST_CASE(test_method_autoPrimaryBackend)
 {
-  DNSResourceRecord rr;
+  DNSResourceRecord resourceRecord;
   std::vector<DNSResourceRecord> nsset;
   DNSBackend* dbd = nullptr;
-  BOOST_TEST_MESSAGE("Testing superMasterBackend method");
-
-  rr.qname = DNSName("example.com.");
-  rr.qtype = QType::NS;
-  rr.qclass = QClass::IN;
-  rr.ttl = 300;
-  rr.content = "ns1.example.com.";
-  nsset.push_back(rr);
-  rr.qname = DNSName("example.com.");
-  rr.qtype = QType::NS;
-  rr.qclass = QClass::IN;
-  rr.ttl = 300;
-  rr.content = "ns2.example.com.";
-  nsset.push_back(rr);
-
-  BOOST_CHECK(be->superMasterBackend("10.0.0.1", DNSName("example.com."), nsset, nullptr, nullptr, &dbd));
+  BOOST_TEST_MESSAGE("Testing autoPrimaryBackend method");
+
+  resourceRecord.qname = DNSName("example.com.");
+  resourceRecord.qtype = QType::NS;
+  resourceRecord.qclass = QClass::IN;
+  resourceRecord.ttl = 300;
+  resourceRecord.content = "ns1.example.com.";
+  nsset.push_back(resourceRecord);
+  resourceRecord.qname = DNSName("example.com.");
+  resourceRecord.qtype = QType::NS;
+  resourceRecord.qclass = QClass::IN;
+  resourceRecord.ttl = 300;
+  resourceRecord.content = "ns2.example.com.";
+  nsset.push_back(resourceRecord);
+
+  BOOST_CHECK(backendUnderTest->autoPrimaryBackend("10.0.0.1", DNSName("example.com."), nsset, nullptr, nullptr, &dbd));
 
   // let's see what we got
-  BOOST_CHECK_EQUAL(dbd, be);
+  BOOST_CHECK_EQUAL(dbd, backendUnderTest.get());
 }
 
-BOOST_AUTO_TEST_CASE(test_method_createSlaveDomain)
+BOOST_AUTO_TEST_CASE(test_method_createSecondaryDomain)
 {
-  BOOST_TEST_MESSAGE("Testing createSlaveDomain method");
-  BOOST_CHECK(be->createSlaveDomain("10.0.0.1", DNSName("pirate.unit.test."), "", ""));
+  BOOST_TEST_MESSAGE("Testing createSecondaryDomain method");
+  BOOST_CHECK(backendUnderTest->createSecondaryDomain("10.0.0.1", DNSName("pirate.unit.test."), "", ""));
 }
 
 BOOST_AUTO_TEST_CASE(test_method_feedRecord)
 {
-  DNSResourceRecord rr;
+  DNSResourceRecord resourceRecord;
   BOOST_TEST_MESSAGE("Testing feedRecord method");
-  be->startTransaction(DNSName("example.com."), 2);
-  rr.qname = DNSName("example.com.");
-  rr.qtype = QType::SOA;
-  rr.qclass = QClass::IN;
-  rr.ttl = 300;
-  rr.content = "ns1.example.com. hostmaster.example.com. 2013013441 7200 3600 1209600 300";
-  BOOST_CHECK(be->feedRecord(rr, DNSName()));
-  rr.qname = DNSName("replace.example.com.");
-  rr.qtype = QType::A;
-  rr.qclass = QClass::IN;
-  rr.ttl = 300;
-  rr.content = "127.0.0.1";
-  BOOST_CHECK(be->feedRecord(rr, DNSName()));
-  be->commitTransaction();
+  backendUnderTest->startTransaction(DNSName("example.com."), 2);
+  resourceRecord.qname = DNSName("example.com.");
+  resourceRecord.qtype = QType::SOA;
+  resourceRecord.qclass = QClass::IN;
+  resourceRecord.ttl = 300;
+  resourceRecord.content = "ns1.example.com. hostmaster.example.com. 2013013441 7200 3600 1209600 300";
+  BOOST_CHECK(backendUnderTest->feedRecord(resourceRecord, DNSName()));
+  resourceRecord.qname = DNSName("replace.example.com.");
+  resourceRecord.qtype = QType::A;
+  resourceRecord.qclass = QClass::IN;
+  resourceRecord.ttl = 300;
+  resourceRecord.content = "127.0.0.1";
+  BOOST_CHECK(backendUnderTest->feedRecord(resourceRecord, DNSName()));
+  backendUnderTest->commitTransaction();
 }
 
 BOOST_AUTO_TEST_CASE(test_method_replaceRRSet)
 {
-  be->startTransaction(DNSName("example.com."), 2);
-  DNSResourceRecord rr;
+  backendUnderTest->startTransaction(DNSName("example.com."), 2);
+  DNSResourceRecord resourceRecord;
   std::vector<DNSResourceRecord> rrset;
   BOOST_TEST_MESSAGE("Testing replaceRRSet method");
-  rr.qname = DNSName("replace.example.com.");
-  rr.qtype = QType::A;
-  rr.qclass = QClass::IN;
-  rr.ttl = 300;
-  rr.content = "1.1.1.1";
-  rrset.push_back(rr);
-  BOOST_CHECK(be->replaceRRSet(2, DNSName("replace.example.com."), QType(QType::A), rrset));
-  be->commitTransaction();
+  resourceRecord.qname = DNSName("replace.example.com.");
+  resourceRecord.qtype = QType::A;
+  resourceRecord.qclass = QClass::IN;
+  resourceRecord.ttl = 300;
+  resourceRecord.content = "1.1.1.1";
+  rrset.push_back(resourceRecord);
+  BOOST_CHECK(backendUnderTest->replaceRRSet(2, DNSName("replace.example.com."), QType(QType::A), rrset));
+  backendUnderTest->commitTransaction();
 }
 
 BOOST_AUTO_TEST_CASE(test_method_feedEnts)
 {
   BOOST_TEST_MESSAGE("Testing feedEnts method");
-  be->startTransaction(DNSName("example.com."), 2);
+  backendUnderTest->startTransaction(DNSName("example.com."), 2);
   map<DNSName, bool> nonterm = boost::assign::map_list_of(DNSName("_udp"), true)(DNSName("_sip._udp"), true);
-  BOOST_CHECK(be->feedEnts(2, nonterm));
-  be->commitTransaction();
+  BOOST_CHECK(backendUnderTest->feedEnts(2, nonterm));
+  backendUnderTest->commitTransaction();
 }
 
 BOOST_AUTO_TEST_CASE(test_method_feedEnts3)
 {
   BOOST_TEST_MESSAGE("Testing feedEnts3 method");
-  be->startTransaction(DNSName("example.com"), 2);
+  backendUnderTest->startTransaction(DNSName("example.com"), 2);
   NSEC3PARAMRecordContent ns3prc;
   ns3prc.d_iterations = 1;
   ns3prc.d_salt = "\u00aa\u00bb\u00cc\u00dd";
   map<DNSName, bool> nonterm = boost::assign::map_list_of(DNSName("_udp"), true)(DNSName("_sip._udp"), true);
-  BOOST_CHECK(be->feedEnts3(2, DNSName("example.com."), nonterm, ns3prc, 0));
-  be->commitTransaction();
+  BOOST_CHECK(backendUnderTest->feedEnts3(2, DNSName("example.com."), nonterm, ns3prc, 0));
+  backendUnderTest->commitTransaction();
 }
 
 BOOST_AUTO_TEST_CASE(test_method_abortTransaction)
 {
   BOOST_TEST_MESSAGE("Testing abortTransaction method");
-  be->startTransaction(DNSName("example.com."), 2);
-  BOOST_CHECK(be->abortTransaction());
+  backendUnderTest->startTransaction(DNSName("example.com."), 2);
+  BOOST_CHECK(backendUnderTest->abortTransaction());
 }
 
 BOOST_AUTO_TEST_CASE(test_method_directBackendCmd)
 {
   BOOST_TEST_MESSAGE("Testing directBackendCmd method");
-  BOOST_CHECK_EQUAL(be->directBackendCmd("PING 1234"), "PING 1234");
+  BOOST_CHECK_EQUAL(backendUnderTest->directBackendCmd("PING 1234"), "PING 1234");
 }
 
-BOOST_AUTO_TEST_CASE(test_method_getUpdatedMasters)
+BOOST_AUTO_TEST_CASE(test_method_getUpdatedPrimaries)
 {
-  DomainInfo di;
-  BOOST_TEST_MESSAGE("Testing getUpdatedMasters method");
+  DomainInfo domainInfo;
+  BOOST_TEST_MESSAGE("Testing getUpdatedPrimaries method");
   vector<DomainInfo> result;
   std::unordered_set<DNSName> catalogs;
   CatalogHashMap hashes;
 
-  be->getUpdatedMasters(result, catalogs, hashes);
+  backendUnderTest->getUpdatedPrimaries(result, catalogs, hashes);
 
   BOOST_REQUIRE(!result.empty());
 
-  di = result.at(0);
-  BOOST_CHECK_EQUAL(di.zone.toString(), "master.test.");
-  BOOST_CHECK_EQUAL(di.serial, 2);
-  BOOST_CHECK_EQUAL(di.notified_serial, 2);
-  BOOST_CHECK_EQUAL(di.kind, DomainInfo::Master);
-  BOOST_CHECK_EQUAL(di.backend, be);
+  domainInfo = result.at(0);
+  BOOST_CHECK_EQUAL(domainInfo.zone.toString(), "master.test.");
+  BOOST_CHECK_EQUAL(domainInfo.serial, 2);
+  BOOST_CHECK_EQUAL(domainInfo.notified_serial, 2);
+  BOOST_CHECK_EQUAL(domainInfo.kind, DomainInfo::Primary);
+  BOOST_CHECK_EQUAL(domainInfo.backend, backendUnderTest.get());
 }
 
 BOOST_AUTO_TEST_SUITE_END();
index b76f20ed1c28656ca1a6eca3ffbcc6e2d0504867..6ba897fb48f94b53d60e5050e56f045ab3e511ae 100644 (file)
@@ -88,7 +88,7 @@ TinyDNSBackend::TinyDNSBackend(const string& suffix)
   d_isWildcardQuery = false;
 }
 
-void TinyDNSBackend::getUpdatedMasters(vector<DomainInfo>& retDomains, std::unordered_set<DNSName>& /* catalogs */, CatalogHashMap& /* catalogHashes */)
+void TinyDNSBackend::getUpdatedPrimaries(vector<DomainInfo>& retDomains, std::unordered_set<DNSName>& /* catalogs */, CatalogHashMap& /* catalogHashes */)
 {
   auto domainInfo = s_domainInfo.lock(); //TODO: We could actually lock less if we do it per suffix.
   if (!domainInfo->count(d_suffix)) {
@@ -175,7 +175,7 @@ void TinyDNSBackend::getAllDomains(vector<DomainInfo>* domains, bool getSerial,
       di.id = -1; //TODO: Check if this is ok.
       di.backend = this;
       di.zone = rr.qname;
-      di.kind = DomainInfo::Master;
+      di.kind = DomainInfo::Primary;
       di.last_check = time(0);
 
       if (getSerial) {
@@ -340,7 +340,7 @@ bool TinyDNSBackend::get(DNSResourceRecord& rr)
         dr.d_type = rr.qtype.getCode();
         dr.d_clen = val.size() - pr.getPosition();
 
-        auto drc = DNSRecordContent::mastermake(dr, pr);
+        auto drc = DNSRecordContent::make(dr, pr);
         rr.content = drc->getZoneRepresentation();
         DLOG(cerr << "CONTENT: " << rr.content << endl);
       }
@@ -374,7 +374,7 @@ public:
 
   void declareArguments(const string& suffix = "") override
   {
-    declare(suffix, "notify-on-startup", "Tell the TinyDNSBackend to notify all the slave nameservers on startup. Default is no.", "no");
+    declare(suffix, "notify-on-startup", "Tell the TinyDNSBackend to notify all the secondary nameservers on startup. Default is no.", "no");
     declare(suffix, "dbfile", "Location of the cdb data file", "data.cdb");
     declare(suffix, "tai-adjust", "This adjusts the TAI value if timestamps are used. These seconds will be added to the start point (1970) and will allow you to adjust for leap seconds. The default is 11.", "11");
     declare(suffix, "locations", "Enable or Disable location support in the backend. Changing the value to 'no' will make the backend ignore the locations. This then returns all records!", "yes");
index 29d1e64798549aa01b2d5d06e94e8312ae92d243..bcad58d4c3c1829c7a8b6e64742f87969784989f 100644 (file)
@@ -72,8 +72,8 @@ public:
   bool get(DNSResourceRecord& rr) override;
   void getAllDomains(vector<DomainInfo>* domains, bool getSerial, bool include_disabled) override;
 
-  //Master mode operation
-  void getUpdatedMasters(vector<DomainInfo>& domains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes) override;
+  // Primary mode operation
+  void getUpdatedPrimaries(vector<DomainInfo>& domains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes) override;
   void setNotified(uint32_t id, uint32_t serial) override;
 
 private:
index 75e0fa213f22bde20eecd1bb5637b40b8c8cfa81..870588bce04f6ed57a9ccf89c7c411118ef73e69 100644 (file)
@@ -196,7 +196,9 @@ pdns_server_SOURCES = \
        auth-catalogzone.cc auth-catalogzone.hh \
        auth-main.cc auth-main.hh \
        auth-packetcache.cc auth-packetcache.hh \
+       auth-primarycommunicator.cc \
        auth-querycache.cc auth-querycache.hh \
+       auth-secondarycommunicator.cc \
        auth-zonecache.cc auth-zonecache.hh \
        axfr-retriever.cc axfr-retriever.hh \
        backends/gsql/gsqlbackend.cc backends/gsql/gsqlbackend.hh \
@@ -246,7 +248,6 @@ pdns_server_SOURCES = \
        logging.hh \
        lua-auth4.cc lua-auth4.hh \
        lua-base4.cc lua-base4.hh \
-       mastercommunicator.cc \
        misc.cc misc.hh \
        nameserver.cc nameserver.hh \
        namespaces.hh \
@@ -270,7 +271,6 @@ pdns_server_SOURCES = \
        shuffle.cc shuffle.hh \
        signingpipe.cc signingpipe.hh \
        sillyrecords.cc \
-       slavecommunicator.cc \
        stat_t.hh \
        statbag.cc statbag.hh \
        stubresolver.cc stubresolver.hh \
index 3970d8cd51af75a84ea46fe861088d51f0889858..d0a4ec7767202726a5a80f53e1de14cec09eb7ba 100644 (file)
@@ -359,12 +359,6 @@ static const map<string, string> deprecateList = {
   {"snmp-master-socket", "snmp-daemon-socket"},
   {"xpf-allow-from", "Proxy Protocol"},
   {"xpf-rr-code", "Proxy Protocol"},
-  {"allow-unsigned-supermaster", "allow-unsigned-autoprimary"},
-  {"master", "primary"},
-  {"slave-cycle-interval", "xfr-cycle-interval"},
-  {"slave-renotify", "secondary-do-renotify"},
-  {"slave", "secondary"},
-  {"superslave", "autosecondary"},
   {"domain-metadata-cache-ttl", "zone-metadata-cache-ttl"},
 };
 
index 559e1f29c358a6656b198e6a5b63bdbf0ce385f9..4d803765f02a76fbf33f15377dfedd1302564b76 100644 (file)
@@ -165,9 +165,8 @@ static void declareArguments()
   ::arg().set("proxy-protocol-maximum-size", "The maximum size of a proxy protocol payload, including the TLV values") = "512";
   ::arg().setSwitch("send-signed-notify", "Send TSIG secured NOTIFY if TSIG key is configured for a zone") = "yes";
   ::arg().set("allow-unsigned-notify", "Allow unsigned notifications for TSIG secured zones") = "yes"; // FIXME: change to 'no' later
-  ::arg().set("allow-unsigned-supermaster", "Allow supermasters to create zones without TSIG signed NOTIFY") = "yes";
   ::arg().set("allow-unsigned-autoprimary", "Allow autoprimaries to create zones without TSIG signed NOTIFY") = "yes";
-  ::arg().setSwitch("forward-dnsupdate", "A global setting to allow DNS update packages that are for a Slave zone, to be forwarded to the master.") = "yes";
+  ::arg().setSwitch("forward-dnsupdate", "A global setting to allow DNS update packages that are for a Secondary zone, to be forwarded to the primary.") = "yes";
   ::arg().setSwitch("log-dns-details", "If PDNS should log DNS non-erroneous details") = "no";
   ::arg().setSwitch("log-dns-queries", "If PDNS should log all incoming DNS queries") = "no";
   ::arg().set("local-address", "Local IP addresses to which we bind") = "0.0.0.0, ::";
@@ -178,7 +177,7 @@ static void declareArguments()
   ::arg().set("overload-queue-length", "Maximum queuelength moving to packetcache only") = "0";
   ::arg().set("max-queue-length", "Maximum queuelength before considering situation lost") = "5000";
 
-  ::arg().set("retrieval-threads", "Number of AXFR-retrieval threads for slave operation") = "2";
+  ::arg().set("retrieval-threads", "Number of AXFR-retrieval threads for secondary operation") = "2";
   ::arg().setSwitch("api", "Enable/disable the REST API (including HTTP listener)") = "no";
   ::arg().set("api-key", "Static pre-shared authentication key for access to the REST API") = "";
   ::arg().setSwitch("default-api-rectify", "Default API-RECTIFY value for zones") = "yes";
@@ -212,7 +211,6 @@ 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") = "";
   ::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";
 
@@ -221,12 +219,9 @@ static void declareArguments()
   ::arg().set("tcp-control-secret", "If set, PowerDNS can be controlled over TCP after passing this secret") = "";
   ::arg().set("tcp-control-range", "If set, remote control of PowerDNS is possible over these networks only") = "127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fe80::/10";
 
-  ::arg().setSwitch("slave", "Act as a secondary") = "no";
   ::arg().setSwitch("secondary", "Act as a secondary") = "no";
-  ::arg().setSwitch("master", "Act as a primary") = "no";
   ::arg().setSwitch("primary", "Act as a primary") = "no";
-  ::arg().setSwitch("superslave", "Act as a autosecondary") = "no";
-  ::arg().setSwitch("autosecondary", "Act as an autosecondary (formerly superslave)") = "no";
+  ::arg().setSwitch("autosecondary", "Act as an autosecondary") = "no";
   ::arg().setSwitch("disable-axfr-rectify", "Disable the rectify step during an outgoing AXFR. Only required for regression testing.") = "no";
   ::arg().setSwitch("guardian", "Run within a guardian process") = "no";
   ::arg().setSwitch("prevent-self-notification", "Don't send notifications to what we think is ourself") = "yes";
@@ -266,9 +261,8 @@ static void declareArguments()
   ::arg().set("zone-metadata-cache-ttl", "Seconds to cache zone metadata from the database") = "60";
 
   ::arg().set("trusted-notification-proxy", "IP address of incoming notification proxy") = "";
-  ::arg().set("slave-renotify", "If we should send out notifications for secondaried updates") = "no";
   ::arg().set("secondary-do-renotify", "If this secondary should send out notifications after receiving zone transfers from a primary") = "no";
-  ::arg().set("forward-notify", "IP addresses to forward received notifications to regardless of master or slave settings") = "";
+  ::arg().set("forward-notify", "IP addresses to forward received notifications to regardless of primary or secondary settings") = "";
 
   ::arg().set("default-ttl", "Seconds a result is valid if not set otherwise") = "3600";
   ::arg().set("max-tcp-connections", "Maximum number of TCP connections") = "20";
@@ -313,7 +307,7 @@ static void declareArguments()
   ::arg().set("lua-health-checks-expire-delay", "Stops doing health checks after the record hasn't been used for that delay (in seconds)") = "3600";
   ::arg().set("lua-health-checks-interval", "LUA records health checks monitoring interval in seconds") = "5";
 #endif
-  ::arg().setSwitch("axfr-lower-serial", "Also AXFR a zone from a master with a lower serial") = "no";
+  ::arg().setSwitch("axfr-lower-serial", "Also AXFR a zone from a primary with a lower serial") = "no";
 
   ::arg().set("lua-axfr-script", "Script to be used to edit incoming AXFRs") = "";
   ::arg().set("xfr-max-received-mbytes", "Maximum number of megabytes received from an incoming XFR") = "100";
@@ -1219,7 +1213,7 @@ int main(int argc, char** argv)
     if (::arg().mustDo("version")) {
       showProductVersion();
       showBuildConfiguration();
-      exit(99);
+      return 0;
     }
 
     if (::arg()["config-name"] != "")
@@ -1242,34 +1236,11 @@ int main(int argc, char** argv)
         g_log << Logger::Error << "Unknown logging facility " << ::arg().asNum("logging-facility") << endl;
     }
 
-    if (::arg().mustDo("master"))
-      ::arg().set("primary") = "yes";
-    if (::arg().mustDo("slave"))
-      ::arg().set("secondary") = "yes";
-    if (::arg().mustDo("slave-renotify"))
-      ::arg().set("secondary-do-renotify") = "yes";
-    if (::arg().mustDo("superslave"))
-      ::arg().set("autosecondary") = "yes";
-    if (::arg().mustDo("allow-unsigned-supermaster"))
-      ::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"))
-      ::arg().set("master") = "yes";
-    if (::arg().mustDo("secondary"))
-      ::arg().set("slave") = "yes";
-    if (::arg().mustDo("secondary-do-renotify"))
-      ::arg().set("slave-renotify") = "yes";
-    if (::arg().mustDo("autosecondary"))
-      ::arg().set("superslave") = "yes";
-    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"));
@@ -1437,7 +1408,7 @@ int main(int argc, char** argv)
     DynListener::registerFunc("RESPSIZES", &DLRSizesHandler, "get histogram of response sizes");
     DynListener::registerFunc("REMOTES", &DLRemotesHandler, "get top remotes");
     DynListener::registerFunc("SET", &DLSettingsHandler, "set config variables", "<var> <value>");
-    DynListener::registerFunc("RETRIEVE", &DLNotifyRetrieveHandler, "retrieve slave zone", "<zone> [<ip>]");
+    DynListener::registerFunc("RETRIEVE", &DLNotifyRetrieveHandler, "retrieve secondary zone", "<zone> [<ip>]");
     DynListener::registerFunc("CURRENT-CONFIG", &DLCurrentConfigHandler, "retrieve the current configuration", "[diff]");
     DynListener::registerFunc("LIST-ZONES", &DLListZones, "show list of zones", "[primary|secondary|native|consumer|producer]");
     DynListener::registerFunc("TOKEN-LOGIN", &DLTokenLogin, "Login to a PKCS#11 token", "<module> <slot> <pin>");
similarity index 73%
rename from pdns/mastercommunicator.cc
rename to pdns/auth-primarycommunicator.cc
index 2fcace7e1799e5091d19a93cca4f6c5a4a23f7a2..1ee65e0849a9d4d50d3f7757697ea50715284e15 100644 (file)
 #include "namespaces.hh"
 #include "query-local-address.hh"
 
-
 void CommunicatorClass::queueNotifyDomain(const DomainInfo& di, UeberBackend* B)
 {
-  bool hasQueuedItem=false;
+  bool hasQueuedItem = false;
   set<string> ips;
   set<DNSName> nsset;
   DNSZoneRecord rr;
   FindNS fns;
 
   try {
-  if (d_onlyNotify.size()) {
-    B->lookup(QType(QType::NS), di.zone, di.id);
-    while(B->get(rr))
-      nsset.insert(getRR<NSRecordContent>(rr.dr)->getNS());
-
-    for(const auto & ns : nsset) {
-      vector<string> nsips=fns.lookup(ns, B);
-      if(nsips.empty())
-        g_log<<Logger::Warning<<"Unable to queue notification of domain '"<<di.zone<<"' to nameserver '"<<ns<<"': nameserver does not resolve!"<<endl;
-      else
-        for(const auto & nsip : nsips) {
-          const ComboAddress caIp(nsip, 53);
-          if(!d_preventSelfNotification || !AddressIsUs(caIp)) {
-            if(!d_onlyNotify.match(&caIp))
-              g_log<<Logger::Notice<<"Skipped notification of domain '"<<di.zone<<"' to "<<ns<<" because "<<caIp<<" does not match only-notify."<<endl;
-            else
-              ips.insert(caIp.toStringWithPort());
+    if (d_onlyNotify.size()) {
+      B->lookup(QType(QType::NS), di.zone, di.id);
+      while (B->get(rr))
+        nsset.insert(getRR<NSRecordContent>(rr.dr)->getNS());
+
+      for (const auto& ns : nsset) {
+        vector<string> nsips = fns.lookup(ns, B);
+        if (nsips.empty())
+          g_log << Logger::Warning << "Unable to queue notification of domain '" << di.zone << "' to nameserver '" << ns << "': nameserver does not resolve!" << endl;
+        else
+          for (const auto& nsip : nsips) {
+            const ComboAddress caIp(nsip, 53);
+            if (!d_preventSelfNotification || !AddressIsUs(caIp)) {
+              if (!d_onlyNotify.match(&caIp))
+                g_log << Logger::Notice << "Skipped notification of domain '" << di.zone << "' to " << ns << " because " << caIp << " does not match only-notify." << endl;
+              else
+                ips.insert(caIp.toStringWithPort());
+            }
           }
-        }
-    }
+      }
 
-    for(const auto & ip : ips) {
-      g_log<<Logger::Notice<<"Queued notification of domain '"<<di.zone<<"' to "<<ip<<endl;
-      d_nq.add(di.zone,ip);
-      hasQueuedItem=true;
+      for (const auto& ip : ips) {
+        g_log << Logger::Notice << "Queued notification of domain '" << di.zone << "' to " << ip << endl;
+        d_nq.add(di.zone, ip);
+        hasQueuedItem = true;
+      }
     }
   }
-  }
-  catch (PDNSException &ae) {
+  catch (PDNSException& ae) {
     g_log << Logger::Error << "Error looking up name servers for " << di.zone << ", cannot notify: " << ae.reason << endl;
     return;
   }
-  catch (std::exception &e) {
+  catch (std::exceptione) {
     g_log << Logger::Error << "Error looking up name servers for " << di.zone << ", cannot notify: " << e.what() << endl;
     return;
   }
 
-
   set<string> alsoNotify(d_alsoNotify);
   B->alsoNotifies(di.zone, &alsoNotify);
 
-  for(const auto & j : alsoNotify) {
+  for (const auto& j : alsoNotify) {
     try {
       const ComboAddress caIp(j, 53);
-      g_log<<Logger::Notice<<"Queued also-notification of domain '"<<di.zone<<"' to "<<caIp.toStringWithPort()<<endl;
+      g_log << Logger::Notice << "Queued also-notification of domain '" << di.zone << "' to " << caIp.toStringWithPort() << endl;
       if (!ips.count(caIp.toStringWithPort())) {
         ips.insert(caIp.toStringWithPort());
         d_nq.add(di.zone, caIp.toStringWithPort());
       }
-      hasQueuedItem=true;
+      hasQueuedItem = true;
     }
-    catch(PDNSException &e) {
-      g_log<<Logger::Warning<<"Unparseable IP in ALSO-NOTIFY metadata of domain '"<<di.zone<<"'. Warning: "<<e.reason<<endl;
+    catch (PDNSException& e) {
+      g_log << Logger::Warning << "Unparseable IP in ALSO-NOTIFY metadata of domain '" << di.zone << "'. Warning: " << e.reason << endl;
     }
   }
 
   if (!hasQueuedItem)
-    g_log<<Logger::Warning<<"Request to queue notification for domain '"<<di.zone<<"' was processed, but no valid nameservers or ALSO-NOTIFYs found. Not notifying!"<<endl;
+    g_log << Logger::Warning << "Request to queue notification for domain '" << di.zone << "' was processed, but no valid nameservers or ALSO-NOTIFYs found. Not notifying!" << endl;
 }
 
-
-bool CommunicatorClass::notifyDomain(const DNSName &domain, UeberBackend* B)
+bool CommunicatorClass::notifyDomain(const DNSName& domain, UeberBackend* B)
 {
   DomainInfo di;
-  if(!B->getDomainInfo(domain, di)) {
-    g_log<<Logger::Warning<<"No such domain '"<<domain<<"' in our database"<<endl;
+  if (!B->getDomainInfo(domain, di)) {
+    g_log << Logger::Warning << "No such domain '" << domain << "' in our database" << endl;
     return false;
   }
   queueNotifyDomain(di, B);
@@ -131,9 +128,9 @@ bool CommunicatorClass::notifyDomain(const DNSName &domain, UeberBackend* B)
 
 void NotificationQueue::dump()
 {
-  cerr<<"Waiting for notification responses: "<<endl;
-  for(NotificationRequest& nr :  d_nqueue) {
-    cerr<<nr.domain<<", "<<nr.ip<<endl;
+  cerr << "Waiting for notification responses: " << endl;
+  for (NotificationRequest& nr : d_nqueue) {
+    cerr << nr.domain << ", " << nr.ip << endl;
   }
 }
 
@@ -185,26 +182,26 @@ void CommunicatorClass::getUpdatedProducers(UeberBackend* B, vector<DomainInfo>&
   }
 }
 
-void CommunicatorClass::masterUpdateCheck(PacketHandler *P)
+void CommunicatorClass::primaryUpdateCheck(PacketHandler* P)
 {
-  if(!::arg().mustDo("primary"))
+  if (!::arg().mustDo("primary"))
     return;
 
-  UeberBackend *B=P->getBackend();
+  UeberBackend* B = P->getBackend();
   vector<DomainInfo> cmdomains;
   std::unordered_set<DNSName> catalogs;
   CatalogHashMap catalogHashes;
-  B->getUpdatedMasters(cmdomains, catalogs, catalogHashes);
+  B->getUpdatedPrimaries(cmdomains, catalogs, catalogHashes);
   getUpdatedProducers(B, cmdomains, catalogs, catalogHashes);
 
-  if(cmdomains.empty()) {
+  if (cmdomains.empty()) {
     g_log << Logger::Info << "no primary or producer domains need notifications" << endl;
   }
   else {
     g_log << Logger::Info << cmdomains.size() << " domain" << addS(cmdomains.size()) << " for which we are primary or consumer need" << addS(cmdomains.size()) << " notifications" << endl;
   }
 
-  for(auto& di : cmdomains) {
+  for (auto& di : cmdomains) {
     purgeAuthCachesExact(di.zone);
     g_zoneCache.add(di.zone, di.id);
     queueNotifyDomain(di, B);
@@ -283,7 +280,7 @@ time_t CommunicatorClass::doNotifications(PacketHandler* P)
   return d_nq.earliest();
 }
 
-void CommunicatorClass::sendNotification(int sock, const DNSName& domain, const ComboAddress& remote, uint16_t id, UeberBackend *B)
+void CommunicatorClass::sendNotification(int sock, const DNSName& domain, const ComboAddress& remote, uint16_t id, UeberBackendB)
 {
   vector<string> meta;
   DNSName tsigkeyname;
@@ -312,35 +309,35 @@ void CommunicatorClass::sendNotification(int sock, const DNSName& domain, const
       trc.d_algoName = tsigalgorithm;
     trc.d_time = time(nullptr);
     trc.d_fudge = 300;
-    trc.d_origID=ntohs(id);
-    trc.d_eRcode=0;
+    trc.d_origID = ntohs(id);
+    trc.d_eRcode = 0;
     if (B64Decode(tsigsecret64, tsigsecret) == -1) {
-      g_log<<Logger::Error<<"Unable to Base-64 decode TSIG key '"<<tsigkeyname<<"' for domain '"<<domain<<"'"<<endl;
+      g_log << Logger::Error << "Unable to Base-64 decode TSIG key '" << tsigkeyname << "' for domain '" << domain << "'" << endl;
       return;
     }
     addTSIG(pw, trc, tsigkeyname, tsigsecret, "", false);
   }
 
-  if(sendto(sock, &packet[0], packet.size(), 0, (struct sockaddr*)(&remote), remote.getSocklen()) < 0) {
-    throw ResolverException("Unable to send notify to "+remote.toStringWithPort()+": "+stringerror());
+  if (sendto(sock, &packet[0], packet.size(), 0, (struct sockaddr*)(&remote), remote.getSocklen()) < 0) {
+    throw ResolverException("Unable to send notify to " + remote.toStringWithPort() + ": " + stringerror());
   }
 }
 
-void CommunicatorClass::drillHole(const DNSName &domain, const string &ip)
+void CommunicatorClass::drillHole(const DNSName& domain, const string& ip)
 {
-  (*d_holes.lock())[pair(domain,ip)]=time(nullptr);
+  (*d_holes.lock())[pair(domain, ip)] = time(nullptr);
 }
 
-bool CommunicatorClass::justNotified(const DNSName &domain, const string &ip)
+bool CommunicatorClass::justNotified(const DNSName& domain, const string& ip)
 {
   auto holes = d_holes.lock();
-  auto it = holes->find(pair(domain,ip));
+  auto it = holes->find(pair(domain, ip));
   if (it == holes->end()) {
     // no hole
     return false;
   }
 
-  if (it->second > time(nullptr)-900) {
+  if (it->second > time(nullptr) - 900) {
     // recent hole
     return true;
   }
@@ -351,19 +348,21 @@ bool CommunicatorClass::justNotified(const DNSName &domain, const string &ip)
 
 void CommunicatorClass::makeNotifySockets()
 {
-  if(pdns::isQueryLocalAddressFamilyEnabled(AF_INET)) {
+  if (pdns::isQueryLocalAddressFamilyEnabled(AF_INET)) {
     d_nsock4 = makeQuerySocket(pdns::getQueryLocalAddress(AF_INET, 0), true, ::arg().mustDo("non-local-bind"));
-  } else {
+  }
+  else {
     d_nsock4 = -1;
   }
-  if(pdns::isQueryLocalAddressFamilyEnabled(AF_INET6)) {
+  if (pdns::isQueryLocalAddressFamilyEnabled(AF_INET6)) {
     d_nsock6 = makeQuerySocket(pdns::getQueryLocalAddress(AF_INET6, 0), true, ::arg().mustDo("non-local-bind"));
-  } else {
+  }
+  else {
     d_nsock6 = -1;
   }
 }
 
-void CommunicatorClass::notify(const DNSName &domain, const string &ip)
+void CommunicatorClass::notify(const DNSName& domain, const string& ip)
 {
   d_nq.add(domain, ip);
 }
similarity index 58%
rename from pdns/slavecommunicator.cc
rename to pdns/auth-secondarycommunicator.cc
index 5029708ee67cc8f52c6003e10200dbbde1b1f23f..9b76a66526381ca93c9de150b3c86fb74ea2f205 100644 (file)
 
 #include "ixfr.hh"
 
-void CommunicatorClass::addSuckRequest(const DNSName &domain, const ComboAddress& master, SuckRequest::RequestPriority priority, bool force)
+void CommunicatorClass::addSuckRequest(const DNSName& domain, const ComboAddress& primary, SuckRequest::RequestPriority priority, bool force)
 {
   auto data = d_data.lock();
   SuckRequest sr;
   sr.domain = domain;
-  sr.master = master;
+  sr.primary = primary;
   sr.force = force;
   sr.priorityAndOrder.first = priority;
   sr.priorityAndOrder.second = data->d_sorthelper++;
-  pair<UniQueue::iterator, bool>  res;
+  pair<UniQueue::iterator, bool> res;
 
   res = data->d_suckdomains.insert(sr);
-  if(res.second) {
+  if (res.second) {
     d_suck_sem.post();
-  } else {
-    data->d_suckdomains.modify(res.first, [priorityAndOrder = sr.priorityAndOrder] (SuckRequest& so) {
+  }
+  else {
+    data->d_suckdomains.modify(res.first, [priorityAndOrder = sr.priorityAndOrder](SuckRequest& so) {
       if (priorityAndOrder.first < so.priorityAndOrder.first) {
         so.priorityAndOrder = priorityAndOrder;
       }
@@ -75,8 +76,8 @@ struct ZoneStatus
 {
   bool isDnssecZone{false};
   bool isPresigned{false};
-  bool isNSEC3 {false};
-  bool optOutFlag {false};
+  bool isNSEC3{false};
+  bool optOutFlag{false};
   NSEC3PARAMRecordContent ns3pr;
 
   bool isNarrow{false};
@@ -151,18 +152,18 @@ static bool catalogDiff(const DomainInfo& di, vector<CatalogInfo>& fromXFR, vect
             di.backend->setOptions(ciXFR.d_zone, ciDB.toJson());
           }
 
-          if (di.masters != ciDB.d_primaries) { // update primaries
+          if (di.primaries != ciDB.d_primaries) { // update primaries
             if (doTransaction && (inTransaction = di.backend->startTransaction(di.zone))) {
               g_log << Logger::Warning << logPrefix << "backend transaction started" << endl;
               doTransaction = false;
             }
 
             vector<string> primaries;
-            for (const auto& primary : di.masters) {
+            for (const auto& primary : di.primaries) {
               primaries.push_back(primary.toStringWithPortExcept(53));
             }
             g_log << Logger::Warning << logPrefix << "update primaries for zone '" << ciXFR.d_zone << "' to '" << boost::join(primaries, ", ") << "'" << endl;
-            di.backend->setMasters(ciXFR.d_zone, di.masters);
+            di.backend->setPrimaries(ciXFR.d_zone, di.primaries);
 
             retrieve.emplace_back(ciXFR);
           }
@@ -194,7 +195,7 @@ static bool catalogDiff(const DomainInfo& di, vector<CatalogInfo>& fromXFR, vect
               doTransaction = false;
             }
 
-            di.backend->setMasters(ciCreate.d_zone, di.masters);
+            di.backend->setPrimaries(ciCreate.d_zone, di.primaries);
             di.backend->setOptions(ciCreate.d_zone, ciCreate.toJson());
             di.backend->setCatalog(ciCreate.d_zone, di.zone);
 
@@ -237,9 +238,9 @@ static bool catalogDiff(const DomainInfo& di, vector<CatalogInfo>& fromXFR, vect
         }
 
         g_log << Logger::Warning << logPrefix << "create zone '" << ciCreate.d_zone << "'" << endl;
-        di.backend->createDomain(ciCreate.d_zone, DomainInfo::Slave, ciCreate.d_primaries, "");
+        di.backend->createDomain(ciCreate.d_zone, DomainInfo::Secondary, ciCreate.d_primaries, "");
 
-        di.backend->setMasters(ciCreate.d_zone, di.masters);
+        di.backend->setPrimaries(ciCreate.d_zone, di.primaries);
         di.backend->setOptions(ciCreate.d_zone, ciCreate.toJson());
         di.backend->setCatalog(ciCreate.d_zone, di.zone);
 
@@ -274,12 +275,12 @@ static bool catalogDiff(const DomainInfo& di, vector<CatalogInfo>& fromXFR, vect
     }
 
     // retrieve new and updated zones with new primaries
-    auto masters = di.masters;
-    if (!masters.empty()) {
+    auto primaries = di.primaries;
+    if (!primaries.empty()) {
       for (auto& ret : retrieve) {
-        shuffle(masters.begin(), masters.end(), pdns::dns_random_engine());
-        const auto& master = masters.front();
-        Communicator.addSuckRequest(ret.d_zone, master, SuckRequest::Notify);
+        shuffle(primaries.begin(), primaries.end(), pdns::dns_random_engine());
+        const auto& primary = primaries.front();
+        Communicator.addSuckRequest(ret.d_zone, primary, SuckRequest::Notify);
       }
     }
 
@@ -423,69 +424,67 @@ static bool catalogProcess(const DomainInfo& di, vector<DNSResourceRecord>& rrs,
 
 void CommunicatorClass::ixfrSuck(const DNSName& domain, const TSIGTriplet& tt, const ComboAddress& laddr, const ComboAddress& remote, ZoneStatus& zs, vector<DNSRecord>* axfr)
 {
-  string logPrefix="IXFR-in zone '"+domain.toLogString()+"', primary '"+remote.toString()+"', ";
+  string logPrefix = "IXFR-in zone '" + domain.toLogString() + "', primary '" + remote.toString() + "', ";
 
   UeberBackend B; // fresh UeberBackend
 
   DomainInfo di;
-  di.backend=nullptr;
+  di.backend = nullptr;
   //  bool transaction=false;
   try {
-    DNSSECKeeper dk (&B); // reuse our UeberBackend copy for DNSSECKeeper
+    DNSSECKeeper dk(&B); // reuse our UeberBackend copy for DNSSECKeeper
 
     bool wrongDomainKind = false;
     // this checks three error conditions, and sets wrongDomainKind if we hit the third & had an error
-    if(!B.getDomainInfo(domain, di) || !di.backend || (wrongDomainKind = true, di.kind != DomainInfo::Slave)) { // di.backend and B are mostly identical
-      if(wrongDomainKind)
-        g_log<<Logger::Warning<<logPrefix<<"can't determine backend, not configured as slave"<<endl;
+    if (!B.getDomainInfo(domain, di) || !di.backend || (wrongDomainKind = true, di.kind != DomainInfo::Secondary)) { // di.backend and B are mostly identical
+      if (wrongDomainKind)
+        g_log << Logger::Warning << logPrefix << "can't determine backend, not configured as secondary" << endl;
       else
-        g_log<<Logger::Warning<<logPrefix<<"can't determine backend"<<endl;
+        g_log << Logger::Warning << logPrefix << "can't determine backend" << endl;
       return;
     }
 
     uint16_t xfrTimeout = ::arg().asNum("axfr-fetch-timeout");
     soatimes st;
     memset(&st, 0, sizeof(st));
-    st.serial=di.serial;
+    st.serial = di.serial;
 
     DNSRecord drsoa;
     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();
+    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;
 
-    for(const auto& d : deltas) {
+    for (const auto& d : deltas) {
       const auto& remove = d.first;
       const auto& add = d.second;
       //      cout<<"Delta sizes: "<<remove.size()<<", "<<add.size()<<endl;
 
-      if(remove.empty()) { // we got passed an AXFR!
+      if (remove.empty()) { // we got passed an AXFR!
         *axfr = add;
         return;
       }
 
-
       // our hammer is 'replaceRRSet(domain_id, qname, qt, vector<DNSResourceRecord>& rrset)
       // which thinks in terms of RRSETs
       // however, IXFR does not, and removes and adds *records* (bummer)
       // this means that we must group updates by {qname,qtype}, retrieve the RRSET, apply
       // the add/remove updates, and replaceRRSet the whole thing.
 
+      map<pair<DNSName, uint16_t>, pair<vector<DNSRecord>, vector<DNSRecord>>> grouped;
 
-      map<pair<DNSName,uint16_t>, pair<vector<DNSRecord>, vector<DNSRecord> > > grouped;
-
-      for(const auto& x: remove)
+      for (const auto& x : remove)
         grouped[{x.d_name, x.d_type}].first.push_back(x);
-      for(const auto& x: add)
+      for (const auto& x : add)
         grouped[{x.d_name, x.d_type}].second.push_back(x);
 
       di.backend->startTransaction(domain, -1);
-      for(const auto& g : grouped) {
+      for (const auto& g : grouped) {
         vector<DNSRecord> rrset;
         {
           DNSZoneRecord zrr;
-          di.backend->lookup(QType(g.first.second), g.first.first+domain, di.id);
-          while(di.backend->get(zrr)) {
+          di.backend->lookup(QType(g.first.second), g.first.first + domain, di.id);
+          while (di.backend->get(zrr)) {
             zrr.dr.d_name.makeUsRelative(domain);
             rrset.push_back(zrr.dr);
           }
@@ -495,45 +494,46 @@ void CommunicatorClass::ixfrSuck(const DNSName& domain, const TSIGTriplet& tt, c
                               [&g](const DNSRecord& dr) {
                                 return count(g.second.first.cbegin(),
                                              g.second.first.cend(), dr);
-                              }), rrset.end());
+                              }),
+                    rrset.end());
         // the DNSRecord== operator compares on name, type, class and lowercase content representation
 
-        for(const auto& x : g.second.second) {
+        for (const auto& x : g.second.second) {
           rrset.push_back(x);
         }
 
         vector<DNSResourceRecord> replacement;
-        for(const auto& dr : rrset) {
+        for (const auto& dr : rrset) {
           auto rr = DNSResourceRecord::fromWire(dr);
           rr.qname += domain;
           rr.domain_id = di.id;
-          if(dr.d_type == QType::SOA) {
+          if (dr.d_type == QType::SOA) {
             //            cout<<"New SOA: "<<x.d_content->getZoneRepresentation()<<endl;
             auto sr = getRR<SOARecordContent>(dr);
-            zs.soa_serial=sr->d_st.serial;
+            zs.soa_serial = sr->d_st.serial;
           }
 
           replacement.push_back(rr);
         }
 
-        di.backend->replaceRRSet(di.id, g.first.first+domain, QType(g.first.second), replacement);
+        di.backend->replaceRRSet(di.id, g.first.first + domain, QType(g.first.second), replacement);
       }
       di.backend->commitTransaction();
     }
   }
-  catch(std::exception& p) {
-    g_log<<Logger::Error<<logPrefix<<"got exception (std::exception): "<<p.what()<<endl;
+  catch (std::exception& p) {
+    g_log << Logger::Error << logPrefix << "got exception (std::exception): " << p.what() << endl;
     throw;
   }
-  catch(PDNSException& p) {
-    g_log<<Logger::Error<<logPrefix<<"got exception (PDNSException): "<<p.reason<<endl;
+  catch (PDNSException& p) {
+    g_log << Logger::Error << logPrefix << "got exception (PDNSException): " << p.reason << endl;
     throw;
   }
 }
 
 static bool processRecordForZS(const DNSName& domain, bool& firstNSEC3, DNSResourceRecord& rr, ZoneStatus& zs)
 {
-  switch(rr.qtype.getCode()) {
+  switch (rr.qtype.getCode()) {
   case QType::NSEC3PARAM:
     zs.ns3pr = NSEC3PARAMRecordContent(rr.content);
     zs.isDnssecZone = zs.isNSEC3 = true;
@@ -544,10 +544,11 @@ static bool processRecordForZS(const DNSName& domain, bool& firstNSEC3, DNSResou
     if (firstNSEC3) {
       zs.isDnssecZone = zs.isPresigned = true;
       firstNSEC3 = false;
-    } else if (zs.optOutFlag != (ns3rc.d_flags & 1))
+    }
+    else if (zs.optOutFlag != (ns3rc.d_flags & 1))
       throw PDNSException("Zones with a mixture of Opt-Out NSEC3 RRs and non-Opt-Out NSEC3 RRs are not supported.");
     zs.optOutFlag = ns3rc.d_flags & 1;
-    if (ns3rc.isSet(QType::NS) && !(rr.qname==domain)) {
+    if (ns3rc.isSet(QType::NS) && !(rr.qname == domain)) {
       DNSName hashPart = rr.qname.makeRelative(domain);
       zs.secured.insert(hashPart);
     }
@@ -559,19 +560,19 @@ static bool processRecordForZS(const DNSName& domain, bool& firstNSEC3, DNSResou
     return false;
 
   case QType::NS:
-    if(rr.qname!=domain)
+    if (rr.qname != domain)
       zs.nsset.insert(rr.qname);
     break;
   }
 
   zs.qnames.insert(rr.qname);
 
-  rr.domain_id=zs.domain_id;
+  rr.domain_id = zs.domain_id;
   return true;
 }
 
 /* So this code does a number of things.
-   1) It will AXFR a domain from a master
+   1) It will AXFR a domain from a primary
       The code can retrieve the current serial number in the database itself.
       It may attempt an IXFR
    2) It will filter the zone through a lua *filter* script
@@ -581,63 +582,61 @@ static bool processRecordForZS(const DNSName& domain, bool& firstNSEC3, DNSResou
    5) It updates the Empty Non Terminals
 */
 
-static vector<DNSResourceRecord> doAxfr(const ComboAddress& raddr, const DNSName& domain, const TSIGTriplet& tt, const ComboAddress& laddr,  unique_ptr<AuthLua4>& pdl, ZoneStatus& zs)
+static vector<DNSResourceRecord> doAxfr(const ComboAddress& raddr, const DNSName& domain, const TSIGTriplet& tt, const ComboAddress& laddr, unique_ptr<AuthLua4>& pdl, ZoneStatus& zs)
 {
-  uint16_t axfr_timeout=::arg().asNum("axfr-fetch-timeout");
+  uint16_t axfr_timeout = ::arg().asNum("axfr-fetch-timeout");
   vector<DNSResourceRecord> rrs;
-  AXFRRetriever retriever(raddr, domain, tt, (laddr.sin4.sin_family == 0) ? nullptr : &laddr, ((size_t) ::arg().asNum("xfr-max-received-mbytes")) * 1024 * 1024, axfr_timeout);
+  AXFRRetriever retriever(raddr, domain, tt, (laddr.sin4.sin_family == 0) ? nullptr : &laddr, ((size_t)::arg().asNum("xfr-max-received-mbytes")) * 1024 * 1024, axfr_timeout);
   Resolver::res_t recs;
-  bool first=true;
+  bool first = true;
   bool firstNSEC3{true};
-  bool soa_received {false};
-  string logPrefix="AXFR-in zone '"+domain.toLogString()+"', primary '"+raddr.toString()+"', ";
-  while(retriever.getChunk(recs, nullptr, axfr_timeout)) {
-    if(first) {
-      g_log<<Logger::Notice<<logPrefix<<"retrieval started"<<endl;
-      first=false;
+  bool soa_received{false};
+  string logPrefix = "AXFR-in zone '" + domain.toLogString() + "', primary '" + raddr.toString() + "', ";
+  while (retriever.getChunk(recs, nullptr, axfr_timeout)) {
+    if (first) {
+      g_log << Logger::Notice << logPrefix << "retrieval started" << endl;
+      first = false;
     }
 
-    for(auto & rec : recs) {
+    for (auto& rec : recs) {
       rec.qname.makeUsLowerCase();
-      if(rec.qtype.getCode() == QType::OPT || rec.qtype.getCode() == QType::TSIG) // ignore EDNS0 & TSIG
+      if (rec.qtype.getCode() == QType::OPT || rec.qtype.getCode() == QType::TSIG) // ignore EDNS0 & TSIG
         continue;
 
-      if(!rec.qname.isPartOf(domain)) {
-        g_log<<Logger::Warning<<logPrefix<<"primary tried to sneak in out-of-zone data '"<<rec.qname<<"'|"<<rec.qtype.toString()<<", ignoring"<<endl;
+      if (!rec.qname.isPartOf(domain)) {
+        g_log << Logger::Warning << logPrefix << "primary tried to sneak in out-of-zone data '" << rec.qname << "'|" << rec.qtype.toString() << ", ignoring" << endl;
         continue;
       }
 
       vector<DNSResourceRecord> out;
-      if(!pdl || !pdl->axfrfilter(raddr, domain, rec, out)) {
+      if (!pdl || !pdl->axfrfilter(raddr, domain, rec, out)) {
         out.push_back(rec); // if axfrfilter didn't do anything, we put our record in 'out' ourselves
       }
 
-      for(auto& rr :  out) {
-        if(!rr.qname.isPartOf(domain)) {
-          g_log<<Logger::Error<<logPrefix<<"axfrfilter() filter tried to sneak in out-of-zone data '"<<rr.qname<<"'|"<<rr.qtype.toString()<<", ignoring"<<endl;
+      for (auto& rr : out) {
+        if (!rr.qname.isPartOf(domain)) {
+          g_log << Logger::Error << logPrefix << "axfrfilter() filter tried to sneak in out-of-zone data '" << rr.qname << "'|" << rr.qtype.toString() << ", ignoring" << endl;
           continue;
         }
-        if(!processRecordForZS(domain, firstNSEC3, rr, zs))
+        if (!processRecordForZS(domain, firstNSEC3, rr, zs))
           continue;
-        if(rr.qtype.getCode() == QType::SOA) {
-          if(soa_received)
-            continue; //skip the last SOA
+        if (rr.qtype.getCode() == QType::SOA) {
+          if (soa_received)
+            continue; // skip the last SOA
           SOAData sd;
-          fillSOAData(rr.content,sd);
+          fillSOAData(rr.content, sd);
           zs.soa_serial = sd.serial;
           soa_received = true;
         }
 
         rrs.push_back(rr);
-
       }
     }
   }
   return rrs;
 }
 
-
-void CommunicatorClass::suck(const DNSName &domain, const ComboAddress& remote, bool force)
+void CommunicatorClass::suck(const DNSName& domain, const ComboAddress& remote, bool force)
 {
   {
     auto data = d_data.lock();
@@ -648,62 +647,62 @@ void CommunicatorClass::suck(const DNSName &domain, const ComboAddress& remote,
   }
   RemoveSentinel rs(domain, this); // this removes us from d_inprogress when we go out of scope
 
-  string logPrefix="XFR-in zone: '"+domain.toLogString()+"', primary: '"+remote.toString()+"', ";
+  string logPrefix = "XFR-in zone: '" + domain.toLogString() + "', primary: '" + remote.toString() + "', ";
 
-  g_log<<Logger::Notice<<logPrefix<<"initiating transfer"<<endl;
+  g_log << Logger::Notice << logPrefix << "initiating transfer" << endl;
   UeberBackend B; // fresh UeberBackend
 
   DomainInfo di;
-  di.backend=nullptr;
-  bool transaction=false;
+  di.backend = nullptr;
+  bool transaction = false;
   try {
-    DNSSECKeeper dk (&B); // reuse our UeberBackend copy for DNSSECKeeper
+    DNSSECKeeper dk(&B); // reuse our UeberBackend copy for DNSSECKeeper
     bool wrongDomainKind = false;
     // this checks three error conditions & sets wrongDomainKind if we hit the third
     if (!B.getDomainInfo(domain, di) || !di.backend || (wrongDomainKind = true, !force && !di.isSecondaryType())) { // di.backend and B are mostly identical
-      if(wrongDomainKind)
+      if (wrongDomainKind)
         g_log << Logger::Warning << logPrefix << "can't determine backend, not configured as secondary" << endl;
       else
-        g_log<<Logger::Warning<<logPrefix<<"can't determine backend"<<endl;
+        g_log << Logger::Warning << logPrefix << "can't determine backend" << endl;
       return;
     }
     ZoneStatus zs;
-    zs.domain_id=di.id;
+    zs.domain_id = di.id;
 
     TSIGTriplet tt;
-    if(dk.getTSIGForAccess(domain, remote, &tt.name)) {
+    if (dk.getTSIGForAccess(domain, remote, &tt.name)) {
       string tsigsecret64;
       if (B.getTSIGKey(tt.name, tt.algo, tsigsecret64)) {
-        if(B64Decode(tsigsecret64, tt.secret)) {
-          g_log<<Logger::Error<<logPrefix<<"unable to Base-64 decode TSIG key '"<<tt.name<<"' or zone not found"<<endl;
+        if (B64Decode(tsigsecret64, tt.secret)) {
+          g_log << Logger::Error << logPrefix << "unable to Base-64 decode TSIG key '" << tt.name << "' or zone not found" << endl;
           return;
         }
       }
       else {
-        g_log<<Logger::Warning<<logPrefix<<"TSIG key '"<<tt.name<<"' for zone not found"<<endl;
+        g_log << Logger::Warning << logPrefix << "TSIG key '" << tt.name << "' for zone not found" << endl;
         return;
       }
     }
 
-
     unique_ptr<AuthLua4> pdl{nullptr};
     vector<string> scripts;
-    string script=::arg()["lua-axfr-script"];
-    if(B.getDomainMetadata(domain, "LUA-AXFR-SCRIPT", scripts) && !scripts.empty()) {
+    string script = ::arg()["lua-axfr-script"];
+    if (B.getDomainMetadata(domain, "LUA-AXFR-SCRIPT", scripts) && !scripts.empty()) {
       if (pdns_iequals(scripts[0], "NONE")) {
         script.clear();
-      } else {
-        script=scripts[0];
+      }
+      else {
+        script = scripts[0];
       }
     }
-    if(!script.empty()){
+    if (!script.empty()) {
       try {
         pdl = make_unique<AuthLua4>();
         pdl->loadFile(script);
-        g_log<<Logger::Info<<logPrefix<<"loaded Lua script '"<<script<<"'"<<endl;
+        g_log << Logger::Info << logPrefix << "loaded Lua script '" << script << "'" << endl;
       }
-      catch(std::exception& e) {
-        g_log<<Logger::Error<<logPrefix<<"failed to load Lua script '"<<script<<"': "<<e.what()<<endl;
+      catch (std::exception& e) {
+        g_log << Logger::Error << logPrefix << "failed to load Lua script '" << script << "': " << e.what() << endl;
         return;
       }
     }
@@ -711,20 +710,20 @@ void CommunicatorClass::suck(const DNSName &domain, const ComboAddress& remote,
     vector<string> localaddr;
     ComboAddress laddr;
 
-    if(B.getDomainMetadata(domain, "AXFR-SOURCE", localaddr) && !localaddr.empty()) {
+    if (B.getDomainMetadata(domain, "AXFR-SOURCE", localaddr) && !localaddr.empty()) {
       try {
         laddr = ComboAddress(localaddr[0]);
-        g_log<<Logger::Info<<logPrefix<<"xfr source set to "<<localaddr[0]<<endl;
+        g_log << Logger::Info << logPrefix << "xfr source set to " << localaddr[0] << endl;
       }
-      catch(std::exception& e) {
-        g_log<<Logger::Error<<logPrefix<<"failed to set xfr source '"<<localaddr[0]<<"': "<<e.what()<<endl;
+      catch (std::exception& e) {
+        g_log << Logger::Error << logPrefix << "failed to set xfr source '" << localaddr[0] << "': " << e.what() << endl;
         return;
       }
-    } else {
+    }
+    else {
       if (!pdns::isQueryLocalAddressFamilyEnabled(remote.sin4.sin_family)) {
         bool isV6 = remote.sin4.sin_family == AF_INET6;
-        g_log<<Logger::Warning<<logPrefix<<"unable to xfr, address family (IPv"<< (isV6 ? "6" : "4") <<
-          " is not enabled for outgoing traffic (query-local-address)"<<endl;
+        g_log << Logger::Warning << logPrefix << "unable to xfr, address family (IPv" << (isV6 ? "6" : "4") << " is not enabled for outgoing traffic (query-local-address)" << endl;
         return;
       }
       laddr = pdns::getQueryLocalAddress(remote.sin4.sin_family, 0);
@@ -734,12 +733,11 @@ void CommunicatorClass::suck(const DNSName &domain, const ComboAddress& remote,
     bool hadPresigned = false;
     bool hadNSEC3 = false;
     NSEC3PARAMRecordContent hadNs3pr;
-    bool hadNarrow=false;
-
+    bool hadNarrow = false;
 
     vector<DNSResourceRecord> rrs;
     if (dk.isSecuredZone(domain, false)) {
-      hadDnssecZone=true;
+      hadDnssecZone = true;
       hadPresigned = dk.isPresigned(domain, false);
       if (dk.getNSEC3PARAM(domain, &zs.ns3pr, &zs.isNarrow, false)) {
         hadNSEC3 = true;
@@ -747,26 +745,26 @@ void CommunicatorClass::suck(const DNSName &domain, const ComboAddress& remote,
         hadNarrow = zs.isNarrow;
       }
     }
-    else if(di.serial) {
+    else if (di.serial) {
       vector<string> meta;
       B.getDomainMetadata(domain, "IXFR", meta);
-      if(!meta.empty() && meta[0]=="1") {
+      if (!meta.empty() && meta[0] == "1") {
         logPrefix = "I" + logPrefix; // XFR -> IXFR
         vector<DNSRecord> axfr;
-        g_log<<Logger::Notice<<logPrefix<<"starting IXFR"<<endl;
+        g_log << Logger::Notice << logPrefix << "starting IXFR" << endl;
         ixfrSuck(domain, tt, laddr, remote, zs, &axfr);
-        if(!axfr.empty()) {
-          g_log<<Logger::Notice<<logPrefix<<"IXFR turned into an AXFR"<<endl;
-          logPrefix[0]='A'; // IXFR -> AXFR
-          bool firstNSEC3=true;
+        if (!axfr.empty()) {
+          g_log << Logger::Notice << logPrefix << "IXFR turned into an AXFR" << endl;
+          logPrefix[0] = 'A'; // IXFR -> AXFR
+          bool firstNSEC3 = true;
           rrs.reserve(axfr.size());
-          for(const auto& dr : axfr) {
+          for (const auto& dr : axfr) {
             auto rr = DNSResourceRecord::fromWire(dr);
             (rr.qname += domain).makeUsLowerCase();
             rr.domain_id = zs.domain_id;
-            if(!processRecordForZS(domain, firstNSEC3, rr, zs))
+            if (!processRecordForZS(domain, firstNSEC3, rr, zs))
               continue;
-            if(dr.d_type == QType::SOA) {
+            if (dr.d_type == QType::SOA) {
               auto sd = getRR<SOARecordContent>(dr);
               zs.soa_serial = sd->d_st.serial;
             }
@@ -774,18 +772,18 @@ void CommunicatorClass::suck(const DNSName &domain, const ComboAddress& remote,
           }
         }
         else {
-          g_log<<Logger::Warning<<logPrefix<<"got "<<zs.numDeltas<<" delta"<<addS(zs.numDeltas)<<", zone committed with serial "<<zs.soa_serial<<endl;
-          purgeAuthCaches(domain.toString()+"$");
+          g_log << Logger::Warning << logPrefix << "got " << zs.numDeltas << " delta" << addS(zs.numDeltas) << ", zone committed with serial " << zs.soa_serial << endl;
+          purgeAuthCaches(domain.toString() + "$");
           return;
         }
       }
     }
 
-    if(rrs.empty()) {
-      g_log<<Logger::Notice<<logPrefix<<"starting AXFR"<<endl;
+    if (rrs.empty()) {
+      g_log << Logger::Notice << logPrefix << "starting AXFR" << endl;
       rrs = doAxfr(remote, domain, tt, laddr, pdl, zs);
       logPrefix = "A" + logPrefix; // XFR -> AXFR
-      g_log<<Logger::Notice<<logPrefix<<"retrieval finished"<<endl;
+      g_log << Logger::Notice << logPrefix << "retrieval finished" << endl;
     }
 
     if (di.kind == DomainInfo::Consumer) {
@@ -794,13 +792,13 @@ void CommunicatorClass::suck(const DNSName &domain, const ComboAddress& remote,
       }
     }
 
-    if(zs.isNSEC3) {
+    if (zs.isNSEC3) {
       zs.ns3pr.d_flags = zs.optOutFlag ? 1 : 0;
     }
 
-    if(!zs.isPresigned) {
+    if (!zs.isPresigned) {
       DNSSECKeeper::keyset_t keys = dk.getKeys(domain, false);
-      if(!keys.empty()) {
+      if (!keys.empty()) {
         zs.isDnssecZone = true;
         zs.isNSEC3 = hadNSEC3;
         zs.ns3pr = hadNs3pr;
@@ -809,18 +807,17 @@ void CommunicatorClass::suck(const DNSName &domain, const ComboAddress& remote,
       }
     }
 
-    if(zs.isDnssecZone) {
-      if(!zs.isNSEC3)
-        g_log<<Logger::Debug<<logPrefix<<"adding NSEC ordering information"<<endl;
-      else if(!zs.isNarrow)
-        g_log<<Logger::Debug<<logPrefix<<"adding NSEC3 hashed ordering information"<<endl;
+    if (zs.isDnssecZone) {
+      if (!zs.isNSEC3)
+        g_log << Logger::Debug << logPrefix << "adding NSEC ordering information" << endl;
+      else if (!zs.isNarrow)
+        g_log << Logger::Debug << logPrefix << "adding NSEC3 hashed ordering information" << endl;
       else
-        g_log<<Logger::Debug<<logPrefix<<"zone is narrow, only setting 'auth' fields"<<endl;
+        g_log << Logger::Debug << logPrefix << "zone is narrow, only setting 'auth' fields" << endl;
     }
 
-
-    transaction=di.backend->startTransaction(domain, zs.domain_id);
-    g_log<<Logger::Info<<logPrefix<<"storage transaction started"<<endl;
+    transaction = di.backend->startTransaction(domain, zs.domain_id);
+    g_log << Logger::Info << logPrefix << "storage transaction started" << endl;
 
     // update the presigned flag and NSEC3PARAM
     if (zs.isDnssecZone) {
@@ -828,25 +825,24 @@ void CommunicatorClass::suck(const DNSName &domain, const ComboAddress& remote,
       if (zs.isPresigned && !hadPresigned) {
         // zone is now presigned
         dk.setPresigned(domain);
-      } else if (hadPresigned && !zs.isPresigned) {
+      }
+      else if (hadPresigned && !zs.isPresigned) {
         // zone is no longer presigned
         dk.unsetPresigned(domain);
       }
       // update NSEC3PARAM
       if (zs.isNSEC3) {
         // zone is NSEC3, only update if there was a change
-        if (!hadNSEC3 || (hadNarrow  != zs.isNarrow) ||
-            (zs.ns3pr.d_algorithm != hadNs3pr.d_algorithm) ||
-            (zs.ns3pr.d_flags != hadNs3pr.d_flags) ||
-            (zs.ns3pr.d_iterations != hadNs3pr.d_iterations) ||
-            (zs.ns3pr.d_salt != hadNs3pr.d_salt)) {
+        if (!hadNSEC3 || (hadNarrow != zs.isNarrow) || (zs.ns3pr.d_algorithm != hadNs3pr.d_algorithm) || (zs.ns3pr.d_flags != hadNs3pr.d_flags) || (zs.ns3pr.d_iterations != hadNs3pr.d_iterations) || (zs.ns3pr.d_salt != hadNs3pr.d_salt)) {
           dk.setNSEC3PARAM(domain, zs.ns3pr, zs.isNarrow);
         }
-      } else if (hadNSEC3 ) {
-         // zone is no longer NSEC3
-         dk.unsetNSEC3PARAM(domain);
       }
-    } else if (hadDnssecZone) {
+      else if (hadNSEC3) {
+        // zone is no longer NSEC3
+        dk.unsetNSEC3PARAM(domain);
+      }
+    }
+    else if (hadDnssecZone) {
       // zone is no longer signed
       if (hadPresigned) {
         // remove presigned
@@ -858,165 +854,171 @@ void CommunicatorClass::suck(const DNSName &domain, const ComboAddress& remote,
       }
     }
 
-    bool doent=true;
+    bool doent = true;
     uint32_t maxent = ::arg().asNum("max-ent-entries");
     DNSName shorter, ordername;
     set<DNSName> rrterm;
-    map<DNSName,bool> nonterm;
-
+    map<DNSName, bool> nonterm;
 
-    for(DNSResourceRecord& rr :  rrs) {
-      if(!zs.isPresigned) {
+    for (DNSResourceRecord& rr : rrs) {
+      if (!zs.isPresigned) {
         if (rr.qtype.getCode() == QType::RRSIG)
           continue;
-        if(zs.isDnssecZone && rr.qtype.getCode() == QType::DNSKEY && !::arg().mustDo("direct-dnskey"))
+        if (zs.isDnssecZone && rr.qtype.getCode() == QType::DNSKEY && !::arg().mustDo("direct-dnskey"))
           continue;
       }
 
       // Figure out auth and ents
-      rr.auth=true;
-      shorter=rr.qname;
+      rr.auth = true;
+      shorter = rr.qname;
       rrterm.clear();
       do {
-        if(doent) {
+        if (doent) {
           if (!zs.qnames.count(shorter))
             rrterm.insert(shorter);
         }
-        if(zs.nsset.count(shorter) && rr.qtype.getCode() != QType::DS)
-          rr.auth=false;
+        if (zs.nsset.count(shorter) && rr.qtype.getCode() != QType::DS)
+          rr.auth = false;
 
-        if (shorter==domain) // stop at apex
+        if (shorter == domain) // stop at apex
           break;
-      }while(shorter.chopOff());
+      } while (shorter.chopOff());
 
       // Insert ents
-      if(doent && !rrterm.empty()) {
+      if (doent && !rrterm.empty()) {
         bool auth;
         if (!rr.auth && rr.qtype.getCode() == QType::NS) {
           if (zs.isNSEC3)
-            ordername=DNSName(toBase32Hex(hashQNameWithSalt(zs.ns3pr, rr.qname)));
-          auth=(!zs.isNSEC3 || !zs.optOutFlag || zs.secured.count(ordername));
-        } else
-          auth=rr.auth;
+            ordername = DNSName(toBase32Hex(hashQNameWithSalt(zs.ns3pr, rr.qname)));
+          auth = (!zs.isNSEC3 || !zs.optOutFlag || zs.secured.count(ordername));
+        }
+        else
+          auth = rr.auth;
 
-        for(const auto &nt: rrterm){
+        for (const auto& nt : rrterm) {
           if (!nonterm.count(nt))
-              nonterm.insert(pair<DNSName, bool>(nt, auth));
-            else if (auth)
-              nonterm[nt]=true;
+            nonterm.insert(pair<DNSName, bool>(nt, auth));
+          else if (auth)
+            nonterm[nt] = true;
         }
 
-        if(nonterm.size() > maxent) {
-          g_log<<Logger::Warning<<logPrefix<<"zone has too many empty non terminals"<<endl;
+        if (nonterm.size() > maxent) {
+          g_log << Logger::Warning << logPrefix << "zone has too many empty non terminals" << endl;
           nonterm.clear();
-          doent=false;
+          doent = false;
         }
       }
 
       // RRSIG is always auth, even inside a delegation
       if (rr.qtype.getCode() == QType::RRSIG)
-        rr.auth=true;
+        rr.auth = true;
 
       // Add ordername and insert record
       if (zs.isDnssecZone && rr.qtype.getCode() != QType::RRSIG) {
         if (zs.isNSEC3) {
           // NSEC3
-          ordername=DNSName(toBase32Hex(hashQNameWithSalt(zs.ns3pr, rr.qname)));
-          if(!zs.isNarrow && (rr.auth || (rr.qtype.getCode() == QType::NS && (!zs.optOutFlag || zs.secured.count(ordername))))) {
+          ordername = DNSName(toBase32Hex(hashQNameWithSalt(zs.ns3pr, rr.qname)));
+          if (!zs.isNarrow && (rr.auth || (rr.qtype.getCode() == QType::NS && (!zs.optOutFlag || zs.secured.count(ordername))))) {
             di.backend->feedRecord(rr, ordername, true);
-          } else
+          }
+          else
             di.backend->feedRecord(rr, DNSName());
-        } else {
+        }
+        else {
           // NSEC
           if (rr.auth || rr.qtype.getCode() == QType::NS) {
-            ordername=rr.qname.makeRelative(domain);
+            ordername = rr.qname.makeRelative(domain);
             di.backend->feedRecord(rr, ordername);
-          } else
+          }
+          else
             di.backend->feedRecord(rr, DNSName());
         }
-      } else
+      }
+      else
         di.backend->feedRecord(rr, DNSName());
     }
 
     // Insert empty non-terminals
-    if(doent && !nonterm.empty()) {
+    if (doent && !nonterm.empty()) {
       if (zs.isNSEC3) {
         di.backend->feedEnts3(zs.domain_id, domain, nonterm, zs.ns3pr, zs.isNarrow);
-      } else
+      }
+      else
         di.backend->feedEnts(zs.domain_id, nonterm);
     }
 
     di.backend->commitTransaction();
     transaction = false;
     di.backend->setFresh(zs.domain_id);
-    purgeAuthCaches(domain.toString()+"$");
+    purgeAuthCaches(domain.toString() + "$");
 
-    g_log<<Logger::Warning<<logPrefix<<"zone committed with serial "<<zs.soa_serial<<endl;
+    g_log << Logger::Warning << logPrefix << "zone committed with serial " << zs.soa_serial << endl;
 
-    // Send slave re-notifications
+    // Send secondary re-notifications
     bool doNotify;
     vector<string> meta;
-    if(B.getDomainMetadata(domain, "SLAVE-RENOTIFY", meta ) && !meta.empty()) {
-      doNotify=(meta.front() == "1");
-    } else {
-      doNotify=(::arg().mustDo("slave-renotify"));
+    if (B.getDomainMetadata(domain, "SLAVE-RENOTIFY", meta) && !meta.empty()) {
+      doNotify = (meta.front() == "1");
+    }
+    else {
+      doNotify = (::arg().mustDo("secondary-do-renotify"));
     }
-    if(doNotify) {
+    if (doNotify) {
       notifyDomain(domain, &B);
     }
-
   }
-  catch(DBException &re) {
-    g_log<<Logger::Error<<logPrefix<<"unable to feed record: "<<re.reason<<endl;
-    if(di.backend && transaction) {
-      g_log<<Logger::Info<<logPrefix<<"aborting possible open transaction"<<endl;
+  catch (DBException& re) {
+    g_log << Logger::Error << logPrefix << "unable to feed record: " << re.reason << endl;
+    if (di.backend && transaction) {
+      g_log << Logger::Info << logPrefix << "aborting possible open transaction" << endl;
       di.backend->abortTransaction();
     }
   }
-  catch(const MOADNSException &mde) {
-    g_log<<Logger::Error<<logPrefix<<"unable to parse record (MOADNSException): "<<mde.what()<<endl;
-    if(di.backend && transaction) {
-      g_log<<Logger::Info<<logPrefix<<"aborting possible open transaction"<<endl;
+  catch (const MOADNSException& mde) {
+    g_log << Logger::Error << logPrefix << "unable to parse record (MOADNSException): " << mde.what() << endl;
+    if (di.backend && transaction) {
+      g_log << Logger::Info << logPrefix << "aborting possible open transaction" << endl;
       di.backend->abortTransaction();
     }
   }
-  catch(std::exception &re) {
-    g_log<<Logger::Error<<logPrefix<<"unable to xfr zone (std::exception): "<<re.what()<<endl;
-    if(di.backend && transaction) {
-      g_log<<Logger::Info<<logPrefix<<"aborting possible open transaction"<<endl;
+  catch (std::exception& re) {
+    g_log << Logger::Error << logPrefix << "unable to xfr zone (std::exception): " << re.what() << endl;
+    if (di.backend && transaction) {
+      g_log << Logger::Info << logPrefix << "aborting possible open transaction" << endl;
       di.backend->abortTransaction();
     }
   }
-  catch(ResolverException &re) {
+  catch (ResolverException& re) {
     {
       auto data = d_data.lock();
-      // The AXFR probably failed due to a problem on the master server. If SOA-checks against this master
+      // The AXFR probably failed due to a problem on the primary server. If SOA-checks against this primary
       // still succeed, we would constantly try to AXFR the zone. To avoid this, we add the zone to the list of
-      // failed slave-checks. This will suspend slave-checks (and subsequent AXFR) for this zone for some time.
+      // failed secondary-checks. This will suspend secondary-checks (and subsequent AXFR) for this zone for some time.
       uint64_t newCount = 1;
       time_t now = time(nullptr);
-      const auto failedEntry = data->d_failedSlaveRefresh.find(domain);
-      if (failedEntry != data->d_failedSlaveRefresh.end()) {
-        newCount = data->d_failedSlaveRefresh[domain].first + 1;
+      const auto failedEntry = data->d_failedSecondaryRefresh.find(domain);
+      if (failedEntry != data->d_failedSecondaryRefresh.end()) {
+        newCount = data->d_failedSecondaryRefresh[domain].first + 1;
       }
       time_t nextCheck = now + std::min(newCount * d_tickinterval, (uint64_t)::arg().asNum("default-ttl"));
-      data->d_failedSlaveRefresh[domain] = {newCount, nextCheck};
-      g_log<<Logger::Warning<<logPrefix<<"unable to xfr zone (ResolverException): "<<re.reason<<" (This was attempt number "<<newCount<<". Excluding zone from slave-checks until "<<nextCheck<<")"<<endl;
+      data->d_failedSecondaryRefresh[domain] = {newCount, nextCheck};
+      g_log << Logger::Warning << logPrefix << "unable to xfr zone (ResolverException): " << re.reason << " (This was attempt number " << newCount << ". Excluding zone from secondary-checks until " << nextCheck << ")" << endl;
     }
-    if(di.backend && transaction) {
-      g_log<<Logger::Info<<"aborting possible open transaction"<<endl;
+    if (di.backend && transaction) {
+      g_log << Logger::Info << "aborting possible open transaction" << endl;
       di.backend->abortTransaction();
     }
   }
-  catch(PDNSException &ae) {
-    g_log<<Logger::Error<<logPrefix<<"unable to xfr zone (PDNSException): "<<ae.reason<<endl;
-    if(di.backend && transaction) {
-      g_log<<Logger::Info<<logPrefix<<"aborting possible open transaction"<<endl;
+  catch (PDNSException& ae) {
+    g_log << Logger::Error << logPrefix << "unable to xfr zone (PDNSException): " << ae.reason << endl;
+    if (di.backend && transaction) {
+      g_log << Logger::Info << logPrefix << "aborting possible open transaction" << endl;
       di.backend->abortTransaction();
     }
   }
 }
-namespace {
+namespace
+{
 struct DomainNotificationInfo
 {
   DomainInfo di;
@@ -1027,12 +1029,12 @@ struct DomainNotificationInfo
 };
 }
 
-
-struct SlaveSenderReceiver
+struct SecondarySenderReceiver
 {
   typedef std::tuple<DNSName, ComboAddress, uint16_t> Identifier;
 
-  struct Answer {
+  struct Answer
+  {
     uint32_t theirSerial;
     uint32_t theirInception;
     uint32_t theirExpire;
@@ -1040,7 +1042,7 @@ struct SlaveSenderReceiver
 
   map<uint32_t, Answer> d_freshness;
 
-  SlaveSenderReceiver()
+  SecondarySenderReceiver()
   {
   }
 
@@ -1050,20 +1052,19 @@ struct SlaveSenderReceiver
 
   Identifier send(DomainNotificationInfo& dni)
   {
-    shuffle(dni.di.masters.begin(), dni.di.masters.end(), pdns::dns_random_engine());
+    shuffle(dni.di.primaries.begin(), dni.di.primaries.end(), pdns::dns_random_engine());
     try {
       return {dni.di.zone,
-                             *dni.di.masters.begin(),
-                             d_resolver.sendResolve(*dni.di.masters.begin(),
-                                                    dni.localaddr,
-                                                    dni.di.zone,
-                                                    QType::SOA,
-                                                    nullptr,
-                                                    dni.dnssecOk, dni.tsigkeyname, dni.tsigalgname, dni.tsigsecret)
-      };
+              *dni.di.primaries.begin(),
+              d_resolver.sendResolve(*dni.di.primaries.begin(),
+                                     dni.localaddr,
+                                     dni.di.zone,
+                                     QType::SOA,
+                                     nullptr,
+                                     dni.dnssecOk, dni.tsigkeyname, dni.tsigalgname, dni.tsigsecret)};
     }
-    catch(PDNSException& e) {
-      throw runtime_error("While attempting to query freshness of '"+dni.di.zone.toLogString()+"': "+e.reason);
+    catch (PDNSException& e) {
+      throw runtime_error("While attempting to query freshness of '" + dni.di.zone.toLogString() + "': " + e.reason);
     }
   }
 
@@ -1074,25 +1075,25 @@ struct SlaveSenderReceiver
 
   void deliverAnswer(const DomainNotificationInfo& dni, const Answer& a, unsigned int /* usec */)
   {
-    d_freshness[dni.di.id]=a;
+    d_freshness[dni.di.id] = a;
   }
 
   Resolver d_resolver;
 };
 
-void CommunicatorClass::addSlaveCheckRequest(const DomainInfo& di, const ComboAddress& remote)
+void CommunicatorClass::addSecondaryCheckRequest(const DomainInfo& di, const ComboAddress& remote)
 {
   auto data = d_data.lock();
   DomainInfo ours = di;
   ours.backend = nullptr;
 
   // When adding a check, if the remote addr from which notification was
-  // received is a master, clear all other masters so we can be sure the
+  // received is a primary, clear all other primaries so we can be sure the
   // query goes to that one.
-  for (const auto& master : di.masters) {
-    if (ComboAddress::addressOnlyEqual()(remote, master)) {
-      ours.masters.clear();
-      ours.masters.push_back(master);
+  for (const auto& primary : di.primaries) {
+    if (ComboAddress::addressOnlyEqual()(remote, primary)) {
+      ours.primaries.clear();
+      ours.primaries.push_back(primary);
       break;
     }
   }
@@ -1101,21 +1102,22 @@ void CommunicatorClass::addSlaveCheckRequest(const DomainInfo& di, const ComboAd
   d_any_sem.post(); // kick the loop!
 }
 
-void CommunicatorClass::addTrySuperMasterRequest(const DNSPacket& p)
+void CommunicatorClass::addTryAutoPrimaryRequest(const DNSPacket& p)
 {
   const DNSPacket& ours = p;
   auto data = d_data.lock();
-  if (data->d_potentialsupermasters.insert(ours).second) {
+  if (data->d_potentialautoprimaries.insert(ours).second) {
     d_any_sem.post(); // kick the loop!
   }
 }
 
-void CommunicatorClass::slaveRefresh(PacketHandler *P)
+void CommunicatorClass::secondaryRefresh(PacketHandler* P)
 {
-  // not unless we are slave
-  if (!::arg().mustDo("secondary")) return;
+  // not unless we are secondary
+  if (!::arg().mustDo("secondary"))
+    return;
 
-  UeberBackend *B=P->getBackend();
+  UeberBackend* B = P->getBackend();
   vector<DomainInfo> rdomains;
   vector<DomainNotificationInfo> sdomains;
   set<DNSPacket, Data::cmp> trysuperdomains;
@@ -1123,66 +1125,67 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
     auto data = d_data.lock();
     set<DomainInfo> requeue;
     rdomains.reserve(data->d_tocheck.size());
-    for (const auto& di: data->d_tocheck) {
+    for (const auto& di : data->d_tocheck) {
       if (data->d_inprogress.count(di.zone)) {
-        g_log<<Logger::Debug<<"Got NOTIFY for "<<di.zone<<" while AXFR in progress, requeueing SOA check"<<endl;
+        g_log << Logger::Debug << "Got NOTIFY for " << di.zone << " while AXFR in progress, requeueing SOA check" << endl;
         requeue.insert(di);
       }
       else {
-        // We received a NOTIFY for a zone. This means at least one of the zone's master server is working.
-        // Therefore we delete the zone from the list of failed slave-checks to allow immediate checking.
-        const auto wasFailedDomain = data->d_failedSlaveRefresh.find(di.zone);
-        if (wasFailedDomain != data->d_failedSlaveRefresh.end()) {
-          g_log<<Logger::Debug<<"Got NOTIFY for "<<di.zone<<", removing zone from list of failed slave-checks and going to check SOA serial"<<endl;
-          data->d_failedSlaveRefresh.erase(di.zone);
-        } else {
-          g_log<<Logger::Debug<<"Got NOTIFY for "<<di.zone<<", going to check SOA serial"<<endl;
+        // We received a NOTIFY for a zone. This means at least one of the zone's primary server is working.
+        // Therefore we delete the zone from the list of failed secondary-checks to allow immediate checking.
+        const auto wasFailedDomain = data->d_failedSecondaryRefresh.find(di.zone);
+        if (wasFailedDomain != data->d_failedSecondaryRefresh.end()) {
+          g_log << Logger::Debug << "Got NOTIFY for " << di.zone << ", removing zone from list of failed secondary-checks and going to check SOA serial" << endl;
+          data->d_failedSecondaryRefresh.erase(di.zone);
+        }
+        else {
+          g_log << Logger::Debug << "Got NOTIFY for " << di.zone << ", going to check SOA serial" << endl;
         }
         rdomains.push_back(di);
       }
     }
     data->d_tocheck.swap(requeue);
 
-    trysuperdomains = std::move(data->d_potentialsupermasters);
-    data->d_potentialsupermasters.clear();
+    trysuperdomains = std::move(data->d_potentialautoprimaries);
+    data->d_potentialautoprimaries.clear();
   }
 
-  for(const DNSPacket& dp :  trysuperdomains) {
+  for (const DNSPacket& dp : trysuperdomains) {
     // get the TSIG key name
     TSIGRecordContent trc;
     DNSName tsigkeyname;
     dp.getTSIGDetails(&trc, &tsigkeyname);
-    P->trySuperMasterSynchronous(dp, tsigkeyname); // FIXME could use some error logging
+    P->tryAutoPrimarySynchronous(dp, tsigkeyname); // FIXME could use some error logging
   }
-  if(rdomains.empty()) { // if we have priority domains, check them first
-    B->getUnfreshSlaveInfos(&rdomains);
+  if (rdomains.empty()) { // if we have priority domains, check them first
+    B->getUnfreshSecondaryInfos(&rdomains);
   }
   sdomains.reserve(rdomains.size());
   DNSSECKeeper dk(B); // NOW HEAR THIS! This DK uses our B backend, so no interleaved access!
   bool checkSignatures = ::arg().mustDo("secondary-check-signature-freshness") && dk.doesDNSSEC();
   {
     auto data = d_data.lock();
-    domains_by_name_t& nameindex=boost::multi_index::get<IDTag>(data->d_suckdomains);
+    domains_by_name_t& nameindex = boost::multi_index::get<IDTag>(data->d_suckdomains);
     time_t now = time(nullptr);
 
-    for(DomainInfo& di :  rdomains) {
-      const auto failed = data->d_failedSlaveRefresh.find(di.zone);
-      if (failed != data->d_failedSlaveRefresh.end() && now < failed->second.second ) {
+    for (DomainInfo& di : rdomains) {
+      const auto failed = data->d_failedSecondaryRefresh.find(di.zone);
+      if (failed != data->d_failedSecondaryRefresh.end() && now < failed->second.second) {
         // If the domain has failed before and the time before the next check has not expired, skip this domain
-        g_log<<Logger::Debug<<"Zone '"<<di.zone<<"' is on the list of failed SOA checks. Skipping SOA checks until "<< failed->second.second<<endl;
+        g_log << Logger::Debug << "Zone '" << di.zone << "' is on the list of failed SOA checks. Skipping SOA checks until " << failed->second.second << endl;
         continue;
       }
       std::vector<std::string> localaddr;
       SuckRequest sr;
-      sr.domain=di.zone;
-      if(di.masters.empty()) // slave domains w/o masters are ignored
+      sr.domain = di.zone;
+      if (di.primaries.empty()) // secondary domains w/o primaries are ignored
         continue;
       // remove unfresh domains already queued for AXFR, no sense polling them again
-      sr.master=*di.masters.begin();
-      if(nameindex.count(sr)) {  // this does NOT however protect us against AXFRs already in progress!
+      sr.primary = *di.primaries.begin();
+      if (nameindex.count(sr)) { // this does NOT however protect us against AXFRs already in progress!
         continue;
       }
-      if(data->d_inprogress.count(sr.domain)) { // this does
+      if (data->d_inprogress.count(sr.domain)) { // this does
         continue;
       }
 
@@ -1190,89 +1193,88 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
       dni.di = di;
       dni.dnssecOk = checkSignatures;
 
-      if(dk.getTSIGForAccess(di.zone, sr.master, &dni.tsigkeyname)) {
+      if (dk.getTSIGForAccess(di.zone, sr.primary, &dni.tsigkeyname)) {
         string secret64;
         if (!B->getTSIGKey(dni.tsigkeyname, dni.tsigalgname, secret64)) {
-          g_log<<Logger::Warning<<"TSIG key '"<<dni.tsigkeyname<<"' for domain '"<<di.zone<<"' not found, can not AXFR."<<endl;
+          g_log << Logger::Warning << "TSIG key '" << dni.tsigkeyname << "' for domain '" << di.zone << "' not found, can not AXFR." << endl;
           continue;
         }
         if (B64Decode(secret64, dni.tsigsecret) == -1) {
-          g_log<<Logger::Error<<"Unable to Base-64 decode TSIG key '"<<dni.tsigkeyname<<"' for domain '"<<di.zone<<"', can not AXFR."<<endl;
+          g_log << Logger::Error << "Unable to Base-64 decode TSIG key '" << dni.tsigkeyname << "' for domain '" << di.zone << "', can not AXFR." << endl;
           continue;
         }
       }
 
       localaddr.clear();
       // check for AXFR-SOURCE
-      if(B->getDomainMetadata(di.zone, "AXFR-SOURCE", localaddr) && !localaddr.empty()) {
+      if (B->getDomainMetadata(di.zone, "AXFR-SOURCE", localaddr) && !localaddr.empty()) {
         try {
           dni.localaddr = ComboAddress(localaddr[0]);
-          g_log<<Logger::Info<<"Freshness check source (AXFR-SOURCE) for domain '"<<di.zone<<"' set to "<<localaddr[0]<<endl;
+          g_log << Logger::Info << "Freshness check source (AXFR-SOURCE) for domain '" << di.zone << "' set to " << localaddr[0] << endl;
         }
-        catch(std::exception& e) {
-          g_log<<Logger::Error<<"Failed to load freshness check source '"<<localaddr[0]<<"' for '"<<di.zone<<"': "<<e.what()<<endl;
+        catch (std::exception& e) {
+          g_log << Logger::Error << "Failed to load freshness check source '" << localaddr[0] << "' for '" << di.zone << "': " << e.what() << endl;
           return;
         }
-      } else {
+      }
+      else {
         dni.localaddr.sin4.sin_family = 0;
       }
 
       sdomains.push_back(std::move(dni));
     }
   }
-  if(sdomains.empty())
-  {
-    if (d_slaveschanged) {
+  if (sdomains.empty()) {
+    if (d_secondarieschanged) {
       auto data = d_data.lock();
-      g_log<<Logger::Info<<"No new unfresh slave domains, "<<data->d_suckdomains.size()<<" queued for AXFR already, "<<data->d_inprogress.size()<<" in progress"<<endl;
+      g_log << Logger::Info << "No new unfresh secondary domains, " << data->d_suckdomains.size() << " queued for AXFR already, " << data->d_inprogress.size() << " in progress" << endl;
     }
-    d_slaveschanged = !rdomains.empty();
+    d_secondarieschanged = !rdomains.empty();
     return;
   }
   else {
     auto data = d_data.lock();
-    g_log<<Logger::Info<<sdomains.size()<<" slave domain"<<(sdomains.size()>1 ? "s" : "")<<" need"<<
-      (sdomains.size()>1 ? "" : "s")<<
-      " checking, "<<data->d_suckdomains.size()<<" queued for AXFR"<<endl;
+    g_log << Logger::Info << sdomains.size() << " secondary domain" << (sdomains.size() > 1 ? "s" : "") << " need" << (sdomains.size() > 1 ? "" : "s") << " checking, " << data->d_suckdomains.size() << " queued for AXFR" << endl;
   }
 
-  SlaveSenderReceiver ssr;
+  SecondarySenderReceiver ssr;
 
-  Inflighter<vector<DomainNotificationInfo>, SlaveSenderReceiver> ifl(sdomains, ssr);
+  Inflighter<vector<DomainNotificationInfo>, SecondarySenderReceiver> ifl(sdomains, ssr);
 
   ifl.d_maxInFlight = 200;
 
-  for(;;) {
+  for (;;) {
     try {
       ifl.run();
       break;
     }
-    catch(std::exception& e) {
-      g_log<<Logger::Error<<"While checking domain freshness: " << e.what()<<endl;
+    catch (std::exception& e) {
+      g_log << Logger::Error << "While checking domain freshness: " << e.what() << endl;
     }
-    catch(PDNSException &re) {
-      g_log<<Logger::Error<<"While checking domain freshness: " << re.reason<<endl;
+    catch (PDNSException& re) {
+      g_log << Logger::Error << "While checking domain freshness: " << re.reason << endl;
     }
   }
 
   if (ifl.getTimeouts()) {
-    g_log<<Logger::Warning<<"Received serial number updates for "<<ssr.d_freshness.size()<<" zone"<<addS(ssr.d_freshness.size())<<", had "<<ifl.getTimeouts()<<" timeout"<<addS(ifl.getTimeouts())<<endl;
-  } else {
-    g_log<<Logger::Info<<"Received serial number updates for "<<ssr.d_freshness.size()<<" zone"<<addS(ssr.d_freshness.size())<<endl;
+    g_log << Logger::Warning << "Received serial number updates for " << ssr.d_freshness.size() << " zone" << addS(ssr.d_freshness.size()) << ", had " << ifl.getTimeouts() << " timeout" << addS(ifl.getTimeouts()) << endl;
+  }
+  else {
+    g_log << Logger::Info << "Received serial number updates for " << ssr.d_freshness.size() << " zone" << addS(ssr.d_freshness.size()) << endl;
   }
 
   time_t now = time(nullptr);
-  for(auto& val : sdomains) {
+  for (auto& val : sdomains) {
     DomainInfo& di(val.di);
     // If our di comes from packethandler (caused by incoming NOTIFY), di.backend will not be filled out,
     // and di.serial will not either.
-    // Conversely, if our di came from getUnfreshSlaveInfos, di.backend and di.serial are valid.
-    if(!di.backend) {
+    // Conversely, if our di came from getUnfreshSecondaryInfos, di.backend and di.serial are valid.
+    if (!di.backend) {
       // Do not overwrite received DI just to make sure it exists in backend:
-      // di.masters should contain the picked master (as first entry)!
+      // di.primaries should contain the picked primary (as first entry)!
       DomainInfo tempdi;
       if (!B->getDomainInfo(di.zone, tempdi, false)) {
-        g_log<<Logger::Info<<"Ignore domain "<< di.zone<<" since it has been removed from our backend"<<endl;
+        g_log << Logger::Info << "Ignore domain " << di.zone << " since it has been removed from our backend" << endl;
         continue;
       }
       // Backend for di still doesn't exist and this might cause us to
@@ -1280,20 +1282,19 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
       di.backend = tempdi.backend;
     }
 
-    if(!ssr.d_freshness.count(di.id)) { // If we don't have an answer for the domain
+    if (!ssr.d_freshness.count(di.id)) { // If we don't have an answer for the domain
       uint64_t newCount = 1;
       auto data = d_data.lock();
-      const auto failedEntry = data->d_failedSlaveRefresh.find(di.zone);
-      if (failedEntry != data->d_failedSlaveRefresh.end())
-        newCount = data->d_failedSlaveRefresh[di.zone].first + 1;
+      const auto failedEntry = data->d_failedSecondaryRefresh.find(di.zone);
+      if (failedEntry != data->d_failedSecondaryRefresh.end())
+        newCount = data->d_failedSecondaryRefresh[di.zone].first + 1;
       time_t nextCheck = now + std::min(newCount * d_tickinterval, (uint64_t)::arg().asNum("default-ttl"));
-      data->d_failedSlaveRefresh[di.zone] = {newCount, nextCheck};
+      data->d_failedSecondaryRefresh[di.zone] = {newCount, nextCheck};
       if (newCount == 1) {
-        g_log<<Logger::Warning<<"Unable to retrieve SOA for "<<di.zone<<
-          ", this was the first time. NOTE: For every subsequent failed SOA check the domain will be suspended from freshness checks for 'num-errors x "<<
-          d_tickinterval<<" seconds', with a maximum of "<<(uint64_t)::arg().asNum("default-ttl")<<" seconds. Skipping SOA checks until "<<nextCheck<<endl;
-      } else if (newCount % 10 == 0) {
-        g_log<<Logger::Notice<<"Unable to retrieve SOA for "<<di.zone<<", this was the "<<std::to_string(newCount)<<"th time. Skipping SOA checks until "<<nextCheck<<endl;
+        g_log << Logger::Warning << "Unable to retrieve SOA for " << di.zone << ", this was the first time. NOTE: For every subsequent failed SOA check the domain will be suspended from freshness checks for 'num-errors x " << d_tickinterval << " seconds', with a maximum of " << (uint64_t)::arg().asNum("default-ttl") << " seconds. Skipping SOA checks until " << nextCheck << endl;
+      }
+      else if (newCount % 10 == 0) {
+        g_log << Logger::Notice << "Unable to retrieve SOA for " << di.zone << ", this was the " << std::to_string(newCount) << "th time. Skipping SOA checks until " << nextCheck << endl;
       }
       // Make sure we recheck SOA for notifies
       if (di.receivedNotify) {
@@ -1304,9 +1305,9 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
 
     {
       auto data = d_data.lock();
-      const auto wasFailedDomain = data->d_failedSlaveRefresh.find(di.zone);
-      if (wasFailedDomain != data->d_failedSlaveRefresh.end())
-        data->d_failedSlaveRefresh.erase(di.zone);
+      const auto wasFailedDomain = data->d_failedSecondaryRefresh.find(di.zone);
+      if (wasFailedDomain != data->d_failedSecondaryRefresh.end())
+        data->d_failedSecondaryRefresh.erase(di.zone);
     }
 
     bool hasSOA = false;
@@ -1318,27 +1319,29 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
       hasSOA = B->get(zr);
       if (hasSOA) {
         fillSOAData(zr, sd);
-        while(B->get(zr));
+        while (B->get(zr))
+          ;
       }
     }
-    catch(...) {}
+    catch (...) {
+    }
 
     uint32_t theirserial = ssr.d_freshness[di.id].theirSerial;
     uint32_t ourserial = sd.serial;
-    const ComboAddress remote = *di.masters.begin();
+    const ComboAddress remote = *di.primaries.begin();
 
-    if(hasSOA && rfc1982LessThan(theirserial, ourserial) && !::arg().mustDo("axfr-lower-serial"))  {
-      g_log<<Logger::Warning<<"Domain '" << di.zone << "' more recent than master " << remote.toStringWithPortExcept(53) << ", our serial "<< ourserial<< " > their serial "<< theirserial << endl;
+    if (hasSOA && rfc1982LessThan(theirserial, ourserial) && !::arg().mustDo("axfr-lower-serial")) {
+      g_log << Logger::Warning << "Domain '" << di.zone << "' more recent than primary " << remote.toStringWithPortExcept(53) << ", our serial " << ourserial << " > their serial " << theirserial << endl;
       di.backend->setFresh(di.id);
     }
-    else if(hasSOA && theirserial == ourserial) {
-      uint32_t maxExpire=0, maxInception=0;
-      if(checkSignatures && dk.isPresigned(di.zone)) {
+    else if (hasSOA && theirserial == ourserial) {
+      uint32_t maxExpire = 0, maxInception = 0;
+      if (checkSignatures && dk.isPresigned(di.zone)) {
         B->lookup(QType(QType::RRSIG), di.zone, di.id); // can't use DK before we are done with this lookup!
         DNSZoneRecord zr;
-        while(B->get(zr)) {
+        while (B->get(zr)) {
           auto rrsig = getRR<RRSIGRecordContent>(zr.dr);
-          if(rrsig->d_type == QType::SOA) {
+          if (rrsig->d_type == QType::SOA) {
             maxInception = std::max(maxInception, rrsig->d_siginception);
             maxExpire = std::max(maxExpire, rrsig->d_sigexpire);
           }
@@ -1350,28 +1353,28 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
         prio = SuckRequest::Notify;
       }
 
-      if(! maxInception && ! ssr.d_freshness[di.id].theirInception) {
-        g_log<<Logger::Info<<"Domain '"<< di.zone << "' is fresh (no DNSSEC), serial is " << ourserial << " (checked master " << remote.toStringWithPortExcept(53) << ")" << endl;
+      if (!maxInception && !ssr.d_freshness[di.id].theirInception) {
+        g_log << Logger::Info << "Domain '" << di.zone << "' is fresh (no DNSSEC), serial is " << ourserial << " (checked primary " << remote.toStringWithPortExcept(53) << ")" << endl;
         di.backend->setFresh(di.id);
       }
-      else if(maxInception == ssr.d_freshness[di.id].theirInception && maxExpire == ssr.d_freshness[di.id].theirExpire) {
-        g_log<<Logger::Info<<"Domain '"<< di.zone << "' is fresh and SOA RRSIGs match, serial is " << ourserial << " (checked master " << remote.toStringWithPortExcept(53) << ")" << endl;
+      else if (maxInception == ssr.d_freshness[di.id].theirInception && maxExpire == ssr.d_freshness[di.id].theirExpire) {
+        g_log << Logger::Info << "Domain '" << di.zone << "' is fresh and SOA RRSIGs match, serial is " << ourserial << " (checked primary " << remote.toStringWithPortExcept(53) << ")" << endl;
         di.backend->setFresh(di.id);
       }
-      else if(maxExpire >= now && ! ssr.d_freshness[di.id].theirInception ) {
-        g_log<<Logger::Info<<"Domain '"<< di.zone << "' is fresh, master " << remote.toStringWithPortExcept(53) << " is no longer signed but (some) signatures are still valid, serial is " << ourserial << endl;
+      else if (maxExpire >= now && !ssr.d_freshness[di.id].theirInception) {
+        g_log << Logger::Info << "Domain '" << di.zone << "' is fresh, primary " << remote.toStringWithPortExcept(53) << " is no longer signed but (some) signatures are still valid, serial is " << ourserial << endl;
         di.backend->setFresh(di.id);
       }
-      else if(maxInception && ! ssr.d_freshness[di.id].theirInception ) {
-        g_log<<Logger::Notice<<"Domain '"<< di.zone << "' is stale, master " << remote.toStringWithPortExcept(53) << " is no longer signed and all signatures have expired, serial is " << ourserial << endl;
+      else if (maxInception && !ssr.d_freshness[di.id].theirInception) {
+        g_log << Logger::Notice << "Domain '" << di.zone << "' is stale, primary " << remote.toStringWithPortExcept(53) << " is no longer signed and all signatures have expired, serial is " << ourserial << endl;
         addSuckRequest(di.zone, remote, prio);
       }
-      else if(dk.doesDNSSEC() && ! maxInception && ssr.d_freshness[di.id].theirInception) {
-        g_log<<Logger::Notice<<"Domain '"<< di.zone << "' is stale, master " << remote.toStringWithPortExcept(53) << " has signed, serial is " << ourserial << endl;
+      else if (dk.doesDNSSEC() && !maxInception && ssr.d_freshness[di.id].theirInception) {
+        g_log << Logger::Notice << "Domain '" << di.zone << "' is stale, primary " << remote.toStringWithPortExcept(53) << " has signed, serial is " << ourserial << endl;
         addSuckRequest(di.zone, remote, prio);
       }
       else {
-        g_log<<Logger::Notice<<"Domain '"<< di.zone << "' is fresh, but RRSIGs differ on master " << remote.toStringWithPortExcept(53)<<", so DNSSEC is stale, serial is " << ourserial << endl;
+        g_log << Logger::Notice << "Domain '" << di.zone << "' is fresh, but RRSIGs differ on primary " << remote.toStringWithPortExcept(53) << ", so DNSSEC is stale, serial is " << ourserial << endl;
         addSuckRequest(di.zone, remote, prio);
       }
     }
@@ -1382,26 +1385,28 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P)
       }
 
       if (hasSOA) {
-        g_log<<Logger::Notice<<"Domain '"<< di.zone << "' is stale, master " << remote.toStringWithPortExcept(53) << " serial " << theirserial << ", our serial " << ourserial << endl;
+        g_log << Logger::Notice << "Domain '" << di.zone << "' is stale, primary " << remote.toStringWithPortExcept(53) << " serial " << theirserial << ", our serial " << ourserial << endl;
       }
       else {
-        g_log<<Logger::Notice<<"Domain '"<< di.zone << "' is empty, master " << remote.toStringWithPortExcept(53) << " serial " << theirserial << endl;
+        g_log << Logger::Notice << "Domain '" << di.zone << "' is empty, primary " << remote.toStringWithPortExcept(53) << " serial " << theirserial << endl;
       }
       addSuckRequest(di.zone, remote, prio);
     }
   }
 }
 
-vector<pair<DNSName, ComboAddress> > CommunicatorClass::getSuckRequests() {
-  vector<pair<DNSName, ComboAddress> > ret;
+vector<pair<DNSName, ComboAddress>> CommunicatorClass::getSuckRequests()
+{
+  vector<pair<DNSName, ComboAddress>> ret;
   auto data = d_data.lock();
   ret.reserve(data->d_suckdomains.size());
-  for (auto const &d : data->d_suckdomains) {
-    ret.emplace_back(d.domain, d.master);
+  for (auto constd : data->d_suckdomains) {
+    ret.emplace_back(d.domain, d.primary);
   }
   return ret;
 }
 
-size_t CommunicatorClass::getSuckRequestsWaiting() {
+size_t CommunicatorClass::getSuckRequestsWaiting()
+{
   return d_data.lock()->d_suckdomains.size();
 }
index db0b7acee3b7c1f906c2e07bc4972cf5fc44f7d5..d3351d16dd4e93977ff967b06719714c0e0fd16c 100644 (file)
@@ -67,22 +67,22 @@ GSQLBackend::GSQLBackend(const string &mode, const string &suffix)
   d_listSubZoneQuery=getArg("list-subzone-query");
 
   d_InfoOfDomainsZoneQuery=getArg("info-zone-query");
-  d_InfoOfAllSlaveDomainsQuery=getArg("info-all-slaves-query");
-  d_SuperMasterInfoQuery=getArg("supermaster-query");
-  d_GetSuperMasterIPs=getArg("supermaster-name-to-ips");
-  d_AddSuperMaster=getArg("supermaster-add");
+  d_InfoOfAllSecondaryDomainsQuery = getArg("info-all-secondaries-query");
+  d_AutoPrimaryInfoQuery = getArg("autoprimary-query");
+  d_GetAutoPrimaryIPs = getArg("autoprimary-name-to-ips");
+  d_AddAutoPrimary = getArg("autoprimary-add");
   d_RemoveAutoPrimaryQuery=getArg("autoprimary-remove");
   d_ListAutoPrimariesQuery=getArg("list-autoprimaries");
   d_InsertZoneQuery=getArg("insert-zone-query");
   d_InsertRecordQuery=getArg("insert-record-query");
-  d_UpdateMasterOfZoneQuery=getArg("update-master-query");
+  d_UpdatePrimaryOfZoneQuery = getArg("update-primary-query");
   d_UpdateKindOfZoneQuery=getArg("update-kind-query");
   d_UpdateSerialOfZoneQuery=getArg("update-serial-query");
   d_UpdateLastCheckOfZoneQuery=getArg("update-lastcheck-query");
   d_UpdateOptionsOfZoneQuery = getArg("update-options-query");
   d_UpdateCatalogOfZoneQuery = getArg("update-catalog-query");
   d_UpdateAccountOfZoneQuery=getArg("update-account-query");
-  d_InfoOfAllMasterDomainsQuery=getArg("info-all-master-query");
+  d_InfoOfAllPrimaryDomainsQuery = getArg("info-all-primary-query");
   d_InfoProducerMembersQuery = getArg("info-producer-members-query");
   d_InfoConsumerMembersQuery = getArg("info-consumer-members-query");
   d_DeleteDomainQuery=getArg("delete-domain-query");
@@ -143,23 +143,23 @@ GSQLBackend::GSQLBackend(const string &mode, const string &suffix)
   d_listQuery_stmt = nullptr;
   d_listSubZoneQuery_stmt = nullptr;
   d_InfoOfDomainsZoneQuery_stmt = nullptr;
-  d_InfoOfAllSlaveDomainsQuery_stmt = nullptr;
-  d_SuperMasterInfoQuery_stmt = nullptr;
-  d_GetSuperMasterIPs_stmt = nullptr;
-  d_AddSuperMaster_stmt = nullptr;
+  d_InfoOfAllSecondaryDomainsQuery_stmt = nullptr;
+  d_AutoPrimaryInfoQuery_stmt = nullptr;
+  d_GetAutoPrimaryIPs_stmt = nullptr;
+  d_AddAutoPrimary_stmt = nullptr;
   d_RemoveAutoPrimary_stmt = nullptr;
   d_ListAutoPrimaries_stmt = nullptr;
   d_InsertZoneQuery_stmt = nullptr;
   d_InsertRecordQuery_stmt = nullptr;
   d_InsertEmptyNonTerminalOrderQuery_stmt = nullptr;
-  d_UpdateMasterOfZoneQuery_stmt = nullptr;
+  d_UpdatePrimaryOfZoneQuery_stmt = nullptr;
   d_UpdateKindOfZoneQuery_stmt = nullptr;
   d_UpdateSerialOfZoneQuery_stmt = nullptr;
   d_UpdateLastCheckOfZoneQuery_stmt = nullptr;
   d_UpdateOptionsOfZoneQuery_stmt = nullptr;
   d_UpdateCatalogOfZoneQuery_stmt = nullptr;
   d_UpdateAccountOfZoneQuery_stmt = nullptr;
-  d_InfoOfAllMasterDomainsQuery_stmt = nullptr;
+  d_InfoOfAllPrimaryDomainsQuery_stmt = nullptr;
   d_InfoProducerMembersQuery_stmt = nullptr;
   d_InfoConsumerMembersQuery_stmt = nullptr;
   d_DeleteDomainQuery_stmt = nullptr;
@@ -208,11 +208,13 @@ void GSQLBackend::setNotified(uint32_t domain_id, uint32_t serial)
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_UpdateSerialOfZoneQuery_stmt->
       bind("serial", serial)->
       bind("domain_id", domain_id)->
       execute()->
       reset();
+    // clang-format on
   }
   catch(SSqlException &e) {
     throw PDNSException("GSQLBackend unable to refresh domain_id "+std::to_string(domain_id)+": "+e.txtReason());
@@ -224,7 +226,12 @@ void GSQLBackend::setLastCheck(uint32_t domain_id, time_t lastcheck)
   try {
     reconnectIfNeeded();
 
-    d_UpdateLastCheckOfZoneQuery_stmt->bind("last_check", lastcheck)->bind("domain_id", domain_id)->execute()->reset();
+    // clang-format off
+    d_UpdateLastCheckOfZoneQuery_stmt->
+      bind("last_check", lastcheck)->
+      bind("domain_id", domain_id)->
+      execute()->reset();
+    // clang-format on
   }
   catch (SSqlException &e) {
     throw PDNSException("GSQLBackend unable to update last_check for domain_id " + std::to_string(domain_id) + ": " + e.txtReason());
@@ -241,27 +248,29 @@ void GSQLBackend::setFresh(uint32_t domain_id)
   setLastCheck(domain_id, time(nullptr));
 }
 
-bool GSQLBackend::setMasters(const DNSName &domain, const vector<ComboAddress> &masters)
+bool GSQLBackend::setPrimaries(const DNSName& domain, const vector<ComboAddress>& primaries)
 {
-  vector<string> masters_s;
-  masters_s.reserve(masters.size());
-  for (const auto& master : masters) {
-    masters_s.push_back(master.toStringWithPortExcept(53));
+  vector<string> primaries_s;
+  primaries_s.reserve(primaries.size());
+  for (const auto& primary : primaries) {
+    primaries_s.push_back(primary.toStringWithPortExcept(53));
   }
 
-  auto tmp = boost::join(masters_s, ", ");
+  auto tmp = boost::join(primaries_s, ", ");
 
   try {
     reconnectIfNeeded();
 
-    d_UpdateMasterOfZoneQuery_stmt->
+    // clang-format off
+    d_UpdatePrimaryOfZoneQuery_stmt->
       bind("master", tmp)->
       bind("domain", domain)->
       execute()->
       reset();
+    // clang-format on
   }
   catch (SSqlException &e) {
-    throw PDNSException("GSQLBackend unable to set masters of domain '"+domain.toLogString()+"' to " + tmp + ": "+e.txtReason());
+    throw PDNSException("GSQLBackend unable to set primaries of domain '" + domain.toLogString() + "' to " + tmp + ": " + e.txtReason());
   }
   return true;
 }
@@ -271,11 +280,13 @@ bool GSQLBackend::setKind(const DNSName &domain, const DomainInfo::DomainKind ki
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_UpdateKindOfZoneQuery_stmt->
       bind("kind", toUpper(DomainInfo::getKindString(kind)))->
       bind("domain", domain)->
       execute()->
       reset();
+    // clang-format on
   }
   catch (SSqlException &e) {
     throw PDNSException("GSQLBackend unable to set kind of domain '"+domain.toLogString()+"' to " + toUpper(DomainInfo::getKindString(kind)) + ": "+e.txtReason());
@@ -326,11 +337,13 @@ bool GSQLBackend::setAccount(const DNSName &domain, const string &account)
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_UpdateAccountOfZoneQuery_stmt->
-            bind("account", account)->
-            bind("domain", domain)->
-            execute()->
-            reset();
+      bind("account", account)->
+      bind("domain", domain)->
+      execute()->
+      reset();
+    // clang-format on
   }
   catch (SSqlException &e) {
     throw PDNSException("GSQLBackend unable to set account of domain '"+domain.toLogString()+"' to '" + account + "': "+e.txtReason());
@@ -345,11 +358,13 @@ bool GSQLBackend::getDomainInfo(const DNSName &domain, DomainInfo &di, bool getS
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_InfoOfDomainsZoneQuery_stmt->
       bind("domain", domain)->
       execute()->
       getResult(d_result)->
       reset();
+    // clang-format on
   }
   catch(SSqlException &e) {
     throw PDNSException("GSQLBackend unable to retrieve information about domain '" + domain.toLogString() + "': "+e.txtReason());
@@ -373,10 +388,10 @@ bool GSQLBackend::getDomainInfo(const DNSName &domain, DomainInfo &di, bool getS
   di.account = d_result[0][8];
   di.kind = DomainInfo::stringToKind(type);
 
-  vector<string> masters;
-  stringtok(masters, d_result[0][2], " ,\t");
-  for(const auto& m : masters)
-    di.masters.emplace_back(m, 53);
+  vector<string> primaries;
+  stringtok(primaries, d_result[0][2], " ,\t");
+  for (const auto& m : primaries)
+    di.primaries.emplace_back(m, 53);
   pdns::checked_stoi_into(di.last_check, d_result[0][3]);
   pdns::checked_stoi_into(di.notified_serial, d_result[0][4]);
   di.backend=this;
@@ -398,7 +413,7 @@ bool GSQLBackend::getDomainInfo(const DNSName &domain, DomainInfo &di, bool getS
   return true;
 }
 
-void GSQLBackend::getUnfreshSlaveInfos(vector<DomainInfo> *unfreshDomains)
+void GSQLBackend::getUnfreshSecondaryInfos(vector<DomainInfo>* unfreshDomains)
 {
   /*
     list all domains that need refreshing for which we are secondary, and insert into
@@ -409,23 +424,23 @@ void GSQLBackend::getUnfreshSlaveInfos(vector<DomainInfo> *unfreshDomains)
     reconnectIfNeeded();
 
     // clang-format off
-    d_InfoOfAllSlaveDomainsQuery_stmt->
+    d_InfoOfAllSecondaryDomainsQuery_stmt->
       execute()->
       getResult(d_result)->
       reset();
     // clang-format on
   }
   catch (SSqlException &e) {
-    throw PDNSException(std::string(__PRETTY_FUNCTION__) + " unable to retrieve list of slave domains: " + e.txtReason());
+    throw PDNSException(std::string(__PRETTY_FUNCTION__) + " unable to retrieve list of secondary domains: " + e.txtReason());
   }
 
   SOAData sd;
   DomainInfo di;
-  vector<string> masters;
+  vector<string> primaries;
 
   unfreshDomains->reserve(d_result.size());
   for (const auto& row : d_result) { // id, name, type, master, last_check, catalog, content
-    ASSERT_ROW_COLUMNS("info-all-slaves-query", row, 6);
+    ASSERT_ROW_COLUMNS("info-all-secondaries-query", row, 6);
 
     try {
       di.zone = DNSName(row[1]);
@@ -474,23 +489,23 @@ void GSQLBackend::getUnfreshSlaveInfos(vector<DomainInfo> *unfreshDomains)
       continue;
     }
 
-    di.masters.clear();
-    masters.clear();
-    stringtok(masters, row[3], ", \t");
-    for(const auto& m : masters) {
+    di.primaries.clear();
+    primaries.clear();
+    stringtok(primaries, row[3], ", \t");
+    for (const auto& m : primaries) {
       try {
-        di.masters.emplace_back(m, 53);
+        di.primaries.emplace_back(m, 53);
       } catch(const PDNSException &e) {
-        g_log << Logger::Warning << __PRETTY_FUNCTION__ << " could not parse master address '" << m << "' for zone '" << di.zone << "': " << e.reason << endl;
+        g_log << Logger::Warning << __PRETTY_FUNCTION__ << " could not parse primary address '" << m << "' for zone '" << di.zone << "': " << e.reason << endl;
       }
     }
-    if (di.masters.empty()) {
-      g_log << Logger::Warning << __PRETTY_FUNCTION__ << " no masters for secondary zone '" << di.zone << "' found in the database" << endl;
+    if (di.primaries.empty()) {
+      g_log << Logger::Warning << __PRETTY_FUNCTION__ << " no primaries for secondary zone '" << di.zone << "' found in the database" << endl;
       continue;
     }
 
     if (pdns_iequals(row[2], "SLAVE")) {
-      di.kind = DomainInfo::Slave;
+      di.kind = DomainInfo::Secondary;
     }
     else if (pdns_iequals(row[2], "CONSUMER")) {
       di.kind = DomainInfo::Consumer;
@@ -504,7 +519,7 @@ void GSQLBackend::getUnfreshSlaveInfos(vector<DomainInfo> *unfreshDomains)
   }
 }
 
-void GSQLBackend::getUpdatedMasters(vector<DomainInfo>& updatedDomains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes)
+void GSQLBackend::getUpdatedPrimaries(vector<DomainInfo>& updatedDomains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes)
 {
   /*
     list all domains that need notifications for which we are promary, and insert into
@@ -515,14 +530,14 @@ void GSQLBackend::getUpdatedMasters(vector<DomainInfo>& updatedDomains, std::uno
     reconnectIfNeeded();
 
     // clang-format off
-    d_InfoOfAllMasterDomainsQuery_stmt->
+    d_InfoOfAllPrimaryDomainsQuery_stmt->
       execute()->
       getResult(d_result)->
       reset();
     // clang-format on
   }
   catch(SSqlException &e) {
-    throw PDNSException(std::string(__PRETTY_FUNCTION__) + " unable to retrieve list of master domains: " + e.txtReason());
+    throw PDNSException(std::string(__PRETTY_FUNCTION__) + " unable to retrieve list of primary domains: " + e.txtReason());
   }
 
   SOAData sd;
@@ -531,7 +546,7 @@ void GSQLBackend::getUpdatedMasters(vector<DomainInfo>& updatedDomains, std::uno
 
   updatedDomains.reserve(d_result.size());
   for (const auto& row : d_result) { // id, name, type, notified_serial, options, catalog, content
-    ASSERT_ROW_COLUMNS("info-all-master-query", row, 7);
+    ASSERT_ROW_COLUMNS("info-all-primary-query", row, 7);
 
     di.backend = this;
 
@@ -608,7 +623,7 @@ void GSQLBackend::getUpdatedMasters(vector<DomainInfo>& updatedDomains, std::uno
     }
 
     if (di.notified_serial != sd.serial) {
-      di.kind = DomainInfo::Master;
+      di.kind = DomainInfo::Primary;
       di.serial = sd.serial;
       di.catalog.clear();
 
@@ -692,14 +707,14 @@ bool GSQLBackend::getCatalogMembers(const DNSName& catalog, vector<CatalogInfo>&
     }
 
     if (row.size() >= 4) { // Consumer only
-      vector<string> masters;
-      stringtok(masters, row[3], ", \t");
-      for (const auto& m : masters) {
+      vector<string> primaries;
+      stringtok(primaries, row[3], ", \t");
+      for (const auto& m : primaries) {
         try {
           ci.d_primaries.emplace_back(m, 53);
         }
         catch (const PDNSException& e) {
-          g_log << Logger::Warning << __PRETTY_FUNCTION__ << " could not parse master address '" << m << "' for zone '" << ci.d_zone << "': " << e.reason << endl;
+          g_log << Logger::Warning << __PRETTY_FUNCTION__ << " could not parse primary address '" << m << "' for zone '" << ci.d_zone << "': " << e.reason << endl;
           members.clear();
           return false;
         }
@@ -721,6 +736,7 @@ bool GSQLBackend::updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName
       try {
         reconnectIfNeeded();
 
+        // clang-format off
         d_updateOrderNameAndAuthQuery_stmt->
           bind("ordername", ordername.labelReverse().toString(" ", false))->
           bind("auth", auth)->
@@ -728,6 +744,7 @@ bool GSQLBackend::updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName
           bind("qname", qname)->
           execute()->
           reset();
+        // clang-format on
       }
       catch(SSqlException &e) {
         throw PDNSException("GSQLBackend unable to update ordername and auth for " + qname.toLogString() + " for domain_id "+std::to_string(domain_id)+", domain name '" + qname.toLogString() + "': "+e.txtReason());
@@ -736,6 +753,7 @@ bool GSQLBackend::updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName
       try {
         reconnectIfNeeded();
 
+        // clang-format off
         d_updateOrderNameAndAuthTypeQuery_stmt->
           bind("ordername", ordername.labelReverse().toString(" ", false))->
           bind("auth", auth)->
@@ -744,6 +762,7 @@ bool GSQLBackend::updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName
           bind("qtype", QType(qtype).toString())->
           execute()->
           reset();
+        // clang-format on
       }
       catch(SSqlException &e) {
         throw PDNSException("GSQLBackend unable to update ordername and auth for " + qname.toLogString() + "|" + QType(qtype).toString() + " for domain_id "+std::to_string(domain_id)+": "+e.txtReason());
@@ -754,12 +773,14 @@ bool GSQLBackend::updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName
       reconnectIfNeeded();
 
       try {
+        // clang-format off
         d_nullifyOrderNameAndUpdateAuthQuery_stmt->
           bind("auth", auth)->
           bind("domain_id", domain_id)->
           bind("qname", qname)->
           execute()->
           reset();
+        // clang-format on
       }
       catch(SSqlException &e) {
         throw PDNSException("GSQLBackend unable to nullify ordername and update auth for " + qname.toLogString() + " for domain_id "+std::to_string(domain_id)+": "+e.txtReason());
@@ -768,6 +789,7 @@ bool GSQLBackend::updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName
       try {
         reconnectIfNeeded();
 
+        // clang-format off
         d_nullifyOrderNameAndUpdateAuthTypeQuery_stmt->
           bind("auth", auth)->
           bind("domain_id", domain_id)->
@@ -775,6 +797,7 @@ bool GSQLBackend::updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName
           bind("qtype", QType(qtype).toString())->
           execute()->
           reset();
+        // clang-format on
       }
       catch(SSqlException &e) {
         throw PDNSException("GSQLBackend unable to nullify ordername and update auth for " + qname.toLogString() + "|" + QType(qtype).toString() + " for domain_id "+std::to_string(domain_id)+": "+e.txtReason());
@@ -790,10 +813,12 @@ bool GSQLBackend::updateEmptyNonTerminals(uint32_t domain_id, set<DNSName>& inse
     try {
       reconnectIfNeeded();
 
+      // clang-format off
       d_RemoveEmptyNonTerminalsFromZoneQuery_stmt->
         bind("domain_id", domain_id)->
         execute()->
         reset();
+      // clang-format on
     }
     catch (SSqlException &e) {
       throw PDNSException("GSQLBackend unable to delete empty non-terminal records from domain_id "+std::to_string(domain_id)+": "+e.txtReason());
@@ -805,11 +830,13 @@ bool GSQLBackend::updateEmptyNonTerminals(uint32_t domain_id, set<DNSName>& inse
       try {
         reconnectIfNeeded();
 
+        // clang-format off
         d_DeleteEmptyNonTerminalQuery_stmt->
           bind("domain_id", domain_id)->
           bind("qname", qname)->
           execute()->
           reset();
+        // clang-format on
       }
       catch (SSqlException &e) {
         throw PDNSException("GSQLBackend unable to delete empty non-terminal rr '"+qname.toLogString()+"' from domain_id "+std::to_string(domain_id)+": "+e.txtReason());
@@ -821,6 +848,7 @@ bool GSQLBackend::updateEmptyNonTerminals(uint32_t domain_id, set<DNSName>& inse
     try {
       reconnectIfNeeded();
 
+      // clang-format off
       d_InsertEmptyNonTerminalOrderQuery_stmt->
         bind("domain_id", domain_id)->
         bind("qname", qname)->
@@ -828,6 +856,7 @@ bool GSQLBackend::updateEmptyNonTerminals(uint32_t domain_id, set<DNSName>& inse
         bind("auth", true)->
         execute()->
         reset();
+      // clang-format on
     }
     catch (SSqlException &e) {
       throw PDNSException("GSQLBackend unable to insert empty non-terminal rr '"+qname.toLogString()+"' in domain_id "+std::to_string(domain_id)+": "+e.txtReason());
@@ -852,10 +881,12 @@ bool GSQLBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_afterOrderQuery_stmt->
       bind("ordername", qname.labelReverse().toString(" ", false))->
       bind("domain_id", id)->
       execute();
+    // clang-format on
     while(d_afterOrderQuery_stmt->hasNextRow()) {
       d_afterOrderQuery_stmt->nextRow(row);
       ASSERT_ROW_COLUMNS("get-order-after-query", row, 1);
@@ -873,9 +904,11 @@ bool GSQLBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna
     try {
       reconnectIfNeeded();
 
+      // clang-format off
       d_firstOrderQuery_stmt->
         bind("domain_id", id)->
         execute();
+      // clang-format on
       while(d_firstOrderQuery_stmt->hasNextRow()) {
         d_firstOrderQuery_stmt->nextRow(row);
         ASSERT_ROW_COLUMNS("get-order-first-query", row, 1);
@@ -894,10 +927,12 @@ bool GSQLBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna
     try {
       reconnectIfNeeded();
 
+      // clang-format off
       d_beforeOrderQuery_stmt->
         bind("ordername", qname.labelReverse().toString(" ", false))->
         bind("domain_id", id)->
         execute();
+      // clang-format on
       while(d_beforeOrderQuery_stmt->hasNextRow()) {
         d_beforeOrderQuery_stmt->nextRow(row);
         ASSERT_ROW_COLUMNS("get-order-before-query", row, 2);
@@ -923,9 +958,11 @@ bool GSQLBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qna
     try {
       reconnectIfNeeded();
 
+      // clang-format off
       d_lastOrderQuery_stmt->
         bind("domain_id", id)->
         execute();
+      // clang-format on
       while(d_lastOrderQuery_stmt->hasNextRow()) {
         d_lastOrderQuery_stmt->nextRow(row);
         ASSERT_ROW_COLUMNS("get-order-last-query", row, 2);
@@ -956,6 +993,7 @@ bool GSQLBackend::addDomainKey(const DNSName& name, const KeyData& key, int64_t&
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_AddDomainKeyQuery_stmt->
       bind("flags", key.flags)->
       bind("active", key.active)->
@@ -963,6 +1001,7 @@ bool GSQLBackend::addDomainKey(const DNSName& name, const KeyData& key, int64_t&
       bind("content", key.content)->
       bind("domain", name)->
       execute();
+    // clang-format on
 
     if (d_AddDomainKeyQuery_stmt->hasNextRow()) {
       SSqlStatement::row_t row;
@@ -1007,11 +1046,13 @@ bool GSQLBackend::activateDomainKey(const DNSName& name, unsigned int id)
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_ActivateDomainKeyQuery_stmt->
       bind("domain", name)->
       bind("key_id", id)->
       execute()->
       reset();
+    // clang-format on
   }
   catch (SSqlException &e) {
     throw PDNSException("GSQLBackend unable to activate key with id "+ std::to_string(id) + " for domain '" + name.toLogString() + "': "+e.txtReason());
@@ -1027,11 +1068,13 @@ bool GSQLBackend::deactivateDomainKey(const DNSName& name, unsigned int id)
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_DeactivateDomainKeyQuery_stmt->
       bind("domain", name)->
       bind("key_id", id)->
       execute()->
       reset();
+    // clang-format on
   }
   catch (SSqlException &e) {
     throw PDNSException("GSQLBackend unable to deactivate key with id "+ std::to_string(id) + " for domain '" + name.toLogString() + "': "+e.txtReason());
@@ -1047,11 +1090,13 @@ bool GSQLBackend::publishDomainKey(const DNSName& name, unsigned int id)
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_PublishDomainKeyQuery_stmt->
       bind("domain", name)->
       bind("key_id", id)->
       execute()->
       reset();
+    // clang-format on
   }
   catch (SSqlException &e) {
     throw PDNSException("GSQLBackend unable to publish key with id "+ std::to_string(id) + " for domain '" + name.toLogString() + "': "+e.txtReason());
@@ -1067,11 +1112,13 @@ bool GSQLBackend::unpublishDomainKey(const DNSName& name, unsigned int id)
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_UnpublishDomainKeyQuery_stmt->
       bind("domain", name)->
       bind("key_id", id)->
       execute()->
       reset();
+    // clang-format on
   }
   catch (SSqlException &e) {
     throw PDNSException("GSQLBackend unable to unpublish key with id "+ std::to_string(id) + " for domain '" + name.toLogString() + "': "+e.txtReason());
@@ -1089,11 +1136,13 @@ bool GSQLBackend::removeDomainKey(const DNSName& name, unsigned int id)
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_RemoveDomainKeyQuery_stmt->
       bind("domain", name)->
       bind("key_id", id)->
       execute()->
       reset();
+    // clang-format on
   }
   catch (SSqlException &e) {
     throw PDNSException("GSQLBackend unable to remove key with id "+ std::to_string(id) + " for domain '" + name.toLogString() + "': "+e.txtReason());
@@ -1106,9 +1155,11 @@ bool GSQLBackend::getTSIGKey(const DNSName& name, DNSName& algorithm, string& co
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_getTSIGKeyQuery_stmt->
       bind("key_name", name)->
       execute();
+    // clang-format on
 
     SSqlStatement::row_t row;
 
@@ -1137,12 +1188,14 @@ bool GSQLBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, cons
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_setTSIGKeyQuery_stmt->
       bind("key_name", name)->
       bind("algorithm", algorithm)->
       bind("content", content)->
       execute()->
       reset();
+    // clang-format on
   }
   catch (SSqlException &e) {
     throw PDNSException("GSQLBackend unable to store TSIG key with name '" + name.toLogString() + "' and algorithm '" + algorithm.toString() + "': "+e.txtReason());
@@ -1155,10 +1208,12 @@ bool GSQLBackend::deleteTSIGKey(const DNSName& name)
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_deleteTSIGKeyQuery_stmt->
       bind("key_name", name)->
       execute()->
       reset();
+    // clang-format on
   }
   catch (SSqlException &e) {
     throw PDNSException("GSQLBackend unable to delete TSIG key with name '" + name.toLogString() + "': "+e.txtReason());
@@ -1171,8 +1226,10 @@ bool GSQLBackend::getTSIGKeys(std::vector< struct TSIGKey > &keys)
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_getTSIGKeysQuery_stmt->
       execute();
+    // clang-format on
 
     SSqlStatement::row_t row;
 
@@ -1207,9 +1264,11 @@ bool GSQLBackend::getDomainKeys(const DNSName& name, std::vector<KeyData>& keys)
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_ListDomainKeysQuery_stmt->
       bind("domain", name)->
       execute();
+    // clang-format on
 
     SSqlStatement::row_t row;
     KeyData kd;
@@ -1241,9 +1300,11 @@ bool GSQLBackend::getAllDomainMetadata(const DNSName& name, std::map<std::string
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_GetAllDomainMetadataQuery_stmt->
       bind("domain", name)->
       execute();
+    // clang-format on
 
     SSqlStatement::row_t row;
 
@@ -1273,10 +1334,12 @@ bool GSQLBackend::getDomainMetadata(const DNSName& name, const std::string& kind
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_GetDomainMetadataQuery_stmt->
       bind("domain", name)->
       bind("kind", kind)->
       execute();
+    // clang-format on
 
     SSqlStatement::row_t row;
 
@@ -1303,19 +1366,23 @@ bool GSQLBackend::setDomainMetadata(const DNSName& name, const std::string& kind
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_ClearDomainMetadataQuery_stmt->
       bind("domain", name)->
       bind("kind", kind)->
       execute()->
       reset();
+    // clang-format on
     if(!meta.empty()) {
       for(const auto& value: meta) {
+        // clang-format off
          d_SetDomainMetadataQuery_stmt->
            bind("kind", kind)->
            bind("content", value)->
            bind("domain", name)->
            execute()->
            reset();
+        // clang-format on
       }
     }
   }
@@ -1335,30 +1402,38 @@ void GSQLBackend::lookup(const QType& qtype, const DNSName& qname, int domain_id
       if(domain_id < 0) {
         d_query_name = "basic-query";
         d_query_stmt = &d_NoIdQuery_stmt;
+        // clang-format off
         (*d_query_stmt)->
           bind("qtype", qtype.toString())->
           bind("qname", qname);
+        // clang-format on
       } else {
         d_query_name = "id-query";
         d_query_stmt = &d_IdQuery_stmt;
+        // clang-format off
         (*d_query_stmt)->
           bind("qtype", qtype.toString())->
           bind("qname", qname)->
           bind("domain_id", domain_id);
+        // clang-format on
       }
     } else {
       // qtype==ANY
       if(domain_id < 0) {
         d_query_name = "any-query";
         d_query_stmt = &d_ANYNoIdQuery_stmt;
+        // clang-format off
         (*d_query_stmt)->
           bind("qname", qname);
+        // clang-format on
       } else {
         d_query_name = "any-id-query";
         d_query_stmt = &d_ANYIdQuery_stmt;
+        // clang-format off
         (*d_query_stmt)->
           bind("qname", qname)->
           bind("domain_id", domain_id);
+        // clang-format on
       }
     }
 
@@ -1382,10 +1457,12 @@ bool GSQLBackend::list(const DNSName &target, int domain_id, bool include_disabl
 
     d_query_name = "list-query";
     d_query_stmt = &d_listQuery_stmt;
+    // clang-format off
     (*d_query_stmt)->
       bind("include_disabled", (int)include_disabled)->
       bind("domain_id", domain_id)->
       execute();
+    // clang-format on
   }
   catch(SSqlException &e) {
     throw PDNSException("GSQLBackend unable to list domain '" + target.toLogString() + "': "+e.txtReason());
@@ -1406,11 +1483,13 @@ bool GSQLBackend::listSubZone(const DNSName &zone, int domain_id) {
 
     d_query_name = "list-subzone-query";
     d_query_stmt = &d_listSubZoneQuery_stmt;
+    // clang-format off
     (*d_query_stmt)->
       bind("zone", zone)->
       bind("wildzone", wildzone)->
       bind("domain_id", domain_id)->
       execute();
+    // clang-format on
   }
   catch(SSqlException &e) {
     throw PDNSException("GSQLBackend unable to list SubZones for domain '" + zone.toLogString() + "': "+e.txtReason());
@@ -1457,18 +1536,19 @@ skiprow:
   return false;
 }
 
-bool GSQLBackend::superMasterAdd(const AutoPrimary& primary)
+bool GSQLBackend::autoPrimaryAdd(const AutoPrimary& primary)
 {
   try{
     reconnectIfNeeded();
 
-    d_AddSuperMaster_stmt ->
+    // clang-format off
+    d_AddAutoPrimary_stmt ->
       bind("ip",primary.ip)->
       bind("nameserver",primary.nameserver)->
       bind("account",primary.account)->
       execute()->
       reset();
-
+    // clang-format on
   }
   catch (SSqlException &e){
     throw PDNSException("GSQLBackend unable to insert an autoprimary with IP " + primary.ip + " and nameserver name '" + primary.nameserver + "' and account '" + primary.account + "': " + e.txtReason());
@@ -1482,12 +1562,13 @@ bool GSQLBackend::autoPrimaryRemove(const AutoPrimary& primary)
   try{
     reconnectIfNeeded();
 
+    // clang-format off
     d_RemoveAutoPrimary_stmt ->
       bind("ip",primary.ip)->
       bind("nameserver",primary.nameserver)->
       execute()->
       reset();
-
+    // clang-format on
   }
   catch (SSqlException &e){
     throw PDNSException("GSQLBackend unable to remove an autoprimary with IP " + primary.ip + " and nameserver name '" + primary.nameserver + "': " + e.txtReason());
@@ -1501,10 +1582,12 @@ bool GSQLBackend::autoPrimariesList(std::vector<AutoPrimary>& primaries)
   try{
     reconnectIfNeeded();
 
+    // clang-format off
     d_ListAutoPrimaries_stmt->
       execute()->
       getResult(d_result)->
       reset();
+    // clang-format on
   }
   catch (SSqlException &e){
      throw PDNSException("GSQLBackend unable to list autoprimaries: " + e.txtReason());
@@ -1518,25 +1601,27 @@ bool GSQLBackend::autoPrimariesList(std::vector<AutoPrimary>& primaries)
   return true;
 }
 
-bool GSQLBackend::superMasterBackend(const string &ip, const DNSName &domain, const vector<DNSResourceRecord>&nsset, string *nameserver, string *account, DNSBackend **ddb)
+bool GSQLBackend::autoPrimaryBackend(const string& ip, const DNSName& domain, const vector<DNSResourceRecord>& nsset, string* nameserver, string* account, DNSBackend** ddb)
 {
   // check if we know the ip/ns couple in the database
   for(const auto & i : nsset) {
     try {
       reconnectIfNeeded();
 
-      d_SuperMasterInfoQuery_stmt->
+      // clang-format off
+      d_AutoPrimaryInfoQuery_stmt->
         bind("ip", ip)->
         bind("nameserver", i.content)->
         execute()->
         getResult(d_result)->
         reset();
+      // clang-format on
     }
     catch (SSqlException &e) {
-      throw PDNSException("GSQLBackend unable to search for a supermaster with IP " + ip + " and nameserver name '" + i.content + "' for domain '" + domain.toLogString() + "': "+e.txtReason());
+      throw PDNSException("GSQLBackend unable to search for a autoprimary with IP " + ip + " and nameserver name '" + i.content + "' for domain '" + domain.toLogString() + "': " + e.txtReason());
     }
     if(!d_result.empty()) {
-      ASSERT_ROW_COLUMNS("supermaster-query", d_result[0], 1);
+      ASSERT_ROW_COLUMNS("autoprimary-query", d_result[0], 1);
       *nameserver=i.content;
       *account=d_result[0][0];
       *ddb=this;
@@ -1546,12 +1631,12 @@ bool GSQLBackend::superMasterBackend(const string &ip, const DNSName &domain, co
   return false;
 }
 
-bool GSQLBackend::createDomain(const DNSName& domain, const DomainInfo::DomainKind kind, const vector<ComboAddress>& masters, const string& account)
+bool GSQLBackend::createDomain(const DNSName& domain, const DomainInfo::DomainKind kind, const vector<ComboAddress>& primaries, const string& account)
 {
-  vector<string> masters_s;
-  masters_s.reserve(masters.size());
-  for (const auto& master : masters) {
-    masters_s.push_back(master.toStringWithPortExcept(53));
+  vector<string> primaries_s;
+  primaries_s.reserve(primaries.size());
+  for (const auto& primary : primaries) {
+    primaries_s.push_back(primary.toStringWithPortExcept(53));
   }
 
   try {
@@ -1561,7 +1646,7 @@ bool GSQLBackend::createDomain(const DNSName& domain, const DomainInfo::DomainKi
     d_InsertZoneQuery_stmt->
       bind("type", toUpper(DomainInfo::getKindString(kind)))->
       bind("domain", domain)->
-      bind("masters", boost::join(masters_s, ", "))->
+      bind("primaries", boost::join(primaries_s, ", "))->
       bind("account", account)->
       execute()->
       reset();
@@ -1573,21 +1658,23 @@ bool GSQLBackend::createDomain(const DNSName& domain, const DomainInfo::DomainKi
   return true;
 }
 
-bool GSQLBackend::createSlaveDomain(const string& ip, const DNSName& domain, const string& nameserver, const string& account)
+bool GSQLBackend::createSecondaryDomain(const string& ip, const DNSName& domain, const string& nameserver, const string& account)
 {
   string name;
-  vector<ComboAddress> masters({ComboAddress(ip, 53)});
+  vector<ComboAddress> primaries({ComboAddress(ip, 53)});
   try {
     if (!nameserver.empty()) {
-      // figure out all IP addresses for the master
+      // figure out all IP addresses for the primary
       reconnectIfNeeded();
 
-      d_GetSuperMasterIPs_stmt->
+      // clang-format off
+      d_GetAutoPrimaryIPs_stmt->
         bind("nameserver", nameserver)->
         bind("account", account)->
         execute()->
         getResult(d_result)->
         reset();
+      // clang-format on
       if (!d_result.empty()) {
         // collect all IP addresses
         vector<ComboAddress> tmp;
@@ -1595,14 +1682,14 @@ bool GSQLBackend::createSlaveDomain(const string& ip, const DNSName& domain, con
           if (account == row[1])
             tmp.emplace_back(row[0], 53);
         }
-        // set them as domain's masters, comma separated
-        masters = tmp;
+        // set them as domain's primaries, comma separated
+        primaries = tmp;
       }
     }
-    createDomain(domain, DomainInfo::Slave, masters, account);
+    createDomain(domain, DomainInfo::Secondary, primaries, account);
   }
   catch(SSqlException &e) {
-    throw PDNSException("Database error trying to insert new slave domain '"+domain.toLogString()+"': "+ e.txtReason());
+    throw PDNSException("Database error trying to insert new secondary domain '" + domain.toLogString() + "': " + e.txtReason());
   }
   return true;
 }
@@ -1621,6 +1708,7 @@ bool GSQLBackend::deleteDomain(const DNSName &domain)
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_DeleteZoneQuery_stmt->
       bind("domain_id", di.id)->
       execute()->
@@ -1641,6 +1729,7 @@ bool GSQLBackend::deleteDomain(const DNSName &domain)
       bind("domain", domain)->
       execute()->
       reset();
+    // clang-format on
   }
   catch(SSqlException &e) {
     throw PDNSException("Database error trying to delete domain '"+domain.toLogString()+"': "+ e.txtReason());
@@ -1655,9 +1744,11 @@ void GSQLBackend::getAllDomains(vector<DomainInfo>* domains, bool getSerial, boo
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_getAllDomainsQuery_stmt->
       bind("include_disabled", (int)include_disabled)->
       execute();
+    // clang-format on
 
     SSqlStatement::row_t row;
     while (d_getAllDomainsQuery_stmt->hasNextRow()) {
@@ -1672,9 +1763,9 @@ void GSQLBackend::getAllDomains(vector<DomainInfo>* domains, bool getSerial, boo
       }
 
       if (pdns_iequals(row[3], "MASTER")) {
-        di.kind = DomainInfo::Master;
+        di.kind = DomainInfo::Primary;
       } else if (pdns_iequals(row[3], "SLAVE")) {
-        di.kind = DomainInfo::Slave;
+        di.kind = DomainInfo::Secondary;
       } else if (pdns_iequals(row[3], "NATIVE")) {
         di.kind = DomainInfo::Native;
       }
@@ -1690,13 +1781,13 @@ void GSQLBackend::getAllDomains(vector<DomainInfo>* domains, bool getSerial, boo
       }
 
       if (!row[4].empty()) {
-        vector<string> masters;
-        stringtok(masters, row[4], " ,\t");
-        for(const auto& m : masters) {
+        vector<string> primaries;
+        stringtok(primaries, row[4], " ,\t");
+        for (const auto& m : primaries) {
           try {
-            di.masters.emplace_back(m, 53);
+            di.primaries.emplace_back(m, 53);
           } catch(const PDNSException &e) {
-            g_log<<Logger::Warning<<"Could not parse master address ("<<m<<") for zone '"<<di.zone<<"': "<<e.reason;
+            g_log << Logger::Warning << "Could not parse primary address (" << m << ") for zone '" << di.zone << "': " << e.reason;
           }
         }
       }
@@ -1743,25 +1834,31 @@ bool GSQLBackend::replaceRRSet(uint32_t domain_id, const DNSName& qname, const Q
 
     if (qt != QType::ANY) {
       if (d_upgradeContent) {
+        // clang-format off
         d_DeleteRRSetQuery_stmt->
           bind("domain_id", domain_id)->
           bind("qname", qname)->
           bind("qtype", "TYPE"+std::to_string(qt.getCode()))->
           execute()->
           reset();
+        // clang-format on
       }
+      // clang-format off
       d_DeleteRRSetQuery_stmt->
         bind("domain_id", domain_id)->
         bind("qname", qname)->
         bind("qtype", qt.toString())->
         execute()->
         reset();
+      // clang-format on
     } else {
+      // clang-format off
       d_DeleteNamesQuery_stmt->
         bind("domain_id", domain_id)->
         bind("qname", qname)->
         execute()->
         reset();
+      // clang-format on
     }
   }
   catch (SSqlException &e) {
@@ -1772,12 +1869,14 @@ bool GSQLBackend::replaceRRSet(uint32_t domain_id, const DNSName& qname, const Q
     try {
       reconnectIfNeeded();
 
+      // clang-format off
       d_DeleteCommentRRsetQuery_stmt->
         bind("domain_id", domain_id)->
         bind("qname", qname)->
         bind("qtype", qt.toString())->
         execute()->
         reset();
+      // clang-format on
     }
     catch (SSqlException &e) {
       throw PDNSException("GSQLBackend unable to delete comment for RRSet " + qname.toLogString() + "|" + qt.toString() + ": "+e.txtReason());
@@ -1806,14 +1905,16 @@ bool GSQLBackend::feedRecord(const DNSResourceRecord& r, const DNSName& ordernam
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_InsertRecordQuery_stmt->
-      bind("content",content)->
-      bind("ttl",r.ttl)->
-      bind("priority",prio)->
-      bind("qtype",r.qtype.toString())->
-      bind("domain_id",r.domain_id)->
-      bind("disabled",r.disabled)->
-      bind("qname",r.qname);
+      bind("content", content)->
+      bind("ttl", r.ttl)->
+      bind("priority", prio)->
+      bind("qtype", r.qtype.toString())->
+      bind("domain_id", r.domain_id)->
+      bind("disabled", r.disabled)->
+      bind("qname", r.qname);
+    // clang-format on
 
     if (!ordername.empty())
       d_InsertRecordQuery_stmt->bind("ordername", ordername.labelReverse().makeLowerCase().toString(" ", false));
@@ -1841,13 +1942,15 @@ bool GSQLBackend::feedEnts(int domain_id, map<DNSName,bool>& nonterm)
     try {
       reconnectIfNeeded();
 
+      // clang-format off
       d_InsertEmptyNonTerminalOrderQuery_stmt->
-        bind("domain_id",domain_id)->
+        bind("domain_id", domain_id)->
         bind("qname", nt.first)->
         bindNull("ordername")->
-        bind("auth",(nt.second || !d_dnssecQueries))->
+        bind("auth", (nt.second || !d_dnssecQueries))->
         execute()->
         reset();
+      // clang-format on
     }
     catch (SSqlException &e) {
       throw PDNSException("GSQLBackend unable to feed empty non-terminal with name '" + nt.first.toLogString() + "': "+e.txtReason());
@@ -1867,21 +1970,29 @@ bool GSQLBackend::feedEnts3(int domain_id, const DNSName& /* domain */, map<DNSN
     try {
       reconnectIfNeeded();
 
+      // clang-format off
       d_InsertEmptyNonTerminalOrderQuery_stmt->
-        bind("domain_id",domain_id)->
+        bind("domain_id", domain_id)->
         bind("qname", nt.first);
+      // clang-format on
       if (narrow || !nt.second) {
+        // clang-format off
         d_InsertEmptyNonTerminalOrderQuery_stmt->
           bindNull("ordername");
+        // clang-format on
       } else {
         ordername=toBase32Hex(hashQNameWithSalt(ns3prc, nt.first));
+        // clang-format off
         d_InsertEmptyNonTerminalOrderQuery_stmt->
           bind("ordername", ordername);
+        // clang-format on
       }
+      // clang-format off
       d_InsertEmptyNonTerminalOrderQuery_stmt->
-        bind("auth",nt.second)->
+        bind("auth", nt.second)->
         execute()->
         reset();
+      // clang-format on
     }
     catch (SSqlException &e) {
       throw PDNSException("GSQLBackend unable to feed empty non-terminal with name '" + nt.first.toLogString() + "' (hashed name '"+ toBase32Hex(hashQNameWithSalt(ns3prc, nt.first)) + "') : "+e.txtReason());
@@ -1901,10 +2012,12 @@ bool GSQLBackend::startTransaction(const DNSName &domain, int domain_id)
     d_db->startTransaction();
     d_inTransaction = true;
     if(domain_id >= 0) {
+      // clang-format off
       d_DeleteZoneQuery_stmt->
         bind("domain_id", domain_id)->
         execute()->
         reset();
+      // clang-format on
     }
   }
   catch (SSqlException &e) {
@@ -1948,9 +2061,11 @@ bool GSQLBackend::listComments(const uint32_t domain_id)
 
     d_query_name = "list-comments-query";
     d_query_stmt = &d_ListCommentsQuery_stmt;
+    // clang-format off
     (*d_query_stmt)->
       bind("domain_id", domain_id)->
       execute();
+    // clang-format on
   }
   catch(SSqlException &e) {
     throw PDNSException("GSQLBackend unable to list comments for domain id " + std::to_string(domain_id) + ": "+e.txtReason());
@@ -1994,15 +2109,17 @@ bool GSQLBackend::feedComment(const Comment& comment)
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_InsertCommentQuery_stmt->
-      bind("domain_id",comment.domain_id)->
-      bind("qname",comment.qname)->
-      bind("qtype",comment.qtype.toString())->
-      bind("modified_at",comment.modified_at)->
-      bind("account",comment.account)->
-      bind("content",comment.content)->
+      bind("domain_id", comment.domain_id)->
+      bind("qname", comment.qname)->
+      bind("qtype", comment.qtype.toString())->
+      bind("modified_at", comment.modified_at)->
+      bind("account", comment.account)->
+      bind("content", comment.content)->
       execute()->
       reset();
+    // clang-format on
   }
   catch (SSqlException &e) {
     throw PDNSException("GSQLBackend unable to feed comment for RRSet '" + comment.qname.toLogString() + "|" + comment.qtype.toString() + "': "+e.txtReason());
@@ -2020,12 +2137,14 @@ bool GSQLBackend::replaceComments(const uint32_t domain_id, const DNSName& qname
       throw PDNSException("replaceComments called outside of transaction");
     }
 
+    // clang-format off
     d_DeleteCommentRRsetQuery_stmt->
-      bind("domain_id",domain_id)->
+      bind("domain_id", domain_id)->
       bind("qname", qname)->
-      bind("qtype",qt.toString())->
+      bind("qtype", qt.toString())->
       execute()->
       reset();
+    // clang-format on
   }
   catch (SSqlException &e) {
     throw PDNSException("GSQLBackend unable to delete comment for RRSet '" + qname.toLogString() + "|" + qt.toString() + "': "+e.txtReason());
@@ -2075,18 +2194,20 @@ string GSQLBackend::pattern2SQLPattern(const string &pattern)
   return escaped_pattern;
 }
 
-bool GSQLBackend::searchRecords(const string &pattern, int maxResults, vector<DNSResourceRecord>& result)
+bool GSQLBackend::searchRecords(const string &pattern, size_t maxResults, vector<DNSResourceRecord>& result)
 {
   d_qname.clear();
   string escaped_pattern = pattern2SQLPattern(pattern);
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_SearchRecordsQuery_stmt->
       bind("value", escaped_pattern)->
       bind("value2", escaped_pattern)->
       bind("limit", maxResults)->
       execute();
+    // clang-format on
 
     while(d_SearchRecordsQuery_stmt->hasNextRow())
     {
@@ -2111,18 +2232,20 @@ bool GSQLBackend::searchRecords(const string &pattern, int maxResults, vector<DN
   }
 }
 
-bool GSQLBackend::searchComments(const string &pattern, int maxResults, vector<Comment>& result)
+bool GSQLBackend::searchComments(const string &pattern, size_t maxResults, vector<Comment>& result)
 {
   Comment c;
   string escaped_pattern = pattern2SQLPattern(pattern);
   try {
     reconnectIfNeeded();
 
+    // clang-format off
     d_SearchCommentsQuery_stmt->
       bind("value", escaped_pattern)->
       bind("value2", escaped_pattern)->
       bind("limit", maxResults)->
       execute();
+    // clang-format on
 
     while(d_SearchCommentsQuery_stmt->hasNextRow()) {
       SSqlStatement::row_t row;
index 9ba76db92d0b0bada136ee77b43ab694c726ada9..51f1da599e4ba8ce2ebc925c007c7cbbb0ac6573 100644 (file)
@@ -29,7 +29,7 @@
 
 bool isDnssecDomainMetadata (const string& name);
 
-/* 
+/*
 GSQLBackend is a generic backend used by other sql backends
 */
 class GSQLBackend : public DNSBackend
@@ -41,7 +41,7 @@ public:
     freeStatements();
     d_db.reset();
   }
-  
+
   void setDB(SSql *db)
   {
     freeStatements();
@@ -61,25 +61,25 @@ protected:
       d_ANYIdQuery_stmt = d_db->prepare(d_ANYIdQuery, 2);
       d_listQuery_stmt = d_db->prepare(d_listQuery, 2);
       d_listSubZoneQuery_stmt = d_db->prepare(d_listSubZoneQuery, 3);
-      d_MasterOfDomainsZoneQuery_stmt = d_db->prepare(d_MasterOfDomainsZoneQuery, 1);
+      d_PrimaryOfDomainsZoneQuery_stmt = d_db->prepare(d_PrimaryOfDomainsZoneQuery, 1);
       d_InfoOfDomainsZoneQuery_stmt = d_db->prepare(d_InfoOfDomainsZoneQuery, 1);
-      d_InfoOfAllSlaveDomainsQuery_stmt = d_db->prepare(d_InfoOfAllSlaveDomainsQuery, 0);
-      d_SuperMasterInfoQuery_stmt = d_db->prepare(d_SuperMasterInfoQuery, 2);
-      d_GetSuperMasterIPs_stmt = d_db->prepare(d_GetSuperMasterIPs, 2);
-      d_AddSuperMaster_stmt = d_db->prepare(d_AddSuperMaster, 3); 
+      d_InfoOfAllSecondaryDomainsQuery_stmt = d_db->prepare(d_InfoOfAllSecondaryDomainsQuery, 0);
+      d_AutoPrimaryInfoQuery_stmt = d_db->prepare(d_AutoPrimaryInfoQuery, 2);
+      d_GetAutoPrimaryIPs_stmt = d_db->prepare(d_GetAutoPrimaryIPs, 2);
+      d_AddAutoPrimary_stmt = d_db->prepare(d_AddAutoPrimary, 3);
       d_RemoveAutoPrimary_stmt = d_db->prepare(d_RemoveAutoPrimaryQuery, 2);
       d_ListAutoPrimaries_stmt = d_db->prepare(d_ListAutoPrimariesQuery, 0);
       d_InsertZoneQuery_stmt = d_db->prepare(d_InsertZoneQuery, 4);
       d_InsertRecordQuery_stmt = d_db->prepare(d_InsertRecordQuery, 9);
       d_InsertEmptyNonTerminalOrderQuery_stmt = d_db->prepare(d_InsertEmptyNonTerminalOrderQuery, 4);
-      d_UpdateMasterOfZoneQuery_stmt = d_db->prepare(d_UpdateMasterOfZoneQuery, 2);
+      d_UpdatePrimaryOfZoneQuery_stmt = d_db->prepare(d_UpdatePrimaryOfZoneQuery, 2);
       d_UpdateKindOfZoneQuery_stmt = d_db->prepare(d_UpdateKindOfZoneQuery, 2);
       d_UpdateOptionsOfZoneQuery_stmt = d_db->prepare(d_UpdateOptionsOfZoneQuery, 2);
       d_UpdateCatalogOfZoneQuery_stmt = d_db->prepare(d_UpdateCatalogOfZoneQuery, 2);
       d_UpdateAccountOfZoneQuery_stmt = d_db->prepare(d_UpdateAccountOfZoneQuery, 2);
       d_UpdateSerialOfZoneQuery_stmt = d_db->prepare(d_UpdateSerialOfZoneQuery, 2);
       d_UpdateLastCheckOfZoneQuery_stmt = d_db->prepare(d_UpdateLastCheckOfZoneQuery, 2);
-      d_InfoOfAllMasterDomainsQuery_stmt = d_db->prepare(d_InfoOfAllMasterDomainsQuery, 0);
+      d_InfoOfAllPrimaryDomainsQuery_stmt = d_db->prepare(d_InfoOfAllPrimaryDomainsQuery, 0);
       d_InfoProducerMembersQuery_stmt = d_db->prepare(d_InfoProducerMembersQuery, 1);
       d_InfoConsumerMembersQuery_stmt = d_db->prepare(d_InfoConsumerMembersQuery, 1);
       d_DeleteDomainQuery_stmt = d_db->prepare(d_DeleteDomainQuery, 1);
@@ -131,25 +131,25 @@ protected:
     d_ANYIdQuery_stmt.reset();
     d_listQuery_stmt.reset();
     d_listSubZoneQuery_stmt.reset();
-    d_MasterOfDomainsZoneQuery_stmt.reset();
+    d_PrimaryOfDomainsZoneQuery_stmt.reset();
     d_InfoOfDomainsZoneQuery_stmt.reset();
-    d_InfoOfAllSlaveDomainsQuery_stmt.reset();
-    d_SuperMasterInfoQuery_stmt.reset();
-    d_GetSuperMasterIPs_stmt.reset();
-    d_AddSuperMaster_stmt.reset();
+    d_InfoOfAllSecondaryDomainsQuery_stmt.reset();
+    d_AutoPrimaryInfoQuery_stmt.reset();
+    d_GetAutoPrimaryIPs_stmt.reset();
+    d_AddAutoPrimary_stmt.reset();
     d_RemoveAutoPrimary_stmt.reset();
     d_ListAutoPrimaries_stmt.reset();
     d_InsertZoneQuery_stmt.reset();
     d_InsertRecordQuery_stmt.reset();
     d_InsertEmptyNonTerminalOrderQuery_stmt.reset();
-    d_UpdateMasterOfZoneQuery_stmt.reset();
+    d_UpdatePrimaryOfZoneQuery_stmt.reset();
     d_UpdateKindOfZoneQuery_stmt.reset();
     d_UpdateOptionsOfZoneQuery_stmt.reset();
     d_UpdateCatalogOfZoneQuery_stmt.reset();
     d_UpdateAccountOfZoneQuery_stmt.reset();
     d_UpdateSerialOfZoneQuery_stmt.reset();
     d_UpdateLastCheckOfZoneQuery_stmt.reset();
-    d_InfoOfAllMasterDomainsQuery_stmt.reset();
+    d_InfoOfAllPrimaryDomainsQuery_stmt.reset();
     d_InfoProducerMembersQuery_stmt.reset();
     d_InfoConsumerMembersQuery_stmt.reset();
     d_DeleteDomainQuery_stmt.reset();
@@ -204,21 +204,21 @@ public:
   bool feedRecord(const DNSResourceRecord &r, const DNSName &ordername, bool ordernameIsNSEC3=false) override;
   bool feedEnts(int domain_id, map<DNSName,bool>& nonterm) override;
   bool feedEnts3(int domain_id, const DNSName &domain, map<DNSName,bool> &nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) override;
-  bool createDomain(const DNSName& domain, const DomainInfo::DomainKind kind, const vector<ComboAddress>& masters, const string& account) override;
-  bool createSlaveDomain(const string& ip, const DNSName& domain, const string& nameserver, const string& account) override;
+  bool createDomain(const DNSName& domain, const DomainInfo::DomainKind kind, const vector<ComboAddress>& primaries, const string& account) override;
+  bool createSecondaryDomain(const string& ip, const DNSName& domain, const string& nameserver, const string& account) override;
   bool deleteDomain(const DNSName &domain) override;
-  bool superMasterAdd(const AutoPrimary& primary) override;
+  bool autoPrimaryAdd(const AutoPrimary& primary) override;
   bool autoPrimaryRemove(const AutoPrimary& primary) override;
   bool autoPrimariesList(std::vector<AutoPrimary>& primaries) override;
-  bool superMasterBackend(const string &ip, const DNSName &domain, const vector<DNSResourceRecord>&nsset, string *nameserver, string *account, DNSBackend **db) override;
+  bool autoPrimaryBackend(const string& ip, const DNSName& domain, const vector<DNSResourceRecord>& nsset, string* nameserver, string* account, DNSBackend** db) override;
   void setStale(uint32_t domain_id) override;
   void setFresh(uint32_t domain_id) override;
-  void getUnfreshSlaveInfos(vector<DomainInfo> *domains) override;
-  void getUpdatedMasters(vector<DomainInfo>& updatedDomains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes) override;
+  void getUnfreshSecondaryInfos(vector<DomainInfo>* domains) override;
+  void getUpdatedPrimaries(vector<DomainInfo>& updatedDomains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes) override;
   bool getCatalogMembers(const DNSName& catalog, vector<CatalogInfo>& members, CatalogInfo::CatalogType type) override;
   bool getDomainInfo(const DNSName &domain, DomainInfo &di, bool getSerial=true) override;
   void setNotified(uint32_t domain_id, uint32_t serial) override;
-  bool setMasters(const DNSName &domain, const vector<ComboAddress> &masters) override;
+  bool setPrimaries(const DNSName& domain, const vector<ComboAddress>& primaries) override;
   bool setKind(const DNSName &domain, const DomainInfo::DomainKind kind) override;
   bool setOptions(const DNSName& domain, const string& options) override;
   bool setCatalog(const DNSName& domain, const DNSName& catalog) override;
@@ -237,7 +237,7 @@ public:
   bool getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string> >& meta) override;
   bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector<std::string>& meta) override;
   bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector<std::string>& meta) override;
-  
+
   bool removeDomainKey(const DNSName& name, unsigned int id) override;
   bool activateDomainKey(const DNSName& name, unsigned int id) override;
   bool deactivateDomainKey(const DNSName& name, unsigned int id) override;
@@ -254,8 +254,8 @@ public:
   bool feedComment(const Comment& comment) override;
   bool replaceComments(const uint32_t domain_id, const DNSName& qname, const QType& qt, const vector<Comment>& comments) override;
   string directBackendCmd(const string &query) override;
-  bool searchRecords(const string &pattern, int maxResults, vector<DNSResourceRecord>& result) override;
-  bool searchComments(const string &pattern, int maxResults, vector<Comment>& result) override;
+  bool searchRecords(const string &pattern, size_t maxResults, vector<DNSResourceRecord>& result) override;
+  bool searchComments(const string &pattern, size_t maxResults, vector<Comment>& result) override;
 
 protected:
   string pattern2SQLPattern(const string& pattern);
@@ -298,27 +298,27 @@ private:
   string d_listSubZoneQuery;
   string d_logprefix;
 
-  string d_MasterOfDomainsZoneQuery;
+  string d_PrimaryOfDomainsZoneQuery;
   string d_InfoOfDomainsZoneQuery;
-  string d_InfoOfAllSlaveDomainsQuery;
-  string d_SuperMasterInfoQuery;
-  string d_GetSuperMasterName;
-  string d_GetSuperMasterIPs;
-  string d_AddSuperMaster;
+  string d_InfoOfAllSecondaryDomainsQuery;
+  string d_AutoPrimaryInfoQuery;
+  string d_GetAutoPrimaryName;
+  string d_GetAutoPrimaryIPs;
+  string d_AddAutoPrimary;
   string d_RemoveAutoPrimaryQuery;
   string d_ListAutoPrimariesQuery;
 
   string d_InsertZoneQuery;
   string d_InsertRecordQuery;
   string d_InsertEmptyNonTerminalOrderQuery;
-  string d_UpdateMasterOfZoneQuery;
+  string d_UpdatePrimaryOfZoneQuery;
   string d_UpdateKindOfZoneQuery;
   string d_UpdateOptionsOfZoneQuery;
   string d_UpdateCatalogOfZoneQuery;
   string d_UpdateAccountOfZoneQuery;
   string d_UpdateSerialOfZoneQuery;
   string d_UpdateLastCheckOfZoneQuery;
-  string d_InfoOfAllMasterDomainsQuery;
+  string d_InfoOfAllPrimaryDomainsQuery;
   string d_InfoProducerMembersQuery;
   string d_InfoConsumerMembersQuery;
   string d_DeleteDomainQuery;
@@ -377,25 +377,25 @@ private:
   unique_ptr<SSqlStatement> d_ANYIdQuery_stmt;
   unique_ptr<SSqlStatement> d_listQuery_stmt;
   unique_ptr<SSqlStatement> d_listSubZoneQuery_stmt;
-  unique_ptr<SSqlStatement> d_MasterOfDomainsZoneQuery_stmt;
+  unique_ptr<SSqlStatement> d_PrimaryOfDomainsZoneQuery_stmt;
   unique_ptr<SSqlStatement> d_InfoOfDomainsZoneQuery_stmt;
-  unique_ptr<SSqlStatement> d_InfoOfAllSlaveDomainsQuery_stmt;
-  unique_ptr<SSqlStatement> d_SuperMasterInfoQuery_stmt;
-  unique_ptr<SSqlStatement> d_GetSuperMasterIPs_stmt;
-  unique_ptr<SSqlStatement> d_AddSuperMaster_stmt;
+  unique_ptr<SSqlStatement> d_InfoOfAllSecondaryDomainsQuery_stmt;
+  unique_ptr<SSqlStatement> d_AutoPrimaryInfoQuery_stmt;
+  unique_ptr<SSqlStatement> d_GetAutoPrimaryIPs_stmt;
+  unique_ptr<SSqlStatement> d_AddAutoPrimary_stmt;
   unique_ptr<SSqlStatement> d_RemoveAutoPrimary_stmt;
   unique_ptr<SSqlStatement> d_ListAutoPrimaries_stmt;
   unique_ptr<SSqlStatement> d_InsertZoneQuery_stmt;
   unique_ptr<SSqlStatement> d_InsertRecordQuery_stmt;
   unique_ptr<SSqlStatement> d_InsertEmptyNonTerminalOrderQuery_stmt;
-  unique_ptr<SSqlStatement> d_UpdateMasterOfZoneQuery_stmt;
+  unique_ptr<SSqlStatement> d_UpdatePrimaryOfZoneQuery_stmt;
   unique_ptr<SSqlStatement> d_UpdateKindOfZoneQuery_stmt;
   unique_ptr<SSqlStatement> d_UpdateOptionsOfZoneQuery_stmt;
   unique_ptr<SSqlStatement> d_UpdateCatalogOfZoneQuery_stmt;
   unique_ptr<SSqlStatement> d_UpdateAccountOfZoneQuery_stmt;
   unique_ptr<SSqlStatement> d_UpdateSerialOfZoneQuery_stmt;
   unique_ptr<SSqlStatement> d_UpdateLastCheckOfZoneQuery_stmt;
-  unique_ptr<SSqlStatement> d_InfoOfAllMasterDomainsQuery_stmt;
+  unique_ptr<SSqlStatement> d_InfoOfAllPrimaryDomainsQuery_stmt;
   unique_ptr<SSqlStatement> d_InfoProducerMembersQuery_stmt;
   unique_ptr<SSqlStatement> d_InfoConsumerMembersQuery_stmt;
   unique_ptr<SSqlStatement> d_DeleteDomainQuery_stmt;
index 9f6ba81fe61b33d21eae0f94d20faff2becfd909..179ca457617a39bbab6ea3aa1640ad5ac08a14ff 100644 (file)
@@ -258,7 +258,7 @@ primaries: /* empty */
 
 primary: AWORD
        {
-               s_di.masters.push_back(ComboAddress($1, 53));
+               s_di.primaries.push_back(ComboAddress($1, 53));
                free($1);
        }
        ;
index b47d2382740391d77614dda78d57f99c5e83192e..1063de98ecb2216bd9e4ee8a7095ba9822dd1301 100644 (file)
@@ -39,7 +39,7 @@ public:
   {
     name=DNSName();
     filename=type="";
-    masters.clear();
+    primaries.clear();
     alsoNotify.clear();
     d_dev=0;
     d_ino=0;
@@ -47,7 +47,7 @@ public:
   DNSName name;
   string viewName;
   string filename;
-  vector<ComboAddress> masters;
+  vector<ComboAddress> primaries;
   set<string> alsoNotify;
   string type;
   bool hadFileDirective;
index fa45ca5736c42034ba1537155d0407d623aa3eed..aaf798152aa335392d273265b0ce80f89663493f 100644 (file)
@@ -130,8 +130,8 @@ uint64_t pruneLockedCollectionsVector(std::vector<T>& maps)
   return totErased;
 }
 
-template <typename S, typename C, typename T>
-uint64_t pruneMutexCollectionsVector(time_t now, C& container, std::vector<T>& maps, uint64_t maxCached, uint64_t cacheSize)
+template <typename S, typename T>
+uint64_t pruneMutexCollectionsVector(time_t now, std::vector<T>& maps, uint64_t maxCached, uint64_t cacheSize)
 {
   uint64_t totErased = 0;
   uint64_t toTrim = 0;
@@ -163,7 +163,7 @@ uint64_t pruneMutexCollectionsVector(time_t now, C& container, std::vector<T>& m
     uint64_t lookedAt = 0;
     for (auto i = sidx.begin(); i != sidx.end(); lookedAt++) {
       if (i->isStale(now)) {
-        container.preRemoval(*shard, *i);
+        shard->preRemoval(*i);
         i = sidx.erase(i);
         erased++;
         content.decEntriesCount();
@@ -223,7 +223,7 @@ uint64_t pruneMutexCollectionsVector(time_t now, C& container, std::vector<T>& m
     auto& sidx = boost::multi_index::get<S>(shard->d_map);
     size_t removed = 0;
     for (auto i = sidx.begin(); i != sidx.end() && removed < toTrimForThisShard; removed++) {
-      container.preRemoval(*shard, *i);
+      shard->preRemoval(*i);
       i = sidx.erase(i);
       content.decEntriesCount();
       ++totErased;
index bbe23eef6a3a5ce1e8ea3434d008ee41163b88db..20cadfd7bfbc2ae7f895656d84cf8925378df38d 100644 (file)
@@ -60,7 +60,7 @@ void CommunicatorClass::retrievalLoopThread()
         data->d_sorthelper = 0;
       }
     }
-    suck(sr.domain, sr.master, sr.force);
+    suck(sr.domain, sr.primary, sr.force);
   }
 }
 
@@ -129,8 +129,8 @@ void CommunicatorClass::mainloop()
     makeNotifySockets();
 
     for(;;) {
-      slaveRefresh(&P);
-      masterUpdateCheck(&P);
+      secondaryRefresh(&P);
+      primaryUpdateCheck(&P);
       doNotifications(&P); // this processes any notification acknowledgements and actually send out our own notifications
 
       next = time(nullptr) + d_tickinterval;
@@ -139,16 +139,16 @@ void CommunicatorClass::mainloop()
         rc=d_any_sem.tryWait();
 
         if(rc) {
-          bool extraSlaveRefresh = false;
+          bool extraSecondaryRefresh = false;
           Utility::sleep(1);
           {
             auto data = d_data.lock();
             if (data->d_tocheck.size()) {
-              extraSlaveRefresh = true;
+              extraSecondaryRefresh = true;
             }
           }
-          if (extraSlaveRefresh)
-            slaveRefresh(&P);
+          if (extraSecondaryRefresh)
+            secondaryRefresh(&P);
         }
         else {
           // eat up extra posts to avoid busy looping if many posts were done
index 9cd12fcbea03cd5e75a51fde9837975945916cbc..20ac6c572348cc8dce0386b9341a0d8baeaacb37 100644 (file)
@@ -44,13 +44,13 @@ using namespace boost::multi_index;
 struct SuckRequest
 {
   DNSName domain;
-  ComboAddress master;
+  ComboAddress primary;
   bool force;
   enum RequestPriority : uint8_t { PdnsControl, Api, Notify, SerialRefresh, SignaturesRefresh };
   std::pair<RequestPriority, uint64_t> priorityAndOrder;
   bool operator<(const SuckRequest& b) const
   {
-    return std::tie(domain, master) < std::tie(b.domain, b.master);
+    return std::tie(domain, primary) < std::tie(b.domain, b.primary);
   }
 };
 
@@ -150,7 +150,7 @@ public:
   CommunicatorClass()
   {
     d_tickinterval=60;
-    d_slaveschanged = true;
+    d_secondarieschanged = true;
     d_nsock4 = -1;
     d_nsock6 = -1;
     d_preventSelfNotification = false;
@@ -161,9 +161,9 @@ public:
 
   void drillHole(const DNSName &domain, const string &ip);
   bool justNotified(const DNSName &domain, const string &ip);
-  void addSuckRequest(const DNSName &domain, const ComboAddress& master, SuckRequest::RequestPriority, bool force=false);
-  void addSlaveCheckRequest(const DomainInfo& di, const ComboAddress& remote);
-  void addTrySuperMasterRequest(const DNSPacket& p);
+  void addSuckRequest(const DNSName& domain, const ComboAddress& primary, SuckRequest::RequestPriority, bool force = false);
+  void addSecondaryCheckRequest(const DomainInfo& di, const ComboAddress& remote);
+  void addTryAutoPrimaryRequest(const DNSPacket& p);
   void notify(const DNSName &domain, const string &ip);
   void mainloop();
   void retrievalLoopThread();
@@ -181,8 +181,8 @@ private:
   void suck(const DNSName &domain, const ComboAddress& remote, bool force=false);
   void ixfrSuck(const DNSName& domain, const TSIGTriplet& tt, const ComboAddress& laddr, const ComboAddress& remote, ZoneStatus& zs, vector<DNSRecord>* axfr);
 
-  void slaveRefresh(PacketHandler *P);
-  void masterUpdateCheck(PacketHandler *P);
+  void secondaryRefresh(PacketHandler* P);
+  void primaryUpdateCheck(PacketHandler* P);
   void getUpdatedProducers(UeberBackend* B, vector<DomainInfo>& domains, const std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes);
 
   Semaphore d_suck_sem;
@@ -193,7 +193,7 @@ private:
   NotificationQueue d_nq;
 
   time_t d_tickinterval;
-  bool d_slaveschanged;
+  bool d_secondarieschanged;
   bool d_preventSelfNotification;
 
   struct Data
@@ -209,12 +209,12 @@ private:
       };
     };
 
-    std::set<DNSPacket, cmp> d_potentialsupermasters;
+    std::set<DNSPacket, cmp> d_potentialautoprimaries;
 
     // Used to keep some state on domains that failed their freshness checks.
     // uint64_t == counter of the number of failures (increased by 1 every consecutive slave-cycle-interval that the domain fails)
     // time_t == wait at least until this time before attempting a new check
-    map<DNSName, pair<uint64_t, time_t> > d_failedSlaveRefresh;
+    map<DNSName, pair<uint64_t, time_t>> d_failedSecondaryRefresh;
   };
 
   LockGuarded<Data> d_data;
index 514025292961af0acc2b4cd4f91a85d3db63f178..717b00bda2f6fc5ce3b723ad141582a43f36ac30 100644 (file)
@@ -668,13 +668,13 @@ bool DNSSECKeeper::TSIGGrantsAccess(const DNSName& zone, const DNSName& keyname)
   return false;
 }
 
-bool DNSSECKeeper::getTSIGForAccess(const DNSName& zone, const ComboAddress& /* master */, DNSName* keyname)
+bool DNSSECKeeper::getTSIGForAccess(const DNSName& zone, const ComboAddress& /* primary */, DNSName* keyname)
 {
   vector<string> keynames;
   d_keymetadb->getDomainMetadata(zone, "AXFR-MASTER-TSIG", keynames);
   keyname->trimToLabels(0);
 
-  // XXX FIXME this should check for a specific master!
+  // XXX FIXME this should check for a specific primary!
   for(const string& dbkey :  keynames) {
     *keyname=DNSName(dbkey);
     return true;
index 066c7c4381b468ae9943b38368f867f5604aad14..83dbf2cf9daec0840fb3fef1028370778991b785 100644 (file)
@@ -48,7 +48,7 @@ public:
 class Opcode
 {
 public:
-  enum { Query=0, IQuery=1, Status=2, Notify=4, Update=5 };
+  enum opcodes_ : uint8_t { Query=0, IQuery=1, Status=2, Notify=4, Update=5 };
   static std::string to_s(uint8_t opcode);
 };
 
index aef1b99a3a3bbea2b95a6d875ce5c581ae286fd1..6b9340f56b3a00b5d55259e937bde6e410405a6a 100644 (file)
@@ -19,6 +19,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
+#include <memory>
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -112,19 +113,22 @@ vector<string> BackendMakerClass::getModules()
 void BackendMakerClass::load_all()
 {
   // TODO: Implement this?
-  DIR *dir=opendir(arg()["module-dir"].c_str());
-  if(!dir) {
+  auto dir = std::unique_ptr<DIR, decltype(&closedir)>(opendir(arg()["module-dir"].c_str()), closedir);
+  if (!dir) {
     g_log<<Logger::Error<<"Unable to open module directory '"<<arg()["module-dir"]<<"'"<<endl;
     return;
   }
-  struct dirent *entry;
-  while((entry=readdir(dir))) {
-    if(!strncmp(entry->d_name,"lib",3) &&
-       strlen(entry->d_name)>13 &&
-       !strcmp(entry->d_name+strlen(entry->d_name)-10,"backend.so"))
+  struct dirent* entry = nullptr;
+  // NOLINTNEXTLINE(concurrency-mt-unsafe): readdir is thread-safe nowadays and readdir_r is deprecated
+  while ((entry = readdir(dir.get())) != nullptr) {
+    // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay): this is what dirent is
+    auto name = std::string_view(entry->d_name, strlen(entry->d_name));
+    if (boost::starts_with(name, "lib") &&
+        name.size() > 13 &&
+        boost::ends_with(name, "backend.so")) {
       load(entry->d_name);
+    }
   }
-  closedir(dir);
 }
 
 void BackendMakerClass::load(const string &module)
@@ -180,12 +184,13 @@ size_t BackendMakerClass::numLauncheable() const
   return d_instances.size();
 }
 
-vector<DNSBackend *> BackendMakerClass::all(bool metadataOnly)
+vector<std::unique_ptr<DNSBackend>> BackendMakerClass::all(bool metadataOnly)
 {
-  vector<DNSBackend *> ret;
-  if(d_instances.empty())
+  if(d_instances.empty()) {
     throw PDNSException("No database backends configured for launch, unable to function");
+  }
 
+  vector<unique_ptr<DNSBackend>> ret;
   ret.reserve(d_instances.size());
 
   std::string current; // to make the exception text more useful
@@ -193,35 +198,23 @@ vector<DNSBackend *> BackendMakerClass::all(bool metadataOnly)
   try {
     for (const auto& instance : d_instances) {
       current = instance.first + instance.second;
-      DNSBackend *made = nullptr;
-
-      if (metadataOnly) {
-        made = d_repository[instance.first]->makeMetadataOnly(instance.second);
-      }
-      else {
-        made = d_repository[instance.first]->make(instance.second);
-      }
-
-      if (!made) {
+      auto* repo = d_repository[instance.first];
+      std::unique_ptr<DNSBackend> made{metadataOnly ? repo->makeMetadataOnly(instance.second) : repo->make(instance.second)};
+      if (made == nullptr) {
         throw PDNSException("Unable to launch backend '" + instance.first + "'");
       }
-
-      ret.push_back(made);
+      ret.push_back(std::move(made));
     }
   }
   catch(const PDNSException &ae) {
-    g_log<<Logger::Error<<"Caught an exception instantiating a backend (" << current << "): "<<ae.reason<<endl;
-    g_log<<Logger::Error<<"Cleaning up"<<endl;
-    for (auto i : ret) {
-      delete i;
-    }
+    g_log << Logger::Error << "Caught an exception instantiating a backend (" << current << "): " << ae.reason << endl;
+    g_log << Logger::Error << "Cleaning up" << endl;
+    ret.clear();
     throw;
   } catch(...) {
     // and cleanup
-    g_log<<Logger::Error<<"Caught an exception instantiating a backend (" << current <<"), cleaning up"<<endl;
-    for (auto i : ret) {
-      delete i;
-    }
+    g_log << Logger::Error << "Caught an exception instantiating a backend (" << current << "), cleaning up" << endl;
+    ret.clear();
     throw;
   }
 
@@ -322,7 +315,7 @@ void fillSOAData(const DNSZoneRecord& in, SOAData& sd)
 
   auto src=getRR<SOARecordContent>(in.dr);
   sd.nameserver = src->d_mname;
-  sd.hostmaster = src->d_rname;
+  sd.rname = src->d_rname;
   sd.serial = src->d_st.serial;
   sd.refresh = src->d_st.refresh;
   sd.retry = src->d_st.retry;
@@ -338,7 +331,7 @@ std::shared_ptr<DNSRecordContent> makeSOAContent(const SOAData& sd)
     st.retry = sd.retry;
     st.expire = sd.expire;
     st.minimum = sd.minimum;
-    return std::make_shared<SOARecordContent>(sd.nameserver, sd.hostmaster, st);
+    return std::make_shared<SOARecordContent>(sd.nameserver, sd.rname, st);
 }
 
 void fillSOAData(const string &content, SOAData &data)
@@ -349,7 +342,7 @@ void fillSOAData(const string &content, SOAData &data)
 
   try {
     data.nameserver = DNSName(parts.at(0));
-    data.hostmaster = DNSName(parts.at(1));
+    data.rname = DNSName(parts.at(1));
     pdns::checked_stoi_into(data.serial, parts.at(2));
     pdns::checked_stoi_into(data.refresh, parts.at(3));
     pdns::checked_stoi_into(data.retry, parts.at(4));
index 12e989ad99c08f9487e0cdb79b23b7bf4d0f858b..a2ee00b41c9fc543b305bafd705376f57bf82b03 100644 (file)
@@ -22,6 +22,7 @@
 #pragma once
 
 #include <algorithm>
+#include <cstddef>
 class DNSPacket;
 
 #include "utility.hh"
@@ -57,7 +58,7 @@ struct DomainInfo
   time_t last_check{};
   string options;
   string account;
-  vector<ComboAddress> masters;
+  vector<ComboAddress> primaries;
   DNSBackend *backend{};
 
   uint32_t id{};
@@ -75,8 +76,8 @@ struct DomainInfo
   // Do not reorder (lmdbbackend)!!! One exception 'All' is always last.
   enum DomainKind : uint8_t
   {
-    Master,
-    Slave,
+    Primary,
+    Secondary,
     Native,
     Producer,
     Consumer,
@@ -97,10 +98,10 @@ struct DomainInfo
   static DomainKind stringToKind(const string& kind)
   {
     if (pdns_iequals(kind, "SECONDARY") || pdns_iequals(kind, "SLAVE")) {
-      return DomainInfo::Slave;
+      return DomainInfo::Secondary;
     }
     if (pdns_iequals(kind, "PRIMARY") || pdns_iequals(kind, "MASTER")) {
-      return DomainInfo::Master;
+      return DomainInfo::Primary;
     }
     if (pdns_iequals(kind, "PRODUCER")) {
       return DomainInfo::Producer;
@@ -112,13 +113,13 @@ struct DomainInfo
     return DomainInfo::Native;
   }
 
-  [[nodiscard]] bool isPrimaryType() const { return (kind == DomainInfo::Master || kind == DomainInfo::Producer); }
-  [[nodiscard]] bool isSecondaryType() const { return (kind == DomainInfo::Slave || kind == DomainInfo::Consumer); }
+  [[nodiscard]] bool isPrimaryType() const { return (kind == DomainInfo::Primary || kind == DomainInfo::Producer); }
+  [[nodiscard]] bool isSecondaryType() const { return (kind == DomainInfo::Secondary || kind == DomainInfo::Consumer); }
   [[nodiscard]] bool isCatalogType() const { return (kind == DomainInfo::Producer || kind == DomainInfo::Consumer); }
 
-  [[nodiscard]] bool isMaster(const ComboAddress& ipAddress) const
+  [[nodiscard]] bool isPrimary(const ComboAddress& ipAddress) const
   {
-    return std::any_of(masters.begin(), masters.end(), [ipAddress](auto master) { return ComboAddress::addressOnlyEqual()(ipAddress, master); });
+    return std::any_of(primaries.begin(), primaries.end(), [ipAddress](auto primary) { return ComboAddress::addressOnlyEqual()(ipAddress, primary); });
   }
 };
 
@@ -278,7 +279,7 @@ public:
     return false;
   }
 
-  //! returns true if master ip is master for domain name.
+  //! returns true if primary ip is primary for domain name.
   //! starts the transaction for updating domain qname (FIXME: what is id?)
   virtual bool startTransaction(const DNSName& /* qname */, int /* id */ = -1)
   {
@@ -329,8 +330,8 @@ public:
   {
     return false;
   }
-  //! slave capable backends should return a list of slaves that should be rechecked for staleness
-  virtual void getUnfreshSlaveInfos(vector<DomainInfo>* /* domains */)
+  //! secondary capable backends should return a list of secondaries that should be rechecked for staleness
+  virtual void getUnfreshSecondaryInfos(vector<DomainInfo>* /* domains */)
   {
   }
 
@@ -342,8 +343,8 @@ public:
     ips->insert(meta.begin(), meta.end());
   }
 
-  //! get list of domains that have been changed since their last notification to slaves
-  virtual void getUpdatedMasters(vector<DomainInfo>& /* domains */, std::unordered_set<DNSName>& /* catalogs */, CatalogHashMap& /* catalogHashes */)
+  //! get list of domains that have been changed since their last notification to secondaries
+  virtual void getUpdatedPrimaries(vector<DomainInfo>& /* domains */, std::unordered_set<DNSName>& /* catalogs */, CatalogHashMap& /* catalogHashes */)
   {
   }
 
@@ -363,18 +364,18 @@ public:
   {
   }
 
-  //! Called by PowerDNS to inform a backend that the changes in the domain have been reported to slaves
+  //! Called by PowerDNS to inform a backend that the changes in the domain have been reported to secondaries
   virtual void setNotified(uint32_t /* id */, uint32_t /* serial */)
   {
   }
 
-  //! Called when the Master list of a domain should be changed
-  virtual bool setMasters(const DNSName& /* domain */, const vector<ComboAddress>& /* masters */)
+  //! Called when the Primary list of a domain should be changed
+  virtual bool setPrimaries(const DNSName& /* domain */, const vector<ComboAddress>& /* primaries */)
   {
     return false;
   }
 
-  //! Called when the Kind of a domain should be changed (master -> native and similar)
+  //! Called when the Kind of a domain should be changed (primary -> native and similar)
   virtual bool setKind(const DNSName& /* domain */, const DomainInfo::DomainKind /* kind */)
   {
     return false;
@@ -401,38 +402,38 @@ public:
   //! Can be called to seed the getArg() function with a prefix
   void setArgPrefix(const string &prefix);
 
-  //! Add an entry for a super master
-  virtual bool superMasterAdd(const struct AutoPrimary& /* primary */)
+  //! Add an entry for a super primary
+  virtual bool autoPrimaryAdd(const struct AutoPrimary& /* primary */)
   {
     return false;
   }
 
-  //! Remove an entry for a super master
+  //! Remove an entry for a super primary
   virtual bool autoPrimaryRemove(const struct AutoPrimary& /* primary */)
   {
     return false;
   }
 
-  //! List all SuperMasters, returns false if feature not supported.
+  //! List all AutoPrimaries, returns false if feature not supported.
   virtual bool autoPrimariesList(std::vector<AutoPrimary>& /* primaries */)
   {
     return false;
   }
 
-  //! determine if ip is a supermaster or a domain
-  virtual bool superMasterBackend(const string& /* ip */, const DNSName& /* domain */, const vector<DNSResourceRecord>& /* nsset */, string* /* nameserver */, string* /* account */, DNSBackend** /* db */)
+  //! determine if ip is a autoprimary or a domain
+  virtual bool autoPrimaryBackend(const string& /* ip */, const DNSName& /* domain */, const vector<DNSResourceRecord>& /* nsset */, string* /* nameserver */, string* /* account */, DNSBackend** /* db */)
   {
     return false;
   }
 
   //! called by PowerDNS to create a new domain
-  virtual bool createDomain(const DNSName& /* domain */, const DomainInfo::DomainKind /* kind */, const vector<ComboAddress>& /* masters */, const string& /* account */)
+  virtual bool createDomain(const DNSName& /* domain */, const DomainInfo::DomainKind /* kind */, const vector<ComboAddress>& /* primaries */, const string& /* account */)
   {
     return false;
   }
 
-  //! called by PowerDNS to create a slave record for a superMaster
-  virtual bool createSlaveDomain(const string& /* ip */, const DNSName& /* domain */, const string& /* nameserver */, const string& /* account */)
+  //! called by PowerDNS to create a secondary record for a autoPrimary
+  virtual bool createSecondaryDomain(const string& /* ip */, const DNSName& /* domain */, const string& /* nameserver */, const string& /* account */)
   {
     return false;
   }
@@ -449,13 +450,13 @@ public:
   }
 
   //! Search for records, returns true if search was done successfully.
-  virtual bool searchRecords(const string& /* pattern */, int /* maxResults */, vector<DNSResourceRecord>& /* result */)
+  virtual bool searchRecords(const string& /* pattern */, size_t /* maxResults */, vector<DNSResourceRecord>& /* result */)
   {
     return false;
   }
 
   //! Search for comments, returns true if search was done successfully.
-  virtual bool searchComments(const string& /* pattern */, int /* maxResults */, vector<Comment>& /* result */)
+  virtual bool searchComments(const string& /* pattern */, size_t /* maxResults */, vector<Comment>& /* result */)
   {
     return false;
   }
@@ -495,7 +496,7 @@ class BackendMakerClass
 public:
   void report(BackendFactory *bf);
   void launch(const string &instr);
-  vector<DNSBackend *> all(bool skipBIND=false);
+  vector<std::unique_ptr<DNSBackend>> all(bool metadataOnly=false);
   void load(const string &module);
   [[nodiscard]] size_t numLauncheable() const;
   vector<string> getModules();
@@ -524,7 +525,7 @@ struct SOAData
 
   DNSName qname;
   DNSName nameserver;
-  DNSName hostmaster;
+  DNSName rname;
   uint32_t ttl{};
   uint32_t serial{};
   uint32_t refresh{};
index 085a644d571256c9f457c31e97e060898a2cefb6..9ebf705ef6331d2d35ce7bc45b941e307164ed5d 100644 (file)
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wdeprecated-copy-with-user-provided-copy"
 #include <boost/accumulators/accumulators.hpp>
 #include <boost/array.hpp>
 #include <boost/accumulators/statistics.hpp>
+#pragma GCC diagnostic pop
 #include <boost/program_options.hpp>
 #include "inflighter.cc"
 #include <deque>
index 6db8613a3d01899c1d3844d6d647bfe44f8055f5..372329bdfcc03d2a2dda8af25c780c34a8f50bef 100644 (file)
@@ -399,9 +399,10 @@ bool DNSCryptQuery::parsePlaintextQuery(const PacketBuffer& packet)
     return false;
   }
 
-  const struct dnsheader * dh = reinterpret_cast<const struct dnsheader *>(packet.data());
-  if (dh->qr || ntohs(dh->qdcount) != 1 || dh->ancount != 0 || dh->nscount != 0 || dh->opcode != Opcode::Query)
+  const dnsheader_aligned dh(packet.data());
+  if (dh->qr || ntohs(dh->qdcount) != 1 || dh->ancount != 0 || dh->nscount != 0 || static_cast<uint8_t>(dh->opcode) != Opcode::Query) {
     return false;
+  }
 
   unsigned int qnameWireLength;
   uint16_t qtype, qclass;
index 7ca9be2f6e7ee0291b2e60c9410f883471969c42..67de6226a0432d7362b5470249ead2e0a507f9c6 100644 (file)
@@ -252,7 +252,7 @@ bool DNSDistPacketCache::get(DNSQuestion& dq, uint16_t queryId, uint32_t* keyOut
     }
 
     /* check for collision */
-    if (!cachedValueMatches(value, *(getFlagsFromDNSHeader(dq.getHeader())), dq.ids.qname, dq.ids.qtype, dq.ids.qclass, receivedOverUDP, dnssecOK, subnet)) {
+    if (!cachedValueMatches(value, *(getFlagsFromDNSHeader(dq.getHeader().get())), dq.ids.qname, dq.ids.qtype, dq.ids.qclass, receivedOverUDP, dnssecOK, subnet)) {
       ++d_lookupCollisions;
       return false;
     }
index a49a50914759924ba0901b89d124c0b1891bbdeb..9dfe8159fe504c2df196bb48446f65c8a350eaf0 100644 (file)
@@ -773,6 +773,8 @@ const std::vector<ConsoleKeyword> g_consoleKeywords{
   { "SetECSPrefixLengthAction", true, "v4, v6", "Set the ECS prefix length. Subsequent rules are processed after this action" },
   { "SetMacAddrAction", true, "option", "Add the source MAC address to the query as EDNS0 option option. This action is currently only supported on Linux. Subsequent rules are processed after this action" },
   { "SetEDNSOptionAction", true, "option, data", "Add arbitrary EDNS option and data to the query. Subsequent rules are processed after this action" },
+  { "SetExtendedDNSErrorAction", true, "infoCode [, extraText]", "Set an Extended DNS Error status that will be added to the response corresponding to the current query. Subsequent rules are processed after this action" },
+  { "SetExtendedDNSErrorResponseAction", true, "infoCode [, extraText]", "Set an Extended DNS Error status that will be added to this response. Subsequent rules are processed after this action" },
   { "SetNoRecurseAction", true, "", "strip RD bit from the question, let it go through" },
   { "setOutgoingDoHWorkerThreads", true, "n", "Number of outgoing DoH worker threads" },
   { "SetProxyProtocolValuesAction", true, "values", "Set the Proxy-Protocol values for this queries to 'values'" },
index 39c8bc7ec8ee2e63e0025d312e1080f8752be2a6..9228ce202492c1517c0ebebbca59b24bcfec0738 100644 (file)
@@ -310,6 +310,16 @@ public:
     d_excludedSubnets.addMasks(group, false);
   }
 
+  void removeRange(const Netmask& range)
+  {
+    d_excludedSubnets.deleteMask(range);
+  }
+
+  void removeRange(const NetmaskGroup& group)
+  {
+    d_excludedSubnets.deleteMasks(group);
+  }
+
   void excludeDomain(const DNSName& domain)
   {
     d_excludedDomains.add(domain);
index 9e9d9c329e76bd8513799abe2082f384ca583080..2cad1945bca8de18beb3eb745743f62dad02b21d 100644 (file)
@@ -21,6 +21,7 @@
  */
 #include "dolog.hh"
 #include "dnsdist.hh"
+#include "dnsdist-dnsparser.hh"
 #include "dnsdist-ecs.hh"
 #include "dnsparser.hh"
 #include "dnswriter.hh"
@@ -44,13 +45,15 @@ bool g_addEDNSToSelfGeneratedResponses{true};
 int rewriteResponseWithoutEDNS(const PacketBuffer& initialPacket, PacketBuffer& newContent)
 {
   assert(initialPacket.size() >= sizeof(dnsheader));
-  const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(initialPacket.data());
+  const dnsheader_aligned dh(initialPacket.data());
 
-  if (ntohs(dh->arcount) == 0)
+  if (ntohs(dh->arcount) == 0) {
     return ENOENT;
+  }
 
-  if (ntohs(dh->qdcount) == 0)
+  if (ntohs(dh->qdcount) == 0) {
     return ENOENT;
+  }
 
   PacketReader pr(std::string_view(reinterpret_cast<const char*>(initialPacket.data()), initialPacket.size()));
 
@@ -152,7 +155,7 @@ static bool addOrReplaceEDNSOption(std::vector<std::pair<uint16_t, std::string>>
 bool slowRewriteEDNSOptionInQueryWithRecords(const PacketBuffer& initialPacket, PacketBuffer& newContent, bool& ednsAdded, uint16_t optionToReplace, bool& optionAdded, bool overrideExisting, const string& newOptionContent)
 {
   assert(initialPacket.size() >= sizeof(dnsheader));
-  const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(initialPacket.data());
+  const dnsheader_aligned dh(initialPacket.data());
 
   if (ntohs(dh->qdcount) == 0) {
     return false;
@@ -269,7 +272,7 @@ static bool slowParseEDNSOptions(const PacketBuffer& packet, EDNSOptionViewMap&
     return false;
   }
 
-  const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(packet.data());
+  const dnsheader_aligned dh(packet.data());
 
   if (ntohs(dh->qdcount) == 0) {
     return false;
@@ -324,10 +327,11 @@ int locateEDNSOptRR(const PacketBuffer& packet, uint16_t * optStart, size_t * op
   assert(optStart != NULL);
   assert(optLen != NULL);
   assert(last != NULL);
-  const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(packet.data());
+  const dnsheader_aligned dh(packet.data());
 
-  if (ntohs(dh->arcount) == 0)
+  if (ntohs(dh->arcount) == 0) {
     return ENOENT;
+  }
 
   PacketReader pr(std::string_view(reinterpret_cast<const char*>(packet.data()), packet.size()));
 
@@ -390,14 +394,15 @@ int getEDNSOptionsStart(const PacketBuffer& packet, const size_t offset, uint16_
 {
   assert(optRDPosition != nullptr);
   assert(remaining != nullptr);
-  const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(packet.data());
+  const dnsheader_aligned dh(packet.data());
 
   if (offset >= packet.size()) {
     return ENOENT;
   }
 
-  if (ntohs(dh->qdcount) != 1 || ntohs(dh->ancount) != 0 || ntohs(dh->arcount) != 1 || ntohs(dh->nscount) != 0)
+  if (ntohs(dh->qdcount) != 1 || ntohs(dh->ancount) != 0 || ntohs(dh->arcount) != 1 || ntohs(dh->nscount) != 0) {
     return ENOENT;
+  }
 
   size_t pos = sizeof(dnsheader) + offset;
   pos += DNS_TYPE_SIZE + DNS_CLASS_SIZE;
@@ -571,10 +576,12 @@ static bool addEDNSWithECS(PacketBuffer& packet, size_t maximumSize, const strin
     return false;
   }
 
-  struct dnsheader* dh = reinterpret_cast<struct dnsheader*>(packet.data());
-  uint16_t arcount = ntohs(dh->arcount);
-  arcount++;
-  dh->arcount = htons(arcount);
+  dnsdist::PacketMangling::editDNSHeaderFromPacket(packet, [](dnsheader& header) {
+    uint16_t arcount = ntohs(header.arcount);
+    arcount++;
+    header.arcount = htons(arcount);
+    return true;
+  });
   ednsAdded = true;
   ecsAdded = true;
 
@@ -585,7 +592,7 @@ bool handleEDNSClientSubnet(PacketBuffer& packet, const size_t maximumSize, cons
 {
   assert(qnameWireLength <= packet.size());
 
-  const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(packet.data());
+  const dnsheader_aligned dh(packet.data());
 
   if (ntohs(dh->ancount) != 0 || ntohs(dh->nscount) != 0 || (ntohs(dh->arcount) != 0 && ntohs(dh->arcount) != 1)) {
     PacketBuffer newContent;
@@ -752,7 +759,7 @@ bool isEDNSOptionInOpt(const PacketBuffer& packet, const size_t optStart, const
 int rewriteResponseWithoutEDNSOption(const PacketBuffer& initialPacket, const uint16_t optionCodeToSkip, PacketBuffer& newContent)
 {
   assert(initialPacket.size() >= sizeof(dnsheader));
-  const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(initialPacket.data());
+  const dnsheader_aligned dh(initialPacket.data());
 
   if (ntohs(dh->arcount) == 0)
     return ENOENT;
@@ -852,8 +859,10 @@ bool addEDNS(PacketBuffer& packet, size_t maximumSize, bool dnssecOK, uint16_t p
     return false;
   }
 
-  auto dh = reinterpret_cast<dnsheader*>(packet.data());
-  dh->arcount = htons(ntohs(dh->arcount) + 1);
+  dnsdist::PacketMangling::editDNSHeaderFromPacket(packet, [](dnsheader& header) {
+    header.arcount = htons(ntohs(header.arcount) + 1);
+    return true;
+  });
 
   return true;
 }
@@ -894,17 +903,19 @@ bool setNegativeAndAdditionalSOA(DNSQuestion& dq, bool nxd, const DNSName& zone,
 
   /* chop off everything after the question */
   packet.resize(queryPartSize);
-  dh = dq.getHeader();
-  if (nxd) {
-    dh->rcode = RCode::NXDomain;
-  }
-  else {
-    dh->rcode = RCode::NoError;
-  }
-  dh->qr = true;
-  dh->ancount = 0;
-  dh->nscount = 0;
-  dh->arcount = 0;
+  dnsdist::PacketMangling::editDNSHeaderFromPacket(packet, [nxd](dnsheader& header) {
+    if (nxd) {
+      header.rcode = RCode::NXDomain;
+    }
+    else {
+      header.rcode = RCode::NoError;
+    }
+    header.qr = true;
+    header.ancount = 0;
+    header.nscount = 0;
+    header.arcount = 0;
+    return true;
+  });
 
   rdLength = htons(rdLength);
   ttl = htonl(ttl);
@@ -934,16 +945,18 @@ bool setNegativeAndAdditionalSOA(DNSQuestion& dq, bool nxd, const DNSName& zone,
   }
 
   packet.insert(packet.end(), soa.begin(), soa.end());
-  dh = dq.getHeader();
 
   /* We are populating a response with only the query in place, order of sections is QD,AN,NS,AR
      NS (authority) is before AR (additional) so we can just decide which section the SOA record is in here
      and have EDNS added to AR afterwards */
-  if (soaInAuthoritySection) {
-    dh->nscount = htons(1);
-  } else {
-    dh->arcount = htons(1);
-  }
+  dnsdist::PacketMangling::editDNSHeaderFromPacket(packet, [soaInAuthoritySection](dnsheader& header) {
+    if (soaInAuthoritySection) {
+      header.nscount = htons(1);
+    } else {
+      header.arcount = htons(1);
+    }
+    return true;
+  });
 
   if (hadEDNS) {
     /* now we need to add a new OPT record */
@@ -982,7 +995,10 @@ bool addEDNSToQueryTurnedResponse(DNSQuestion& dq)
 
   /* remove the existing OPT record, and everything else that follows (any SIG or TSIG would be useless anyway) */
   packet.resize(packet.size() - existingOptLen);
-  dq.getHeader()->arcount = 0;
+  dnsdist::PacketMangling::editDNSHeaderFromPacket(packet, [](dnsheader& header) {
+    header.arcount = 0;
+    return true;
+  });
 
   if (g_addEDNSToSelfGeneratedResponses) {
     /* now we need to add a new OPT record */
@@ -1107,7 +1123,10 @@ bool setEDNSOption(DNSQuestion& dq, uint16_t ednsCode, const std::string& ednsDa
 
   auto& data = dq.getMutableData();
   if (generateOptRR(optRData, data, dq.getMaximumSize(), g_EdnsUDPPayloadSize, 0, false)) {
-    dq.getHeader()->arcount = htons(1);
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [](dnsheader& header) {
+      header.arcount = htons(1);
+      return true;
+    });
     // make sure that any EDNS sent by the backend is removed before forwarding the response to the client
     dq.ids.ednsAdded = true;
   }
@@ -1129,17 +1148,22 @@ bool setInternalQueryRCode(InternalQueryState& state, PacketBuffer& buffer,  uin
     hadEDNS = getEDNS0Record(buffer, edns0);
   }
 
-  auto dh = reinterpret_cast<dnsheader*>(buffer.data());
-  dh->rcode = rcode;
-  dh->ad = false;
-  dh->aa = false;
-  dh->ra = dh->rd;
-  dh->qr = true;
+  dnsdist::PacketMangling::editDNSHeaderFromPacket(buffer, [rcode,clearAnswers](dnsheader& header) {
+    header.rcode = rcode;
+    header.ad = false;
+    header.aa = false;
+    header.ra = header.rd;
+    header.qr = true;
+
+    if (clearAnswers) {
+      header.ancount = 0;
+      header.nscount = 0;
+      header.arcount = 0;
+    }
+    return true;
+  });
 
   if (clearAnswers) {
-    dh->ancount = 0;
-    dh->nscount = 0;
-    dh->arcount = 0;
     buffer.resize(sizeof(dnsheader) + qnameLength + sizeof(uint16_t) + sizeof(uint16_t));
     if (hadEDNS) {
       DNSQuestion dq(state, buffer);
index 63daead6026509f6d97718d2dd7127b1477e7c52..e1fb8d38e1534b63c13d68e00078a36dd40c6950 100644 (file)
  */
 #pragma once
 
+#include <unordered_map>
+
 #include "config.h"
 #include "dnscrypt.hh"
 #include "dnsname.hh"
 #include "dnsdist-protocols.hh"
+#include "ednsextendederror.hh"
 #include "gettime.hh"
 #include "iputils.hh"
 #include "noinitvector.hh"
@@ -129,6 +132,7 @@ struct InternalQueryState
   std::unique_ptr<QTag> qTag{nullptr}; // 8
   std::unique_ptr<PacketBuffer> d_packet{nullptr}; // Initial packet, so we can restart the query from the response path if needed // 8
   std::unique_ptr<ProtoBufData> d_protoBufData{nullptr};
+  std::unique_ptr<EDNSExtendedError> d_extendedError{nullptr};
   boost::optional<uint32_t> tempFailureTTL{boost::none}; // 8
   ClientState* cs{nullptr}; // 8
   std::unique_ptr<DOHUnitInterface> du; // 8
index b81600fe8c92aa2e7668efa78f28fc71860797a2..575c8f3465b98cd933aa1247addef6650ac592ea 100644 (file)
@@ -23,6 +23,7 @@
 #include "threadname.hh"
 #include "dnsdist.hh"
 #include "dnsdist-async.hh"
+#include "dnsdist-dnsparser.hh"
 #include "dnsdist-ecs.hh"
 #include "dnsdist-edns.hh"
 #include "dnsdist-lua.hh"
@@ -242,37 +243,54 @@ std::map<std::string,double> TeeAction::getStats() const
 void TeeAction::worker()
 {
   setThreadName("dnsdist/TeeWork");
-  char packet[1500];
-  int res=0;
-  struct dnsheader* dh=(struct dnsheader*)packet;
-  for(;;) {
-    res=waitForData(d_fd, 0, 250000);
-    if(d_pleaseQuit)
+  std::array<char, s_udpIncomingBufferSize> packet{};
+  ssize_t res = 0;
+  const dnsheader_aligned dh(packet.data());
+  for (;;) {
+    res = waitForData(d_fd, 0, 250000);
+    if (d_pleaseQuit) {
       break;
-    if(res < 0) {
+    }
+
+    if (res < 0) {
       usleep(250000);
       continue;
     }
-    if(res==0)
+    if (res == 0) {
       continue;
-    res=recv(d_fd, packet, sizeof(packet), 0);
-    if(res <= (int)sizeof(struct dnsheader))
+    }
+    res = recv(d_fd, packet.data(), packet.size(), 0);
+    if (static_cast<size_t>(res) <= sizeof(struct dnsheader)) {
       d_recverrors++;
-    else
+    }
+    else {
       d_responses++;
+    }
 
-    if(dh->rcode == RCode::NoError)
+    // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions): rcode is unsigned, RCode::rcodes_ as well
+    if (dh->rcode == RCode::NoError) {
       d_noerrors++;
-    else if(dh->rcode == RCode::ServFail)
+    }
+    // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions): rcode is unsigned, RCode::rcodes_ as well
+    else if (dh->rcode == RCode::ServFail) {
       d_servfails++;
-    else if(dh->rcode == RCode::NXDomain)
+    }
+    // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions): rcode is unsigned, RCode::rcodes_ as well
+    else if (dh->rcode == RCode::NXDomain) {
       d_nxdomains++;
-    else if(dh->rcode == RCode::Refused)
+    }
+    // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions): rcode is unsigned, RCode::rcodes_ as well
+    else if (dh->rcode == RCode::Refused) {
       d_refuseds++;
-    else if(dh->rcode == RCode::FormErr)
+    }
+    // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions): rcode is unsigned, RCode::rcodes_ as well
+    else if (dh->rcode == RCode::FormErr) {
       d_formerrs++;
-    else if(dh->rcode == RCode::NotImp)
+    }
+    // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions): rcode is unsigned, RCode::rcodes_ as well
+    else if (dh->rcode == RCode::NotImp) {
       d_notimps++;
+    }
   }
 }
 
@@ -343,9 +361,12 @@ public:
   RCodeAction(uint8_t rcode) : d_rcode(rcode) {}
   DNSAction::Action operator()(DNSQuestion* dq, std::string* ruleresult) const override
   {
-    dq->getHeader()->rcode = d_rcode;
-    dq->getHeader()->qr = true; // for good measure
-    setResponseHeadersFromConfig(*dq->getHeader(), d_responseConfig);
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(dq->getMutableData(), [this](dnsheader& header) {
+      header.rcode = d_rcode;
+      header.qr = true; // for good measure
+      setResponseHeadersFromConfig(header, d_responseConfig);
+      return true;
+    });
     return Action::HeaderModify;
   }
   std::string toString() const override
@@ -364,10 +385,13 @@ public:
   ERCodeAction(uint8_t rcode) : d_rcode(rcode) {}
   DNSAction::Action operator()(DNSQuestion* dq, std::string* ruleresult) const override
   {
-    dq->getHeader()->rcode = (d_rcode & 0xF);
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(dq->getMutableData(), [this](dnsheader& header) {
+      header.rcode = (d_rcode & 0xF);
+      header.qr = true; // for good measure
+      setResponseHeadersFromConfig(header, d_responseConfig);
+      return true;
+    });
     dq->ednsRCode = ((d_rcode & 0xFFF0) >> 4);
-    dq->getHeader()->qr = true; // for good measure
-    setResponseHeadersFromConfig(*dq->getHeader(), d_responseConfig);
     return Action::HeaderModify;
   }
   std::string toString() const override
@@ -819,7 +843,10 @@ DNSAction::Action SpoofAction::operator()(DNSQuestion* dq, std::string* ruleresu
   if (d_raw.size() >= sizeof(dnsheader)) {
     auto id = dq->getHeader()->id;
     dq->getMutableData() = d_raw;
-    dq->getHeader()->id = id;
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(dq->getMutableData(), [id](dnsheader& header) {
+      header.id = id;
+      return true;
+    });
     return Action::HeaderModify;
   }
   vector<ComboAddress> addrs;
@@ -875,10 +902,13 @@ DNSAction::Action SpoofAction::operator()(DNSQuestion* dq, std::string* ruleresu
   data.resize(sizeof(dnsheader) + qnameWireLength + 4 + numberOfRecords*12 /* recordstart */ + totrdatalen); // there goes your EDNS
   uint8_t* dest = &(data.at(sizeof(dnsheader) + qnameWireLength + 4));
 
-  dq->getHeader()->qr = true; // for good measure
-  setResponseHeadersFromConfig(*dq->getHeader(), d_responseConfig);
-  dq->getHeader()->ancount = 0;
-  dq->getHeader()->arcount = 0; // for now, forget about your EDNS, we're marching over it
+  dnsdist::PacketMangling::editDNSHeaderFromPacket(dq->getMutableData(), [this](dnsheader& header) {
+    header.qr = true; // for good measure
+    setResponseHeadersFromConfig(header, d_responseConfig);
+    header.ancount = 0;
+    header.arcount = 0; // for now, forget about your EDNS, we're marching over it
+    return true;
+  });
 
   uint32_t ttl = htonl(d_responseConfig.ttl);
   uint16_t qclass = htons(dq->ids.qclass);
@@ -902,7 +932,10 @@ DNSAction::Action SpoofAction::operator()(DNSQuestion* dq, std::string* ruleresu
     memcpy(dest, recordstart, sizeof(recordstart));
     dest += sizeof(recordstart);
     memcpy(dest, wireData.c_str(), wireData.length());
-    dq->getHeader()->ancount++;
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(dq->getMutableData(), [](dnsheader& header) {
+      header.ancount++;
+      return true;
+    });
   }
   else if (!rawResponses.empty()) {
     qtype = htons(qtype);
@@ -917,7 +950,10 @@ DNSAction::Action SpoofAction::operator()(DNSQuestion* dq, std::string* ruleresu
       memcpy(dest, rawResponse.c_str(), rawResponse.size());
       dest += rawResponse.size();
 
-      dq->getHeader()->ancount++;
+      dnsdist::PacketMangling::editDNSHeaderFromPacket(dq->getMutableData(), [](dnsheader& header) {
+        header.ancount++;
+        return true;
+      });
     }
     raw = true;
   }
@@ -935,11 +971,18 @@ DNSAction::Action SpoofAction::operator()(DNSQuestion* dq, std::string* ruleresu
              addr.sin4.sin_family == AF_INET ? reinterpret_cast<const void*>(&addr.sin4.sin_addr.s_addr) : reinterpret_cast<const void*>(&addr.sin6.sin6_addr.s6_addr),
              addr.sin4.sin_family == AF_INET ? sizeof(addr.sin4.sin_addr.s_addr) : sizeof(addr.sin6.sin6_addr.s6_addr));
       dest += (addr.sin4.sin_family == AF_INET ? sizeof(addr.sin4.sin_addr.s_addr) : sizeof(addr.sin6.sin6_addr.s6_addr));
-      dq->getHeader()->ancount++;
+      dnsdist::PacketMangling::editDNSHeaderFromPacket(dq->getMutableData(), [](dnsheader& header) {
+        header.ancount++;
+        return true;
+      });
     }
   }
 
-  dq->getHeader()->ancount = htons(dq->getHeader()->ancount);
+  auto finalANCount = dq->getHeader()->ancount;
+  dnsdist::PacketMangling::editDNSHeaderFromPacket(dq->getMutableData(), [finalANCount](dnsheader& header) {
+    header.ancount = htons(finalANCount);
+    return true;
+  });
 
   if (hadEDNS && raw == false) {
     addEDNS(dq->getMutableData(), dq->getMaximumSize(), dnssecOK, g_PayloadSizeSelfGenAnswers, 0);
@@ -991,7 +1034,10 @@ public:
 
     auto& data = dq->getMutableData();
     if (generateOptRR(optRData, data, dq->getMaximumSize(), g_EdnsUDPPayloadSize, 0, false)) {
-      dq->getHeader()->arcount = htons(1);
+      dnsdist::PacketMangling::editDNSHeaderFromPacket(dq->getMutableData(), [](dnsheader& header) {
+        header.arcount = htons(1);
+        return true;
+      });
       // make sure that any EDNS sent by the backend is removed before forwarding the response to the client
       dq->ids.ednsAdded = true;
     }
@@ -1036,7 +1082,10 @@ public:
   // this action does not stop the processing
   DNSAction::Action operator()(DNSQuestion* dq, std::string* ruleresult) const override
   {
-    dq->getHeader()->rd = false;
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(dq->getMutableData(), [](dnsheader& header) {
+      header.rd = false;
+      return true;
+    });
     return Action::None;
   }
   std::string toString() const override
@@ -1252,7 +1301,10 @@ public:
   // this action does not stop the processing
   DNSAction::Action operator()(DNSQuestion* dq, std::string* ruleresult) const override
   {
-    dq->getHeader()->cd = true;
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(dq->getMutableData(), [](dnsheader& header) {
+      header.cd = true;
+      return true;
+    });
     return Action::None;
   }
   std::string toString() const override
@@ -1922,8 +1974,11 @@ public:
     }
 
     dq->ids.du->setHTTPResponse(d_code, PacketBuffer(d_body), d_contentType);
-    dq->getHeader()->qr = true; // for good measure
-    setResponseHeadersFromConfig(*dq->getHeader(), d_responseConfig);
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(dq->getMutableData(), [this](dnsheader& header) {
+      header.qr = true; // for good measure
+      setResponseHeadersFromConfig(header, d_responseConfig);
+      return true;
+    });
     return Action::HeaderModify;
   }
 
@@ -2067,7 +2122,10 @@ public:
       return Action::None;
     }
 
-    setResponseHeadersFromConfig(*dq->getHeader(), d_responseConfig);
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(dq->getMutableData(), [this](dnsheader& header) {
+      setResponseHeadersFromConfig(header, d_responseConfig);
+      return true;
+    });
 
     return Action::Allow;
   }
@@ -2180,6 +2238,58 @@ private:
   double d_ratio{1.0};
 };
 
+class SetExtendedDNSErrorAction : public DNSAction
+{
+public:
+  // this action does not stop the processing
+  SetExtendedDNSErrorAction(uint16_t infoCode, const std::string& extraText)
+  {
+    d_ede.infoCode = infoCode;
+    d_ede.extraText = extraText;
+  }
+
+  DNSAction::Action operator()(DNSQuestion* dnsQuestion, std::string* ruleresult) const override
+  {
+    dnsQuestion->ids.d_extendedError = std::make_unique<EDNSExtendedError>(d_ede);
+
+    return DNSAction::Action::None;
+  }
+
+  [[nodiscard]] std::string toString() const override
+  {
+    return "set EDNS Extended DNS Error to " + std::to_string(d_ede.infoCode) + (d_ede.extraText.empty() ? std::string() : std::string(": \"") + d_ede.extraText + std::string("\""));
+  }
+
+private:
+  EDNSExtendedError d_ede;
+};
+
+class SetExtendedDNSErrorResponseAction : public DNSResponseAction
+{
+public:
+  // this action does not stop the processing
+  SetExtendedDNSErrorResponseAction(uint16_t infoCode, const std::string& extraText)
+  {
+    d_ede.infoCode = infoCode;
+    d_ede.extraText = extraText;
+  }
+
+  DNSResponseAction::Action operator()(DNSResponse* dnsResponse, std::string* ruleresult) const override
+  {
+    dnsResponse->ids.d_extendedError = std::make_unique<EDNSExtendedError>(d_ede);
+
+    return DNSResponseAction::Action::None;
+  }
+
+  [[nodiscard]] std::string toString() const override
+  {
+    return "set EDNS Extended DNS Error to " + std::to_string(d_ede.infoCode) + (d_ede.extraText.empty() ? std::string() : std::string(": \"") + d_ede.extraText + std::string("\""));
+  }
+
+private:
+  EDNSExtendedError d_ede;
+};
+
 template<typename T, typename ActionT>
 static void addAction(GlobalStateHolder<vector<T> > *someRuleActions, const luadnsrule_t& var, const std::shared_ptr<ActionT>& action, boost::optional<luaruleparams_t>& params) {
   setLuaSideEffect();
@@ -2225,6 +2335,7 @@ void setResponseHeadersFromConfig(dnsheader& dh, const ResponseConfig& config)
   }
 }
 
+// NOLINTNEXTLINE(readability-function-cognitive-complexity): this function declares Lua bindings, even with a good refactoring it will likely blow up the threshold
 void setupLuaActions(LuaContext& luaCtx)
 {
   luaCtx.writeFunction("newRuleAction", [](luadnsrule_t dnsrule, std::shared_ptr<DNSAction> action, boost::optional<luaruleparams_t> params) {
@@ -2715,4 +2826,12 @@ void setupLuaActions(LuaContext& luaCtx)
   luaCtx.writeFunction("SetAdditionalProxyProtocolValueAction", [](uint8_t type, const std::string& value) {
     return std::shared_ptr<DNSAction>(new SetAdditionalProxyProtocolValueAction(type, value));
   });
+
+  luaCtx.writeFunction("SetExtendedDNSErrorAction", [](uint16_t infoCode, boost::optional<std::string> extraText) {
+    return std::shared_ptr<DNSAction>(new SetExtendedDNSErrorAction(infoCode, extraText ? *extraText : ""));
+  });
+
+  luaCtx.writeFunction("SetExtendedDNSErrorResponseAction", [](uint16_t infoCode, boost::optional<std::string> extraText) {
+    return std::shared_ptr<DNSResponseAction>(new SetExtendedDNSErrorResponseAction(infoCode, extraText ? *extraText : ""));
+  });
 }
index 057f71c9073a795ef5a3b3de0b5ec8dab738a8a0..933d1720b9904e81327bddb3b26914a7bf46df6d 100644 (file)
@@ -27,6 +27,7 @@
 #include "dnsdist-lua.hh"
 #include "dnsparser.hh"
 
+// NOLINTNEXTLINE(readability-function-cognitive-complexity): this function declares Lua bindings, even with a good refactoring it will likely blow up the threshold
 void setupLuaBindingsDNSQuestion(LuaContext& luaCtx)
 {
 #ifndef DISABLE_NON_FFI_DQ_BINDINGS
@@ -36,10 +37,20 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx)
   luaCtx.registerMember<const DNSName (DNSQuestion::*)>("qname", [](const DNSQuestion& dq) -> const DNSName { return dq.ids.qname; }, [](DNSQuestion& dq, const DNSName& newName) { (void) newName; });
   luaCtx.registerMember<uint16_t (DNSQuestion::*)>("qtype", [](const DNSQuestion& dq) -> uint16_t { return dq.ids.qtype; }, [](DNSQuestion& dq, uint16_t newType) { (void) newType; });
   luaCtx.registerMember<uint16_t (DNSQuestion::*)>("qclass", [](const DNSQuestion& dq) -> uint16_t { return dq.ids.qclass; }, [](DNSQuestion& dq, uint16_t newClass) { (void) newClass; });
-  luaCtx.registerMember<int (DNSQuestion::*)>("rcode", [](const DNSQuestion& dq) -> int { return dq.getHeader()->rcode; }, [](DNSQuestion& dq, int newRCode) { dq.getHeader()->rcode = newRCode; });
+  luaCtx.registerMember<int (DNSQuestion::*)>("rcode", [](const DNSQuestion& dq) -> int { return static_cast<int>(dq.getHeader()->rcode); }, [](DNSQuestion& dq, int newRCode) {
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [newRCode](dnsheader& header) {
+      header.rcode = static_cast<decltype(header.rcode)>(newRCode);
+      return true;
+    });
+  });
   luaCtx.registerMember<const ComboAddress (DNSQuestion::*)>("remoteaddr", [](const DNSQuestion& dq) -> const ComboAddress { return dq.ids.origRemote; }, [](DNSQuestion& dq, const ComboAddress newRemote) { (void) newRemote; });
   /* DNSDist DNSQuestion */
-  luaCtx.registerMember<dnsheader* (DNSQuestion::*)>("dh", [](const DNSQuestion& dq) -> dnsheader* { return const_cast<DNSQuestion&>(dq).getHeader(); }, [](DNSQuestion& dq, const dnsheader* dh) { *(dq.getHeader()) = *dh; });
+  luaCtx.registerMember<dnsheader* (DNSQuestion::*)>("dh", [](const DNSQuestion& dq) -> dnsheader* { return dq.getMutableHeader(); }, [](DNSQuestion& dq, const dnsheader* dh) {
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [&dh](dnsheader& header) {
+      header = *dh;
+      return true;
+    });
+  });
   luaCtx.registerMember<uint16_t (DNSQuestion::*)>("len", [](const DNSQuestion& dq) -> uint16_t { return dq.getData().size(); }, [](DNSQuestion& dq, uint16_t newlen) { dq.getMutableData().resize(newlen); });
   luaCtx.registerMember<uint8_t (DNSQuestion::*)>("opcode", [](const DNSQuestion& dq) -> uint8_t { return dq.getHeader()->opcode; }, [](DNSQuestion& dq, uint8_t newOpcode) { (void) newOpcode; });
   luaCtx.registerMember<bool (DNSQuestion::*)>("tcp", [](const DNSQuestion& dq) -> bool { return dq.overTCP(); }, [](DNSQuestion& dq, bool newTcp) { (void) newTcp; });
@@ -90,7 +101,7 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx)
     dq.ids.d_protoBufData->d_requestorID = newValue;
   });
   luaCtx.registerFunction<bool(DNSQuestion::*)()const>("getDO", [](const DNSQuestion& dq) {
-      return getEDNSZ(dq) & EDNS_HEADER_FLAG_DO;
+    return getEDNSZ(dq) & EDNS_HEADER_FLAG_DO;
     });
   luaCtx.registerFunction<std::string(DNSQuestion::*)()const>("getContent", [](const DNSQuestion& dq) {
     return std::string(reinterpret_cast<const char*>(dq.getData().data()), dq.getData().size());
@@ -100,7 +111,11 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx)
     auto& buffer = dq.getMutableData();
     buffer.clear();
     buffer.insert(buffer.begin(), raw.begin(), raw.end());
-    reinterpret_cast<dnsheader*>(buffer.data())->id = oldID;
+
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(buffer, [oldID](dnsheader& header) {
+      header.id = oldID;
+      return true;
+    });
   });
   luaCtx.registerFunction<std::map<uint16_t, EDNSOptionView>(DNSQuestion::*)()const>("getEDNSOptions", [](const DNSQuestion& dq) {
       if (dq.ednsOptions == nullptr) {
@@ -243,6 +258,15 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx)
     setEDNSOption(dq, code, data);
   });
 
+  luaCtx.registerFunction<void(DNSQuestion::*)(uint16_t infoCode, const boost::optional<std::string>& extraText)>("setExtendedDNSError", [](DNSQuestion& dnsQuestion, uint16_t infoCode, const boost::optional<std::string>& extraText) {
+    EDNSExtendedError ede;
+    ede.infoCode = infoCode;
+    if (extraText) {
+      ede.extraText = *extraText;
+    }
+    dnsQuestion.ids.d_extendedError = std::make_unique<EDNSExtendedError>(ede);
+  });
+
   luaCtx.registerFunction<bool(DNSQuestion::*)(uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs)>("suspend", [](DNSQuestion& dq, uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs) {
     dq.asynchronous = true;
     return dnsdist::suspendQuery(dq, asyncID, queryID, timeoutMs);
@@ -333,9 +357,19 @@ private:
   luaCtx.registerMember<const DNSName (DNSResponse::*)>("qname", [](const DNSResponse& dq) -> const DNSName { return dq.ids.qname; }, [](DNSResponse& dq, const DNSName& newName) { (void) newName; });
   luaCtx.registerMember<uint16_t (DNSResponse::*)>("qtype", [](const DNSResponse& dq) -> uint16_t { return dq.ids.qtype; }, [](DNSResponse& dq, uint16_t newType) { (void) newType; });
   luaCtx.registerMember<uint16_t (DNSResponse::*)>("qclass", [](const DNSResponse& dq) -> uint16_t { return dq.ids.qclass; }, [](DNSResponse& dq, uint16_t newClass) { (void) newClass; });
-  luaCtx.registerMember<int (DNSResponse::*)>("rcode", [](const DNSResponse& dq) -> int { return dq.getHeader()->rcode; }, [](DNSResponse& dq, int newRCode) { dq.getHeader()->rcode = newRCode; });
+  luaCtx.registerMember<int (DNSResponse::*)>("rcode", [](const DNSResponse& dq) -> int { return static_cast<int>(dq.getHeader()->rcode); }, [](DNSResponse& dq, int newRCode) {
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [newRCode](dnsheader& header) {
+      header.rcode = static_cast<decltype(header.rcode)>(newRCode);
+      return true;
+    });
+  });
   luaCtx.registerMember<const ComboAddress (DNSResponse::*)>("remoteaddr", [](const DNSResponse& dq) -> const ComboAddress { return dq.ids.origRemote; }, [](DNSResponse& dq, const ComboAddress newRemote) { (void) newRemote; });
-  luaCtx.registerMember<dnsheader* (DNSResponse::*)>("dh", [](const DNSResponse& dr) -> dnsheader* { return const_cast<DNSResponse&>(dr).getHeader(); }, [](DNSResponse& dr, const dnsheader* dh) { *(dr.getHeader()) = *dh; });
+  luaCtx.registerMember<dnsheader* (DNSResponse::*)>("dh", [](const DNSResponse& dr) -> dnsheader* { return dr.getMutableHeader(); }, [](DNSResponse& dr, const dnsheader* dh) {
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(dr.getMutableData(), [&dh](dnsheader& header) {
+      header = *dh;
+      return true;
+    });
+  });
   luaCtx.registerMember<uint16_t (DNSResponse::*)>("len", [](const DNSResponse& dq) -> uint16_t { return dq.getData().size(); }, [](DNSResponse& dq, uint16_t newlen) { dq.getMutableData().resize(newlen); });
   luaCtx.registerMember<uint8_t (DNSResponse::*)>("opcode", [](const DNSResponse& dq) -> uint8_t { return dq.getHeader()->opcode; }, [](DNSResponse& dq, uint8_t newOpcode) { (void) newOpcode; });
   luaCtx.registerMember<bool (DNSResponse::*)>("tcp", [](const DNSResponse& dq) -> bool { return dq.overTCP(); }, [](DNSResponse& dq, bool newTcp) { (void) newTcp; });
@@ -355,7 +389,10 @@ private:
     auto& buffer = dr.getMutableData();
     buffer.clear();
     buffer.insert(buffer.begin(), raw.begin(), raw.end());
-    reinterpret_cast<dnsheader*>(buffer.data())->id = oldID;
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(buffer, [oldID](dnsheader& header) {
+      header.id = oldID;
+      return true;
+    });
   });
 
   luaCtx.registerFunction<std::map<uint16_t, EDNSOptionView>(DNSResponse::*)()const>("getEDNSOptions", [](const DNSResponse& dq) {
@@ -478,6 +515,15 @@ private:
       return setNegativeAndAdditionalSOA(dq, nxd, DNSName(zone), ttl, DNSName(mname), DNSName(rname), serial, refresh, retry, expire, minimum, false);
     });
 
+  luaCtx.registerFunction<void(DNSResponse::*)(uint16_t infoCode, const boost::optional<std::string>& extraText)>("setExtendedDNSError", [](DNSResponse& dnsResponse, uint16_t infoCode, const boost::optional<std::string>& extraText) {
+    EDNSExtendedError ede;
+    ede.infoCode = infoCode;
+    if (extraText) {
+      ede.extraText = *extraText;
+    }
+    dnsResponse.ids.d_extendedError = std::make_unique<EDNSExtendedError>(ede);
+  });
+
   luaCtx.registerFunction<bool(DNSResponse::*)(uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs)>("suspend", [](DNSResponse& dr, uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs) {
     dr.asynchronous = true;
     return dnsdist::suspendResponse(dr, asyncID, queryID, timeoutMs);
index f778a492ddedaacbc2dd303107bcd0e41d8144bb..3ae4a4e8ecb539a64575ad6d41a3feaca692126e 100644 (file)
@@ -252,7 +252,7 @@ static counts_t exceedRespByterate(unsigned int rate, int seconds)
 
 #endif /* DISABLE_DEPRECATED_DYNBLOCK */
 #endif /* DISABLE_DYNBLOCKS */
-
+// NOLINTNEXTLINE(readability-function-cognitive-complexity): this function declares Lua bindings, even with a good refactoring it will likely blow up the threshold
 void setupLuaInspection(LuaContext& luaCtx)
 {
 #ifndef DISABLE_TOP_N_BINDINGS
@@ -728,7 +728,9 @@ void setupLuaInspection(LuaContext& luaCtx)
 
   luaCtx.writeFunction("requestDoHStatesDump", [] {
     setLuaNoSideEffect();
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
     g_dohStatesDumpRequested += g_dohClientThreads->getThreadsCount();
+#endif
   });
 
   luaCtx.writeFunction("dumpStats", [] {
@@ -916,6 +918,19 @@ void setupLuaInspection(LuaContext& luaCtx)
         group->includeRange(Netmask(*boost::get<std::string>(&ranges)));
       }
     });
+  luaCtx.registerFunction<void(std::shared_ptr<DynBlockRulesGroup>::*)(boost::variant<std::string, LuaArray<std::string>, NetmaskGroup>)>("removeRange", [](std::shared_ptr<DynBlockRulesGroup>& group, boost::variant<std::string, LuaArray<std::string>, NetmaskGroup> ranges) {
+      if (ranges.type() == typeid(LuaArray<std::string>)) {
+        for (const auto& range : *boost::get<LuaArray<std::string>>(&ranges)) {
+          group->removeRange(Netmask(range.second));
+        }
+      }
+      else if (ranges.type() == typeid(NetmaskGroup)) {
+        group->removeRange(*boost::get<NetmaskGroup>(&ranges));
+      }
+      else {
+        group->removeRange(Netmask(*boost::get<std::string>(&ranges)));
+      }
+    });
   luaCtx.registerFunction<void(std::shared_ptr<DynBlockRulesGroup>::*)(LuaTypeOrArrayOf<std::string>)>("excludeDomains", [](std::shared_ptr<DynBlockRulesGroup>& group, LuaTypeOrArrayOf<std::string> domains) {
       if (domains.type() == typeid(LuaArray<std::string>)) {
         for (const auto& range : *boost::get<LuaArray<std::string>>(&domains)) {
index 2495b4a9ee8e2cd259dfd9ce3a21d986abc9ef3a..37f04218cc6643f56c6d0fe06a519a6cddbaff2d 100644 (file)
@@ -131,23 +131,27 @@ static void rmRule(GlobalStateHolder<vector<T> > *someRuleActions, const boost::
   if (auto str = boost::get<std::string>(&id)) {
     try {
       const auto uuid = getUniqueID(*str);
-      if (rules.erase(std::remove_if(rules.begin(),
+      auto removeIt = std::remove_if(rules.begin(),
                                      rules.end(),
-                                     [uuid](const T& a) { return a.d_id == uuid; }),
-                      rules.end()) == rules.end()) {
+                                     [&uuid](const T& rule) { return rule.d_id == uuid; });
+      if (removeIt == rules.end()) {
         g_outputBuffer = "Error: no rule matched\n";
         return;
       }
+      rules.erase(removeIt,
+                  rules.end());
     }
     catch (const std::runtime_error& e) {
       /* it was not an UUID, let's see if it was a name instead */
-      if (rules.erase(std::remove_if(rules.begin(),
+      auto removeIt = std::remove_if(rules.begin(),
                                      rules.end(),
-                                     [&str](const T& a) { return a.d_name == *str; }),
-                      rules.end()) == rules.end()) {
+                                     [&str](const T& rule) { return rule.d_name == *str; });
+      if (removeIt == rules.end()) {
         g_outputBuffer = "Error: no rule matched\n";
         return;
       }
+      rules.erase(removeIt,
+                  rules.end());
     }
   }
   else if (auto pos = boost::get<unsigned int>(&id)) {
index e39748e8c2ad2f735fefec183891e322390bc86b..2b47f26007f7a4a65028d14e470830e62d5fa259 100644 (file)
@@ -544,8 +544,8 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
                            tlsCtx = getTLSContext(config.d_tlsParams);
 
                            if (getOptionalValue<std::string>(vars, "dohPath", valueStr) > 0) {
-#ifndef HAVE_NGHTTP2
-                             throw std::runtime_error("Outgoing DNS over HTTPS support requested (via 'dohPath' on newServer()) but nghttp2 support is not available");
+#if !defined(HAVE_DNS_OVER_HTTPS) || !defined(HAVE_NGHTTP2)
+                             throw std::runtime_error("Outgoing DNS over HTTPS support requested (via 'dohPath' on newServer()) but it is not available");
 #endif
 
                              serverPort = 443;
@@ -1332,6 +1332,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
     setTCPDownstreamMaxIdleConnectionsPerBackend(max);
   });
 
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
   luaCtx.writeFunction("setMaxIdleDoHConnectionsPerDownstream", [](uint64_t max) {
     setDoHDownstreamMaxIdleConnectionsPerBackend(max);
   });
@@ -1342,6 +1343,7 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
     }
     g_outgoingDoHWorkerThreads = workers;
   });
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
 
   luaCtx.writeFunction("setOutgoingTLSSessionsCacheMaxTicketsPerBackend", [](uint64_t max) {
     if (!checkConfigurationTime("setOutgoingTLSSessionsCacheMaxTicketsPerBackend")) {
@@ -1859,33 +1861,37 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
       return;
     }
 
-    DIR* dirp;
-    struct dirent* ent;
     std::vector<std::string> files;
-    if (!(dirp = opendir(dirname.c_str()))) {
-      errlog("Error opening the included directory %s!", dirname.c_str());
-      g_outputBuffer = "Error opening the included directory " + dirname + "!";
-      return;
-    }
-
-    while ((ent = readdir(dirp)) != NULL) {
-      if (ent->d_name[0] == '.') {
-        continue;
+    {
+      auto dirHandle = std::unique_ptr<DIR, decltype(&closedir)>(opendir(dirname.c_str()), closedir);
+      if (!dirHandle) {
+        errlog("Error opening the included directory %s!", dirname.c_str());
+        g_outputBuffer = "Error opening the included directory " + dirname + "!";
+        return;
       }
 
-      if (boost::ends_with(ent->d_name, ".conf")) {
-        std::ostringstream namebuf;
-        namebuf << dirname << "/" << ent->d_name;
-
-        if (stat(namebuf.str().c_str(), &st) || !S_ISREG(st.st_mode)) {
+      struct dirent* ent = nullptr;
+      // NOLINTNEXTLINE(concurrency-mt-unsafe): readdir is thread-safe nowadays and readdir_r is deprecated
+      while ((ent = readdir(dirHandle.get())) != nullptr) {
+        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay): this is what dirent is
+        if (ent->d_name[0] == '.') {
           continue;
         }
 
-        files.push_back(namebuf.str());
+        if (boost::ends_with(ent->d_name, ".conf")) {
+          std::ostringstream namebuf;
+          // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay): this is what dirent is
+          namebuf << dirname << "/" << ent->d_name;
+
+          if (stat(namebuf.str().c_str(), &st) != 0 || !S_ISREG(st.st_mode)) {
+            continue;
+          }
+
+          files.push_back(namebuf.str());
+        }
       }
     }
 
-    closedir(dirp);
     std::sort(files.begin(), files.end());
 
     g_included = true;
@@ -2120,11 +2126,13 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
     setTCPDownstreamCleanupInterval(interval);
   });
 
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
   luaCtx.writeFunction("setDoHDownstreamCleanupInterval", [](uint64_t interval) {
     setLuaSideEffect();
     checkParameterBound("setDoHDownstreamCleanupInterval", interval);
     setDoHDownstreamCleanupInterval(interval);
   });
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
 
   luaCtx.writeFunction("setTCPDownstreamMaxIdleTime", [](uint64_t max) {
     setLuaSideEffect();
@@ -2132,11 +2140,13 @@ static void setupLuaConfig(LuaContext& luaCtx, bool client, bool configCheck)
     setTCPDownstreamMaxIdleTime(max);
   });
 
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
   luaCtx.writeFunction("setDoHDownstreamMaxIdleTime", [](uint64_t max) {
     setLuaSideEffect();
     checkParameterBound("setDoHDownstreamMaxIdleTime", max);
     setDoHDownstreamMaxIdleTime(max);
   });
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
 
   luaCtx.writeFunction("setConsoleConnectionsLogging", [](bool enabled) {
     g_logConsoleConnections = enabled;
index 3d118508cd3e26d92b6aebe35f6dcb1a2f719e5c..9ef56c62c1aa0730f57e265b85b48b5f0ae04e95 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "dnsdist.hh"
 #include "dnsdist-concurrent-connections.hh"
+#include "dnsdist-dnsparser.hh"
 #include "dnsdist-ecs.hh"
 #include "dnsdist-nghttp2-in.hh"
 #include "dnsdist-proxy-protocol.hh"
@@ -511,7 +512,7 @@ void IncomingTCPConnectionState::handleResponse(const struct timeval& now, TCPRe
       DNSResponse dr(ids, response.d_buffer, ds);
       dr.d_incomingTCPState = state;
 
-      memcpy(&response.d_cleartextDH, dr.getHeader(), sizeof(response.d_cleartextDH));
+      memcpy(&response.d_cleartextDH, dr.getHeader().get(), sizeof(response.d_cleartextDH));
 
       if (!processResponse(response.d_buffer, *state->d_threadData.localRespRuleActions, *state->d_threadData.localCacheInsertedRespRuleActions, dr, false)) {
         state->terminateClientConnection();
@@ -668,16 +669,19 @@ IncomingTCPConnectionState::QueryProcessingResult IncomingTCPConnectionState::ha
 
   {
     /* this pointer will be invalidated the second the buffer is resized, don't hold onto it! */
-    auto* dh = reinterpret_cast<dnsheader*>(query.data());
-    if (!checkQueryHeaders(dh, *d_ci.cs)) {
+    const dnsheader_aligned dh(query.data());
+    if (!checkQueryHeaders(dh.get(), *d_ci.cs)) {
       return QueryProcessingResult::InvalidHeaders;
     }
 
     if (dh->qdcount == 0) {
       TCPResponse response;
-      dh->rcode = RCode::NotImp;
-      dh->qr = true;
       auto queryID = dh->id;
+      dnsdist::PacketMangling::editDNSHeaderFromPacket(query, [](dnsheader& header) {
+        header.rcode = RCode::NotImp;
+        header.qr = true;
+        return true;
+      });
       response.d_idstate = std::move(ids);
       response.d_idstate.origID = queryID;
       response.d_idstate.selfGenerated = true;
@@ -696,8 +700,11 @@ IncomingTCPConnectionState::QueryProcessingResult IncomingTCPConnectionState::ha
   }
 
   DNSQuestion dq(ids, query);
-  const uint16_t* flags = getFlagsFromDNSHeader(dq.getHeader());
-  ids.origFlags = *flags;
+  dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [&ids](dnsheader& header) {
+    const uint16_t* flags = getFlagsFromDNSHeader(&header);
+    ids.origFlags = *flags;
+    return true;
+  });
   dq.d_incomingTCPState = state;
   dq.sni = d_handler.getServerNameIndication();
 
@@ -714,7 +721,7 @@ IncomingTCPConnectionState::QueryProcessingResult IncomingTCPConnectionState::ha
   if (forwardViaUDPFirst()) {
     // if there was no EDNS, we add it with a large buffer size
     // so we can use UDP to talk to the backend.
-    auto dh = const_cast<struct dnsheader*>(reinterpret_cast<const struct dnsheader*>(query.data()));
+    const dnsheader_aligned dh(query.data());
     if (!dh->arcount) {
       if (addEDNS(query, 4096, false, 4096, 0)) {
         dq.ids.ednsAdded = true;
@@ -747,15 +754,15 @@ IncomingTCPConnectionState::QueryProcessingResult IncomingTCPConnectionState::ha
   // the buffer might have been invalidated by now
   uint16_t queryID;
   {
-    const dnsheader* dh = dq.getHeader();
+    const auto dh = dq.getHeader();
     queryID = dh->id;
   }
 
   if (result == ProcessQueryResult::SendAnswer) {
     TCPResponse response;
     {
-      const dnsheader* dh = dq.getHeader();
-      memcpy(&response.d_cleartextDH, dh, sizeof(response.d_cleartextDH));
+      const auto dh = dq.getHeader();
+      memcpy(&response.d_cleartextDH, dh.get(), sizeof(response.d_cleartextDH));
     }
     response.d_idstate = std::move(ids);
     response.d_idstate.origID = queryID;
@@ -1245,10 +1252,10 @@ static void handleIncomingTCPQuery(int pipefd, FDMultiplexer::funcparam_t& param
   gettimeofday(&now, nullptr);
 
   if (citmp->cs->dohFrontend) {
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
     auto state = std::make_shared<IncomingHTTP2Connection>(std::move(*citmp), *threadData, now);
     state->handleIO();
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
   }
   else {
     auto state = std::make_shared<IncomingTCPConnectionState>(std::move(*citmp), *threadData, now);
@@ -1399,7 +1406,7 @@ static void tcpClientThread(pdns::channel::Receiver<ConnectionInfo>&& queryRecei
                 state->handleTimeout(state, false);
               }
             }
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
             else if (cbData.second.type() == typeid(std::shared_ptr<IncomingHTTP2Connection>)) {
               auto state = boost::any_cast<std::shared_ptr<IncomingHTTP2Connection>>(cbData.second);
               if (cbData.first == state->d_handler.getDescriptor()) {
@@ -1408,7 +1415,7 @@ static void tcpClientThread(pdns::channel::Receiver<ConnectionInfo>&& queryRecei
                 state->handleTimeout(parentState, false);
               }
             }
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
             else if (cbData.second.type() == typeid(std::shared_ptr<TCPConnectionToBackend>)) {
               auto conn = boost::any_cast<std::shared_ptr<TCPConnectionToBackend>>(cbData.second);
               vinfolog("Timeout (read) from remote backend %s", conn->getBackendName());
@@ -1425,7 +1432,7 @@ static void tcpClientThread(pdns::channel::Receiver<ConnectionInfo>&& queryRecei
                 state->handleTimeout(state, true);
               }
             }
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
             else if (cbData.second.type() == typeid(std::shared_ptr<IncomingHTTP2Connection>)) {
               auto state = boost::any_cast<std::shared_ptr<IncomingHTTP2Connection>>(cbData.second);
               if (cbData.first == state->d_handler.getDescriptor()) {
@@ -1434,7 +1441,7 @@ static void tcpClientThread(pdns::channel::Receiver<ConnectionInfo>&& queryRecei
                 state->handleTimeout(parentState, true);
               }
             }
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
             else if (cbData.second.type() == typeid(std::shared_ptr<TCPConnectionToBackend>)) {
               auto conn = boost::any_cast<std::shared_ptr<TCPConnectionToBackend>>(cbData.second);
               vinfolog("Timeout (write) from remote backend %s", conn->getBackendName());
@@ -1465,12 +1472,12 @@ static void tcpClientThread(pdns::channel::Receiver<ConnectionInfo>&& queryRecei
                   auto state = boost::any_cast<std::shared_ptr<IncomingTCPConnectionState>>(param);
                   infolog(" - %s", state->toString());
                 }
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
                 else if (param.type() == typeid(std::shared_ptr<IncomingHTTP2Connection>)) {
                   auto state = boost::any_cast<std::shared_ptr<IncomingHTTP2Connection>>(param);
                   infolog(" - %s", state->toString());
                 }
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
                 else if (param.type() == typeid(std::shared_ptr<TCPConnectionToBackend>)) {
                   auto conn = boost::any_cast<std::shared_ptr<TCPConnectionToBackend>>(param);
                   infolog(" - %s", conn->toString());
@@ -1570,10 +1577,10 @@ static void acceptNewConnection(const TCPAcceptorParam& param, TCPClientThreadDa
       gettimeofday(&now, nullptr);
 
       if (ci.cs->dohFrontend) {
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
         auto state = std::make_shared<IncomingHTTP2Connection>(std::move(ci), *threadData, now);
         state->handleIO();
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
       }
       else {
         auto state = std::make_shared<IncomingTCPConnectionState>(std::move(ci), *threadData, now);
index 69f543621e5062edbc0445e6d59c83918d05379a..d0890b5462de8bd3b6db961db71638e29c533be2 100644 (file)
@@ -36,6 +36,7 @@
 #include "dnsdist-healthchecks.hh"
 #include "dnsdist-metrics.hh"
 #include "dnsdist-prometheus.hh"
+#include "dnsdist-rings.hh"
 #include "dnsdist-web.hh"
 #include "dolog.hh"
 #include "gettime.hh"
@@ -176,6 +177,10 @@ std::map<std::string, MetricDefinition> MetricDefinitionStorage::metrics{
   { "latency-doh-avg1000",                   MetricDefinition(PrometheusMetricType::gauge,   "Average response latency, in microseconds, of the last 1000 packets received over DoH")},
   { "latency-doh-avg10000",                  MetricDefinition(PrometheusMetricType::gauge,   "Average response latency, in microseconds, of the last 10000 packets received over DoH")},
   { "latency-doh-avg1000000",                MetricDefinition(PrometheusMetricType::gauge,   "Average response latency, in microseconds, of the last 1000000 packets received over DoH")},
+  { "latency-doq-avg100",                    MetricDefinition(PrometheusMetricType::gauge,   "Average response latency, in microseconds, of the last 100 packets received over DoQ")},
+  { "latency-doq-avg1000",                   MetricDefinition(PrometheusMetricType::gauge,   "Average response latency, in microseconds, of the last 1000 packets received over DoQ")},
+  { "latency-doq-avg10000",                  MetricDefinition(PrometheusMetricType::gauge,   "Average response latency, in microseconds, of the last 10000 packets received over DoQ")},
+  { "latency-doq-avg1000000",                MetricDefinition(PrometheusMetricType::gauge,   "Average response latency, in microseconds, of the last 1000000 packets received over DoQ")},
   { "uptime",                                MetricDefinition(PrometheusMetricType::gauge,   "Uptime of the dnsdist process in seconds")},
   { "real-memory-usage",                     MetricDefinition(PrometheusMetricType::gauge,   "Current memory usage in bytes")},
   { "noncompliant-queries",                  MetricDefinition(PrometheusMetricType::counter, "Number of queries dropped as non-compliant")},
@@ -1625,6 +1630,104 @@ static void handleCacheManagement(const YaHTTP::Request& req, YaHTTP::Response&
 }
 #endif /* DISABLE_WEB_CACHE_MANAGEMENT */
 
+template<typename T> static void addRingEntryToList(const struct timespec& now, Json::array& list, const T& entry)
+{
+  constexpr bool response = std::is_same_v<T, Rings::Response>;
+  Json::object tmp{
+    { "age", static_cast<double>(DiffTime(entry.when, now)) },
+    { "id", ntohs(entry.dh.id) },
+    { "name", entry.name.toString() },
+    { "requestor", entry.requestor.toStringWithPort() },
+    { "size", static_cast<int>(entry.size) },
+    { "qtype", entry.qtype },
+    { "protocol", entry.protocol.toString() },
+    { "rd", static_cast<bool>(entry.dh.rd) },
+  };
+  if constexpr (!response) {
+#if defined(DNSDIST_RINGS_WITH_MACADDRESS)
+    tmp.emplace("mac", entry.hasmac ? std::string(reinterpret_cast<const char*>(entry.macaddress.data()), entry.macaddress.size()) : std::string());
+#endif
+  }
+  else {
+    tmp.emplace("latency", static_cast<double>(entry.usec));
+    tmp.emplace("rcode", static_cast<uint8_t>(entry.dh.rcode));
+    tmp.emplace("tc", static_cast<bool>(entry.dh.tc));
+    tmp.emplace("aa", static_cast<bool>(entry.dh.aa));
+    tmp.emplace("answers", ntohs(entry.dh.ancount));
+    auto server = entry.ds.toStringWithPort();
+    tmp.emplace("backend", server != "0.0.0.0:0" ? std::move(server) : "Cache");
+  }
+  list.push_back(std::move(tmp));
+}
+
+static void handleRings(const YaHTTP::Request& req, YaHTTP::Response& resp)
+{
+  handleCORS(req, resp);
+
+  std::optional<size_t> maxNumberOfQueries{std::nullopt};
+  std::optional<size_t> maxNumberOfResponses{std::nullopt};
+
+  const auto maxQueries = req.getvars.find("maxQueries");
+  if (maxQueries != req.getvars.end()) {
+    try {
+      maxNumberOfQueries = pdns::checked_stoi<size_t>(maxQueries->second);
+    }
+    catch (const std::exception& exp) {
+      vinfolog("Error parsing the 'maxQueries' value from rings HTTP GET query: %s", exp.what());
+    }
+  }
+
+  const auto maxResponses = req.getvars.find("maxResponses");
+  if (maxResponses != req.getvars.end()) {
+    try {
+      maxNumberOfResponses = pdns::checked_stoi<size_t>(maxResponses->second);
+    }
+    catch (const std::exception& exp) {
+      vinfolog("Error parsing the 'maxResponses' value from rings HTTP GET query: %s", exp.what());
+    }
+  }
+
+  resp.status = 200;
+
+  Json::object doc;
+  size_t numberOfQueries = 0;
+  size_t numberOfResponses = 0;
+  Json::array queries;
+  Json::array responses;
+  struct timespec now
+  {
+  };
+  gettime(&now);
+
+  for (const auto& shard : g_rings.d_shards) {
+    if (!maxNumberOfQueries || numberOfQueries < *maxNumberOfQueries) {
+      auto queryRing = shard->queryRing.lock();
+      for (const auto& entry : *queryRing) {
+        addRingEntryToList(now, queries, entry);
+        numberOfQueries++;
+        if (maxNumberOfQueries && numberOfQueries >= *maxNumberOfQueries) {
+          break;
+        }
+      }
+    }
+    if (!maxNumberOfResponses || numberOfResponses < *maxNumberOfResponses) {
+      auto responseRing = shard->respRing.lock();
+      for (const auto& entry : *responseRing) {
+        addRingEntryToList(now, responses, entry);
+        numberOfResponses++;
+        if (maxNumberOfResponses && numberOfResponses >= *maxNumberOfResponses) {
+          break;
+        }
+      }
+    }
+  }
+  doc.emplace("queries", std::move(queries));
+  doc.emplace("responses", std::move(responses));
+  Json my_json = doc;
+  resp.body = my_json.dump();
+  resp.headers["Content-Type"] = "application/json";
+}
+
 static std::unordered_map<std::string, std::function<void(const YaHTTP::Request&, YaHTTP::Response&)>> s_webHandlers;
 
 void registerWebHandler(const std::string& endpoint, std::function<void(const YaHTTP::Request&, YaHTTP::Response&)> handler);
@@ -1689,6 +1792,7 @@ void registerBuiltInWebHandlers()
   registerWebHandler("/api/v1/servers/localhost", handleStats);
   registerWebHandler("/api/v1/servers/localhost/pool", handlePoolStats);
   registerWebHandler("/api/v1/servers/localhost/statistics", handleStatsOnly);
+  registerWebHandler("/api/v1/servers/localhost/rings", handleRings);
 #ifndef DISABLE_WEB_CONFIG
   registerWebHandler("/api/v1/servers/localhost/config", handleConfigDump);
   registerWebHandler("/api/v1/servers/localhost/config/allow-from", handleAllowFrom);
index 6f4cba5315815ebc07c1c9fa53ccdc0ab0aaffcc..eb2ba5785571ccee55431742b320a6e468c24e38 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "dnsdist-xpf.hh"
 
+#include "dnsdist-dnsparser.hh"
 #include "dnsparser.hh"
 #include "xpf.hh"
 
@@ -54,7 +55,9 @@ bool addXPF(DNSQuestion& dq, uint16_t optionCode)
   pos += payload.size();
   (void) pos;
 
-  dq.getHeader()->arcount = htons(ntohs(dq.getHeader()->arcount) + 1);
-
+  dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [](dnsheader& header) {
+    header.arcount = htons(ntohs(header.arcount) + 1);
+    return true;
+  });
   return true;
 }
index ec4ca88ac07ea594feaff27b110a255a77cf040f..b07713885097520160ce2728f51cc1e4695ab409 100644 (file)
 #include "dnsdist-carbon.hh"
 #include "dnsdist-console.hh"
 #include "dnsdist-discovery.hh"
+#include "dnsdist-dnsparser.hh"
 #include "dnsdist-dynblocks.hh"
 #include "dnsdist-ecs.hh"
+#include "dnsdist-edns.hh"
 #include "dnsdist-healthchecks.hh"
 #include "dnsdist-lua.hh"
 #include "dnsdist-nghttp2.hh"
@@ -197,8 +199,12 @@ static void truncateTC(PacketBuffer& packet, size_t maximumSize, unsigned int qn
     }
 
     packet.resize(static_cast<uint16_t>(sizeof(dnsheader)+qnameWireLength+DNS_TYPE_SIZE+DNS_CLASS_SIZE));
-    struct dnsheader* dh = reinterpret_cast<struct dnsheader*>(packet.data());
-    dh->ancount = dh->arcount = dh->nscount = 0;
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(packet, [](dnsheader& header) {
+      header.ancount = 0;
+      header.arcount = 0;
+      header.nscount = 0;
+      return true;
+    });
 
     if (hadEDNS) {
       addEDNS(packet, maximumSize, z & EDNS_HEADER_FLAG_DO, payloadSize, 0);
@@ -232,8 +238,9 @@ static std::unique_ptr<DelayPipe<DelayedPacket>> g_delay{nullptr};
 
 std::string DNSQuestion::getTrailingData() const
 {
-  const char* message = reinterpret_cast<const char*>(this->getHeader());
-  const uint16_t messageLen = getDNSPacketLength(message, this->data.size());
+  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+  const auto* message = reinterpret_cast<const char*>(this->getData().data());
+  const uint16_t messageLen = getDNSPacketLength(message, this->getData().size());
   return std::string(message + messageLen, this->getData().size() - messageLen);
 }
 
@@ -251,6 +258,14 @@ bool DNSQuestion::setTrailingData(const std::string& tail)
   return true;
 }
 
+bool DNSQuestion::editHeader(const std::function<bool(dnsheader&)>& editFunction)
+{
+  if (data.size() < sizeof(dnsheader)) {
+    throw std::runtime_error("Trying to access the dnsheader of a too small (" + std::to_string(data.size()) + ") DNSQuestion buffer");
+  }
+  return dnsdist::PacketMangling::editDNSHeaderFromPacket(data, editFunction);
+}
+
 static void doLatencyStats(dnsdist::Protocol protocol, double udiff)
 {
   constexpr auto doAvg = [](double& var, double n, double weight) {
@@ -303,6 +318,12 @@ static void doLatencyStats(dnsdist::Protocol protocol, double udiff)
     doAvg(dnsdist::metrics::g_stats.latencyDoHAvg10000,   udiff,   10000);
     doAvg(dnsdist::metrics::g_stats.latencyDoHAvg1000000, udiff, 1000000);
   }
+  else if (protocol == dnsdist::Protocol::DoQ) {
+    doAvg(dnsdist::metrics::g_stats.latencyDoQAvg100,     udiff,     100);
+    doAvg(dnsdist::metrics::g_stats.latencyDoQAvg1000,    udiff,    1000);
+    doAvg(dnsdist::metrics::g_stats.latencyDoQAvg10000,   udiff,   10000);
+    doAvg(dnsdist::metrics::g_stats.latencyDoQAvg1000000, udiff, 1000000);
+  }
 }
 
 bool responseContentMatches(const PacketBuffer& response, const DNSName& qname, const uint16_t qtype, const uint16_t qclass, const std::shared_ptr<DownstreamState>& remote, unsigned int& qnameWireLength)
@@ -311,7 +332,7 @@ bool responseContentMatches(const PacketBuffer& response, const DNSName& qname,
     return false;
   }
 
-  const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(response.data());
+  const dnsheader_aligned dh(response.data());
   if (dh->qr == 0) {
     ++dnsdist::metrics::g_stats.nonCompliantResponses;
     if (remote) {
@@ -370,11 +391,14 @@ static void restoreFlags(struct dnsheader* dh, uint16_t origFlags)
   *flags |= origFlags;
 }
 
-static bool fixUpQueryTurnedResponse(DNSQuestion& dq, const uint16_t origFlags)
+static bool fixUpQueryTurnedResponse(DNSQuestion& dnsQuestion, const uint16_t origFlags)
 {
-  restoreFlags(dq.getHeader(), origFlags);
+  dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsQuestion.getMutableData(), [origFlags](dnsheader& header) {
+    restoreFlags(&header, origFlags);
+    return true;
+  });
 
-  return addEDNSToQueryTurnedResponse(dq);
+  return addEDNSToQueryTurnedResponse(dnsQuestion);
 }
 
 static bool fixUpResponse(PacketBuffer& response, const DNSName& qname, uint16_t origFlags, bool ednsAdded, bool ecsAdded, bool* zeroScope)
@@ -383,8 +407,10 @@ static bool fixUpResponse(PacketBuffer& response, const DNSName& qname, uint16_t
     return false;
   }
 
-  struct dnsheader* dh = reinterpret_cast<struct dnsheader*>(response.data());
-  restoreFlags(dh, origFlags);
+  dnsdist::PacketMangling::editDNSHeaderFromPacket(response, [origFlags](dnsheader& header) {
+    restoreFlags(&header, origFlags);
+    return true;
+  });
 
   if (response.size() == sizeof(dnsheader)) {
     return true;
@@ -422,10 +448,12 @@ static bool fixUpResponse(PacketBuffer& response, const DNSName& qname, uint16_t
         if (last) {
           /* simply remove the last AR */
           response.resize(response.size() - optLen);
-          dh = reinterpret_cast<struct dnsheader*>(response.data());
-          uint16_t arcount = ntohs(dh->arcount);
-          arcount--;
-          dh->arcount = htons(arcount);
+          dnsdist::PacketMangling::editDNSHeaderFromPacket(response, [](dnsheader& header) {
+            uint16_t arcount = ntohs(header.arcount);
+            arcount--;
+            header.arcount = htons(arcount);
+            return true;
+          });
         }
         else {
           /* Removing an intermediary RR could lead to compression error */
@@ -499,7 +527,10 @@ static bool applyRulesToResponse(const std::vector<DNSDistResponseRuleAction>& r
         return true;
         break;
       case DNSResponseAction::Action::ServFail:
-        dr.getHeader()->rcode = RCode::ServFail;
+        dnsdist::PacketMangling::editDNSHeaderFromPacket(dr.getMutableData(), [](dnsheader& header) {
+          header.rcode = RCode::ServFail;
+          return true;
+        });
         return true;
         break;
         /* non-terminal actions follow */
@@ -556,6 +587,10 @@ bool processResponseAfterRules(PacketBuffer& response, const std::vector<DNSDist
     ac(&dr, &result);
   }
 
+  if (dr.ids.d_extendedError) {
+    dnsdist::edns::addExtendedDNSError(dr.getMutableData(), dr.getMaximumSize(), dr.ids.d_extendedError->infoCode, dr.ids.d_extendedError->extraText);
+  }
+
 #ifdef HAVE_DNSCRYPT
   if (!muted) {
     if (!encryptResponse(response, dr.getMaximumSize(), dr.overTCP(), dr.ids.dnsCryptQuery)) {
@@ -660,7 +695,10 @@ static void handleResponseForUDPClient(InternalQueryState& ids, PacketBuffer& re
   if (ids.udpPayloadSize > 0 && response.size() > ids.udpPayloadSize) {
     vinfolog("Got a response of size %d while the initial UDP payload size was %d, truncating", response.size(), ids.udpPayloadSize);
     truncateTC(dr.getMutableData(), dr.getMaximumSize(), dr.ids.qname.wirelength());
-    dr.getHeader()->tc = true;
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(dr.getMutableData(), [](dnsheader& header) {
+      header.tc = true;
+      return true;
+    });
   }
   else if (dr.getHeader()->tc && g_truncateTC) {
     truncateTC(response, dr.getMaximumSize(), dr.ids.qname.wirelength());
@@ -669,7 +707,7 @@ static void handleResponseForUDPClient(InternalQueryState& ids, PacketBuffer& re
   /* when the answer is encrypted in place, we need to get a copy
      of the original header before encryption to fill the ring buffer */
   dnsheader cleartextDH;
-  memcpy(&cleartextDH, dr.getHeader(), sizeof(cleartextDH));
+  memcpy(&cleartextDH, dr.getHeader().get(), sizeof(cleartextDH));
 
   if (!isAsync) {
     if (!processResponse(response, respRuleActions, cacheInsertedRespRuleActions, dr, ids.cs && ids.cs->muted)) {
@@ -759,7 +797,7 @@ void responderThread(std::shared_ptr<DownstreamState> dss)
         }
 
         response.resize(static_cast<size_t>(got));
-        dnsheader* dh = reinterpret_cast<struct dnsheader*>(response.data());
+        const dnsheader_aligned dh(response.data());
         queryId = dh->id;
 
         auto ids = dss->getState(queryId);
@@ -775,7 +813,10 @@ void responderThread(std::shared_ptr<DownstreamState> dss)
 
         auto du = std::move(ids->du);
 
-        dh->id = ids->origID;
+        dnsdist::PacketMangling::editDNSHeaderFromPacket(response, [&ids](dnsheader& header) {
+          header.id = ids->origID;
+          return true;
+        });
         ++dss->responses;
 
         double udiff = ids->queryRealTime.udiff();
@@ -869,7 +910,15 @@ bool processRulesResult(const DNSAction::Action& action, DNSQuestion& dq, std::s
     return false;
   }
 
-  switch(action) {
+  auto setRCode = [&dq](uint8_t rcode) {
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [rcode](dnsheader& header) {
+      header.rcode = rcode;
+      header.qr = true;
+      return true;
+    });
+  };
+
+  switch (action) {
   case DNSAction::Action::Allow:
     return true;
     break;
@@ -879,18 +928,15 @@ bool processRulesResult(const DNSAction::Action& action, DNSQuestion& dq, std::s
     return true;
     break;
   case DNSAction::Action::Nxdomain:
-    dq.getHeader()->rcode = RCode::NXDomain;
-    dq.getHeader()->qr = true;
+    setRCode(RCode::NXDomain);
     return true;
     break;
   case DNSAction::Action::Refused:
-    dq.getHeader()->rcode = RCode::Refused;
-    dq.getHeader()->qr = true;
+    setRCode(RCode::Refused);
     return true;
     break;
   case DNSAction::Action::ServFail:
-    dq.getHeader()->rcode = RCode::ServFail;
-    dq.getHeader()->qr = true;
+    setRCode(RCode::ServFail);
     return true;
     break;
   case DNSAction::Action::Spoof:
@@ -907,11 +953,14 @@ bool processRulesResult(const DNSAction::Action& action, DNSQuestion& dq, std::s
     break;
   case DNSAction::Action::Truncate:
     if (!dq.overTCP()) {
-      dq.getHeader()->tc = true;
-      dq.getHeader()->qr = true;
-      dq.getHeader()->ra = dq.getHeader()->rd;
-      dq.getHeader()->aa = false;
-      dq.getHeader()->ad = false;
+      dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [](dnsheader& header) {
+        header.tc = true;
+        header.qr = true;
+        header.ra = header.rd;
+        header.aa = false;
+        header.ad = false;
+        return true;
+      });
       ++dnsdist::metrics::g_stats.ruleTruncated;
       return true;
     }
@@ -926,7 +975,10 @@ bool processRulesResult(const DNSAction::Action& action, DNSQuestion& dq, std::s
     return true;
     break;
   case DNSAction::Action::NoRecurse:
-    dq.getHeader()->rd = false;
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [](dnsheader& header) {
+      header.rd = false;
+      return true;
+    });
     return true;
     break;
     /* non-terminal actions follow */
@@ -968,6 +1020,14 @@ static bool applyRulesToQuery(LocalHolders& holders, DNSQuestion& dq, const stru
   }
 
 #ifndef DISABLE_DYNBLOCKS
+  auto setRCode = [&dq](uint8_t rcode) {
+    dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [rcode](dnsheader& header) {
+      header.rcode = rcode;
+      header.qr = true;
+      return true;
+    });
+  };
+
   /* the Dynamic Block mechanism supports address and port ranges, so we need to pass the full address and port */
   if (auto got = holders.dynNMGBlock->lookup(AddressAndPortRange(dq.ids.origRemote, dq.ids.origRemote.isIPv4() ? 32 : 128, 16))) {
     auto updateBlockStats = [&got]() {
@@ -980,6 +1040,7 @@ static bool applyRulesToQuery(LocalHolders& holders, DNSQuestion& dq, const stru
       if (action == DNSAction::Action::None) {
         action = g_dynBlockAction;
       }
+
       switch (action) {
       case DNSAction::Action::NoOp:
         /* do nothing */
@@ -989,27 +1050,28 @@ static bool applyRulesToQuery(LocalHolders& holders, DNSQuestion& dq, const stru
         vinfolog("Query from %s turned into NXDomain because of dynamic block", dq.ids.origRemote.toStringWithPort());
         updateBlockStats();
 
-        dq.getHeader()->rcode = RCode::NXDomain;
-        dq.getHeader()->qr=true;
+        setRCode(RCode::NXDomain);
         return true;
 
       case DNSAction::Action::Refused:
         vinfolog("Query from %s refused because of dynamic block", dq.ids.origRemote.toStringWithPort());
         updateBlockStats();
 
-        dq.getHeader()->rcode = RCode::Refused;
-        dq.getHeader()->qr = true;
+        setRCode(RCode::Refused);
         return true;
 
       case DNSAction::Action::Truncate:
         if (!dq.overTCP()) {
           updateBlockStats();
           vinfolog("Query from %s truncated because of dynamic block", dq.ids.origRemote.toStringWithPort());
-          dq.getHeader()->tc = true;
-          dq.getHeader()->qr = true;
-          dq.getHeader()->ra = dq.getHeader()->rd;
-          dq.getHeader()->aa = false;
-          dq.getHeader()->ad = false;
+          dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [](dnsheader& header) {
+            header.tc = true;
+            header.qr = true;
+            header.ra = header.rd;
+            header.aa = false;
+            header.ad = false;
+            return true;
+          });
           return true;
         }
         else {
@@ -1019,7 +1081,10 @@ static bool applyRulesToQuery(LocalHolders& holders, DNSQuestion& dq, const stru
       case DNSAction::Action::NoRecurse:
         updateBlockStats();
         vinfolog("Query from %s setting rd=0 because of dynamic block", dq.ids.origRemote.toStringWithPort());
-        dq.getHeader()->rd = false;
+        dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [](dnsheader& header) {
+          header.rd = false;
+          return true;
+        });
         return true;
       default:
         updateBlockStats();
@@ -1048,26 +1113,27 @@ static bool applyRulesToQuery(LocalHolders& holders, DNSQuestion& dq, const stru
         vinfolog("Query from %s for %s turned into NXDomain because of dynamic block", dq.ids.origRemote.toStringWithPort(), dq.ids.qname.toLogString());
         updateBlockStats();
 
-        dq.getHeader()->rcode = RCode::NXDomain;
-        dq.getHeader()->qr = true;
+        setRCode(RCode::NXDomain);
         return true;
       case DNSAction::Action::Refused:
         vinfolog("Query from %s for %s refused because of dynamic block", dq.ids.origRemote.toStringWithPort(), dq.ids.qname.toLogString());
         updateBlockStats();
 
-        dq.getHeader()->rcode = RCode::Refused;
-        dq.getHeader()->qr = true;
+        setRCode(RCode::Refused);
         return true;
       case DNSAction::Action::Truncate:
         if (!dq.overTCP()) {
           updateBlockStats();
 
           vinfolog("Query from %s for %s truncated because of dynamic block", dq.ids.origRemote.toStringWithPort(), dq.ids.qname.toLogString());
-          dq.getHeader()->tc = true;
-          dq.getHeader()->qr = true;
-          dq.getHeader()->ra = dq.getHeader()->rd;
-          dq.getHeader()->aa = false;
-          dq.getHeader()->ad = false;
+          dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [](dnsheader& header) {
+            header.tc = true;
+            header.qr = true;
+            header.ra = header.rd;
+            header.aa = false;
+            header.ad = false;
+            return true;
+          });
           return true;
         }
         else {
@@ -1077,7 +1143,10 @@ static bool applyRulesToQuery(LocalHolders& holders, DNSQuestion& dq, const stru
       case DNSAction::Action::NoRecurse:
         updateBlockStats();
         vinfolog("Query from %s setting rd=0 because of dynamic block", dq.ids.origRemote.toStringWithPort());
-        dq.getHeader()->rd = false;
+        dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [](dnsheader& header) {
+          header.rd = false;
+          return true;
+        });
         return true;
       default:
         updateBlockStats();
@@ -1268,6 +1337,10 @@ static bool prepareOutgoingResponse(LocalHolders& holders, const ClientState& cs
     ac(&dr, &result);
   }
 
+  if (dr.ids.d_extendedError) {
+    dnsdist::edns::addExtendedDNSError(dr.getMutableData(), dr.getMaximumSize(), dr.ids.d_extendedError->infoCode, dr.ids.d_extendedError->extraText);
+  }
+
   if (cacheHit) {
     ++dnsdist::metrics::g_stats.cacheHits;
   }
@@ -1368,7 +1441,10 @@ ProcessQueryResult processQueryAfterRules(DNSQuestion& dq, LocalHolders& holders
          yet, as we will do a second-lookup */
       if (dq.ids.packetCache->get(dq, dq.getHeader()->id, &dq.ids.cacheKey, dq.ids.subnet, dq.ids.dnssecOK, forwardedOverUDP, allowExpired, false, true, dq.ids.protocol != dnsdist::Protocol::DoH || forwardedOverUDP)) {
 
-        restoreFlags(dq.getHeader(), dq.ids.origFlags);
+        dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [flags=dq.ids.origFlags](dnsheader& header) {
+          restoreFlags(&header, flags);
+          return true;
+        });
 
         vinfolog("Packet cache hit for query for %s|%s from %s (%s, %d bytes)", dq.ids.qname.toLogString(), QType(dq.ids.qtype).toString(), dq.ids.origRemote.toStringWithPort(), dq.ids.protocol.toString(), dq.getData().size());
 
@@ -1403,8 +1479,11 @@ ProcessQueryResult processQueryAfterRules(DNSQuestion& dq, LocalHolders& holders
 
       vinfolog("%s query for %s|%s from %s, no downstream server available", g_servFailOnNoPolicy ? "ServFailed" : "Dropped", dq.ids.qname.toLogString(), QType(dq.ids.qtype).toString(), dq.ids.origRemote.toStringWithPort());
       if (g_servFailOnNoPolicy) {
-        dq.getHeader()->rcode = RCode::ServFail;
-        dq.getHeader()->qr = true;
+        dnsdist::PacketMangling::editDNSHeaderFromPacket(dq.getMutableData(), [](dnsheader& header) {
+          header.rcode = RCode::ServFail;
+          header.qr = true;
+          return true;
+        });
 
         fixUpQueryTurnedResponse(dq, dq.ids.origFlags);
 
@@ -1421,7 +1500,7 @@ ProcessQueryResult processQueryAfterRules(DNSQuestion& dq, LocalHolders& holders
     }
 
     /* save the DNS flags as sent to the backend so we can cache the answer with the right flags later */
-    dq.ids.cacheFlags = *getFlagsFromDNSHeader(dq.getHeader());
+    dq.ids.cacheFlags = *getFlagsFromDNSHeader(dq.getHeader().get());
 
     if (dq.addXPF && selectedBackend->d_config.xpfRRCode != 0) {
       addXPF(dq, selectedBackend->d_config.xpfRRCode);
@@ -1647,16 +1726,20 @@ static void processUDPQuery(ClientState& cs, LocalHolders& holders, const struct
 
     {
       /* this pointer will be invalidated the second the buffer is resized, don't hold onto it! */
-      struct dnsheader* dh = reinterpret_cast<struct dnsheader*>(query.data());
+      const dnsheader_aligned dh(query.data());
       queryId = ntohs(dh->id);
 
-      if (!checkQueryHeaders(dh, cs)) {
+      if (!checkQueryHeaders(dh.get(), cs)) {
         return;
       }
 
       if (dh->qdcount == 0) {
-        dh->rcode = RCode::NotImp;
-        dh->qr = true;
+        dnsdist::PacketMangling::editDNSHeaderFromPacket(query, [](dnsheader& header) {
+          header.rcode = RCode::NotImp;
+          header.qr = true;
+          return true;
+        });
+
         sendUDPResponse(cs.udpFD, query, 0, dest, remote);
         return;
       }
@@ -1667,7 +1750,7 @@ static void processUDPQuery(ClientState& cs, LocalHolders& holders, const struct
       ids.protocol = dnsdist::Protocol::DNSCryptUDP;
     }
     DNSQuestion dq(ids, query);
-    const uint16_t* flags = getFlagsFromDNSHeader(dq.getHeader());
+    const uint16_t* flags = getFlagsFromDNSHeader(dq.getHeader().get());
     ids.origFlags = *flags;
 
     if (!proxyProtocolValues.empty()) {
@@ -1682,7 +1765,7 @@ static void processUDPQuery(ClientState& cs, LocalHolders& holders, const struct
     }
 
     // the buffer might have been invalidated by now (resized)
-    struct dnsheader* dh = dq.getHeader();
+    const auto dh = dq.getHeader();
     if (result == ProcessQueryResult::SendAnswer) {
 #ifndef DISABLE_RECVMMSG
 #if defined(HAVE_RECVMMSG) && defined(HAVE_SENDMMSG) && defined(MSG_WAITFORONE)
@@ -2918,7 +3001,9 @@ int main(int argc, char** argv)
     g_tcpclientthreads = std::make_unique<TCPClientCollection>(*g_maxTCPClientThreads, std::vector<ClientState*>());
 #endif
 
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
     initDoHWorkers();
+#endif
 
     for (auto& todoItem : todo) {
       todoItem();
index dfaa3d1e58db540a3130f81d10129bac1877cf64..acbc45102e49787944a6c255fe9ad8d413e7c979 100644 (file)
@@ -89,20 +89,26 @@ struct DNSQuestion
     return data;
   }
 
-  dnsheader* getHeader()
+  bool editHeader(const std::function<bool(dnsheader&)>& editFunction);
+
+  const dnsheader_aligned getHeader() const
   {
     if (data.size() < sizeof(dnsheader)) {
       throw std::runtime_error("Trying to access the dnsheader of a too small (" + std::to_string(data.size()) + ") DNSQuestion buffer");
     }
-    return reinterpret_cast<dnsheader*>(&data.at(0));
+    dnsheader_aligned dh(data.data());
+    return dh;
   }
 
-  const dnsheader* getHeader() const
+  /* this function is not safe against unaligned access, you should
+     use editHeader() instead, but we need it for the Lua bindings */
+  dnsheader* getMutableHeader() const
   {
     if (data.size() < sizeof(dnsheader)) {
       throw std::runtime_error("Trying to access the dnsheader of a too small (" + std::to_string(data.size()) + ") DNSQuestion buffer");
     }
-    return reinterpret_cast<const dnsheader*>(&data.at(0));
+    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
+    return reinterpret_cast<dnsheader*>(data.data());
   }
 
   bool hasRoomFor(size_t more) const
index 8e22528413dd4a92affeabdb317e5b47ae481979..5033a20ffc4c385acc139fcdbabea5f3642ced4f 100644 (file)
@@ -34,6 +34,7 @@
 /missing
 /testrunner
 /dnsdist
+/fuzz_target_dnsdistcache
 /*.pb.cc
 /*.pb.h
 /dnsdist.service
index f9a7bc297bd10a5b96898f8f937fac995987cee2..d463c5bfb88df512fcdfc68865f77d9b9aa326fe 100644 (file)
@@ -185,8 +185,8 @@ dnsdist_SOURCES = \
        dnsdist-lua.cc dnsdist-lua.hh \
        dnsdist-mac-address.cc dnsdist-mac-address.hh \
        dnsdist-metrics.cc dnsdist-metrics.hh \
-       dnsdist-nghttp2-in.cc dnsdist-nghttp2-in.hh \
-       dnsdist-nghttp2.cc dnsdist-nghttp2.hh \
+       dnsdist-nghttp2-in.hh \
+       dnsdist-nghttp2.hh \
        dnsdist-prometheus.hh \
        dnsdist-protobuf.cc dnsdist-protobuf.hh \
        dnsdist-protocols.cc dnsdist-protocols.hh \
@@ -214,6 +214,7 @@ dnsdist_SOURCES = \
        dolog.hh \
        doq.hh \
        ednscookies.cc ednscookies.hh \
+       ednsextendederror.cc ednsextendederror.hh \
        ednsoptions.cc ednsoptions.hh \
        ednssubnet.cc ednssubnet.hh \
        ext/json11/json11.cpp \
@@ -284,8 +285,8 @@ testrunner_SOURCES = \
        dnsdist-lua-vars.cc \
        dnsdist-mac-address.cc dnsdist-mac-address.hh \
        dnsdist-metrics.cc dnsdist-metrics.hh \
-       dnsdist-nghttp2-in.cc dnsdist-nghttp2-in.hh \
-       dnsdist-nghttp2.cc dnsdist-nghttp2.hh \
+       dnsdist-nghttp2-in.hh \
+       dnsdist-nghttp2.hh \
        dnsdist-protocols.cc dnsdist-protocols.hh \
        dnsdist-proxy-protocol.cc dnsdist-proxy-protocol.hh \
        dnsdist-random.cc dnsdist-random.hh \
@@ -339,8 +340,6 @@ testrunner_SOURCES = \
        test-dnsdistkvs_cc.cc \
        test-dnsdistlbpolicies_cc.cc \
        test-dnsdistluanetwork.cc \
-       test-dnsdistnghttp2-in_cc.cc \
-       test-dnsdistnghttp2_cc.cc \
        test-dnsdistnghttp2_common.hh \
        test-dnsdistpacketcache_cc.cc \
        test-dnsdistrings_cc.cc \
@@ -435,6 +434,17 @@ dnsdist_SOURCES += doh.cc
 dnsdist_LDADD += $(LIBH2OEVLOOP_LIBS)
 endif
 
+if HAVE_NGHTTP2
+dnsdist_SOURCES += dnsdist-nghttp2-in.cc
+dnsdist_SOURCES += dnsdist-nghttp2.cc
+testrunner_SOURCES += dnsdist-nghttp2-in.cc
+testrunner_SOURCES += dnsdist-nghttp2.cc
+testrunner_SOURCES += test-dnsdistnghttp2-in_cc.cc \
+       test-dnsdistnghttp2_cc.cc
+dnsdist_LDADD += $(NGHTTP2_LDFLAGS) $(NGHTTP2_LIBS)
+testrunner_LDADD += $(NGHTTP2_LDFLAGS) $(NGHTTP2_LIBS)
+endif
+
 endif
 
 if HAVE_DNS_OVER_QUIC
@@ -445,11 +455,6 @@ dnsdist_LDADD += $(QUICHE_LDFLAGS) $(QUICHE_LIBS)
 endif
 endif
 
-if HAVE_NGHTTP2
-dnsdist_LDADD += $(NGHTTP2_LDFLAGS) $(NGHTTP2_LIBS)
-testrunner_LDADD += $(NGHTTP2_LDFLAGS) $(NGHTTP2_LIBS)
-endif
-
 if !HAVE_LUA_HPP
 BUILT_SOURCES += lua.hpp
 nodist_dnsdist_SOURCES = lua.hpp
@@ -513,6 +518,7 @@ fuzz_target_dnsdistcache_SOURCES = \
        channel.hh channel.cc \
        dns.cc dns.hh \
        dnsdist-cache.cc dnsdist-cache.hh \
+       dnsdist-dnsparser.cc dnsdist-dnsparser.hh \
        dnsdist-ecs.cc dnsdist-ecs.hh \
        dnsdist-idstate.hh \
        dnsdist-protocols.cc dnsdist-protocols.hh \
index 11495c3c7916d20ab8a480b4fd2c4aa0f99c9117..8de53ba3689ce2a5de80788ffe63d4cad26da96a 100644 (file)
@@ -113,7 +113,6 @@ AS_IF([test "x$enable_dns_over_quic" != "xno"], [
   ])
 ])
 
-PDNS_WITH_NGHTTP2
 DNSDIST_WITH_CDB
 PDNS_CHECK_LMDB
 PDNS_ENABLE_IPCIPHER
index 44b3d9c39dc4685cf041fb5261c797acc8200af5..d3d70abc843af4be42b3470d01ebb754adddb1b1 100644 (file)
 
 bool DownstreamState::passCrossProtocolQuery(std::unique_ptr<CrossProtocolQuery>&& cpq)
 {
-  if (d_config.d_dohPath.empty()) {
-    return g_tcpclientthreads && g_tcpclientthreads->passCrossProtocolQueryToThread(std::move(cpq));
-  }
-  else {
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
+  if (!d_config.d_dohPath.empty()) {
     return g_dohClientThreads && g_dohClientThreads->passCrossProtocolQueryToThread(std::move(cpq));
   }
+#endif
+  return g_tcpclientthreads && g_tcpclientthreads->passCrossProtocolQueryToThread(std::move(cpq));
 }
 
 bool DownstreamState::reconnect(bool initialAttempt)
index 5bb61ba450918995cdc3526706351e17099ec80e..889249d0c0fb03a0a31c76dec797336c47db99a7 100644 (file)
@@ -52,7 +52,7 @@ struct DesignatedResolvers
 static bool parseSVCParams(const PacketBuffer& answer, std::map<uint16_t, DesignatedResolvers>& resolvers)
 {
   std::map<DNSName, std::vector<ComboAddress>> hints;
-  const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(answer.data());
+  const dnsheader_aligned dh(answer.data());
   PacketReader pr(std::string_view(reinterpret_cast<const char*>(answer.data()), answer.size()));
   uint16_t qdcount = ntohs(dh->qdcount);
   uint16_t ancount = ntohs(dh->ancount);
index 1131bf29bc66150c0effe25d86d2a8db1b0b3260..0aa85397139585d72f8f7f430aa3d3362ab64035 100644 (file)
@@ -22,6 +22,7 @@
 #include "dnsdist-ecs.hh"
 #include "dnsdist-edns.hh"
 #include "ednsoptions.hh"
+#include "ednsextendederror.hh"
 
 namespace dnsdist::edns
 {
@@ -55,4 +56,39 @@ std::pair<std::optional<uint16_t>, std::optional<std::string>> getExtendedDNSErr
   }
   return {infoCode, std::move(extraText)};
 }
+
+bool addExtendedDNSError(PacketBuffer& packet, size_t maximumPacketSize, uint16_t code, const std::string& extraStatus)
+{
+  uint16_t optStart = 0;
+  size_t optLen = 0;
+  bool last = false;
+
+  int res = locateEDNSOptRR(packet, &optStart, &optLen, &last);
+
+  if (res != 0) {
+    /* no EDNS OPT record in the response, something is not right */
+    return false;
+  }
+
+  EDNSExtendedError ede{.infoCode = code, .extraText = extraStatus};
+  auto edeOptionPayload = makeEDNSExtendedErrorOptString(ede);
+  std::string edeOption;
+  generateEDNSOption(EDNSOptionCode::EXTENDEDERROR, edeOptionPayload, edeOption);
+
+  /* we might have one record after the OPT one, we need to rewrite
+     the whole packet because of compression */
+  PacketBuffer newContent;
+  bool ednsAdded = false;
+  bool edeAdded = false;
+  if (!slowRewriteEDNSOptionInQueryWithRecords(packet, newContent, ednsAdded, EDNSOptionCode::EXTENDEDERROR, edeAdded, true, edeOption)) {
+    return false;
+  }
+
+  if (newContent.size() > maximumPacketSize) {
+    return false;
+  }
+
+  packet = std::move(newContent);
+  return true;
+}
 }
index 75c92c143ac1367710c2ca39514cace500e7f08b..8e60e5b049dc1162465fbe1e20e355628ec74045 100644 (file)
@@ -30,4 +30,5 @@
 namespace dnsdist::edns
 {
 std::pair<std::optional<uint16_t>, std::optional<std::string>> getExtendedDNSError(const PacketBuffer& packet);
+bool addExtendedDNSError(PacketBuffer& packet, size_t maximumPacketSize, uint16_t code, const std::string& extraStatus);
 }
index 37139e8661f418eca8422d2fa4c54a6dfce5bb96..36805573e7842624ecefe7ecc223e7270f92250a 100644 (file)
@@ -390,6 +390,7 @@ bool queueHealthCheck(std::unique_ptr<FDMultiplexer>& mplexer, const std::shared
 
       mplexer->addReadFD(data->d_udpSocket.getHandle(), &healthCheckUDPCallback, data, &data->d_ttd);
     }
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
     else if (downstream->isDoH()) {
       InternalQuery query(std::move(packet), InternalQueryState());
       query.d_proxyProtocolPayload = std::move(proxyProtocolPayload);
@@ -398,6 +399,7 @@ bool queueHealthCheck(std::unique_ptr<FDMultiplexer>& mplexer, const std::shared
         data->d_ds->submitHealthCheckResult(data->d_initial, false);
       }
     }
+#endif
     else {
       data->d_tcpHandler = std::make_unique<TCPIOHandler>(downstream->d_config.d_tlsSubjectName, downstream->d_config.d_tlsSubjectIsAddr, sock.releaseHandle(), timeval{downstream->d_config.checkTimeout, 0}, downstream->d_tlsCtx);
       data->d_ioState = std::make_unique<IOStateHandler>(*mplexer, data->d_tcpHandler->getDescriptor());
@@ -464,7 +466,9 @@ void handleQueuedHealthChecks(FDMultiplexer& mplexer, bool initial)
       continue;
     }
 
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
     handleH2Timeouts(mplexer, now);
+#endif
 
     auto timeouts = mplexer.getTimeouts(now);
     for (const auto& timeout : timeouts) {
index e7cc8fe873335b3f43dd2079c4bd00383b5cad56..622b3d90bf68a941b3387be1bcc7369dbbb1f515 100644 (file)
@@ -117,6 +117,8 @@ void dnsdist_ffi_dnsquestion_set_device_name(dnsdist_ffi_dnsquestion_t* dq, cons
 
 void dnsdist_ffi_dnsquestion_set_http_response(dnsdist_ffi_dnsquestion_t* dq, uint16_t statusCode, const char* body, size_t bodyLen, const char* contentType) __attribute__ ((visibility ("default")));
 
+void dnsdist_ffi_dnsquestion_set_extended_dns_error(dnsdist_ffi_dnsquestion_t* dnsQuestion, uint16_t infoCode, const char* extraText, size_t extraTextSize) __attribute__ ((visibility ("default")));
+
 size_t dnsdist_ffi_dnsquestion_get_trailing_data(dnsdist_ffi_dnsquestion_t* dq, const char** out) __attribute__ ((visibility ("default")));
 
 bool dnsdist_ffi_dnsquestion_set_trailing_data(dnsdist_ffi_dnsquestion_t* dq, const char* data, size_t dataLen) __attribute__ ((visibility ("default")));
index 48ce507da8e7331fe56e48aab3fb0a90ff7bd97d..f7365bf7718b2c885072e767e93ac41091d39ea2 100644 (file)
@@ -129,7 +129,7 @@ int dnsdist_ffi_dnsquestion_get_rcode(const dnsdist_ffi_dnsquestion_t* dq)
 
 void* dnsdist_ffi_dnsquestion_get_header(const dnsdist_ffi_dnsquestion_t* dq)
 {
-  return dq->dq->getHeader();
+  return dq->dq->getMutableHeader();
 }
 
 uint16_t dnsdist_ffi_dnsquestion_get_len(const dnsdist_ffi_dnsquestion_t* dq)
@@ -458,14 +458,30 @@ void dnsdist_ffi_dnsquestion_set_http_response(dnsdist_ffi_dnsquestion_t* dq, ui
 #ifdef HAVE_DNS_OVER_HTTPS
   PacketBuffer bodyVect(body, body + bodyLen);
   dq->dq->ids.du->setHTTPResponse(statusCode, std::move(bodyVect), contentType);
-  dq->dq->getHeader()->qr = true;
+  dnsdist::PacketMangling::editDNSHeaderFromPacket(dq->dq->getMutableData(), [](dnsheader& header) {
+    header.qr = true;
+    return true;
+  });
 #endif
 }
 
+void dnsdist_ffi_dnsquestion_set_extended_dns_error(dnsdist_ffi_dnsquestion_t* dnsQuestion, uint16_t infoCode, const char* extraText, size_t extraTextSize)
+{
+  EDNSExtendedError ede;
+  ede.infoCode = infoCode;
+  if (extraText != nullptr && extraTextSize > 0) {
+    ede.extraText = std::string(extraText, extraTextSize);
+  }
+  dnsQuestion->dq->ids.d_extendedError = std::make_unique<EDNSExtendedError>(ede);
+}
+
 void dnsdist_ffi_dnsquestion_set_rcode(dnsdist_ffi_dnsquestion_t* dq, int rcode)
 {
-  dq->dq->getHeader()->rcode = rcode;
-  dq->dq->getHeader()->qr = true;
+  dnsdist::PacketMangling::editDNSHeaderFromPacket(dq->dq->getMutableData(), [rcode](dnsheader& header) {
+    header.rcode = rcode;
+    header.qr = true;
+    return true;
+  });
 }
 
 void dnsdist_ffi_dnsquestion_set_len(dnsdist_ffi_dnsquestion_t* dq, uint16_t len)
@@ -950,11 +966,15 @@ bool dnsdist_ffi_set_answer_from_async(uint16_t asyncID, uint16_t queryID, const
     return false;
   }
 
-  auto oldId = reinterpret_cast<const dnsheader*>(query->query.d_buffer.data())->id;
+  dnsheader_aligned alignedHeader(query->query.d_buffer.data());
+  auto oldID = alignedHeader->id;
   query->query.d_buffer.clear();
   query->query.d_buffer.insert(query->query.d_buffer.begin(), raw, raw + rawSize);
-  reinterpret_cast<dnsheader*>(query->query.d_buffer.data())->id = oldId;
 
+  dnsdist::PacketMangling::editDNSHeaderFromPacket(query->query.d_buffer, [oldID](dnsheader& header) {
+    header.id = oldID;
+    return true;
+  });
   query->query.d_idstate.skipCache = true;
 
   return dnsdist::queueQueryResumptionEvent(std::move(query));
@@ -1297,15 +1317,15 @@ template<typename T> static void addRingEntryToList(std::unique_ptr<dnsdist_ffi_
   constexpr bool response = std::is_same_v<T, Rings::Response>;
 #if defined(DNSDIST_RINGS_WITH_MACADDRESS)
   if constexpr (!response) {
-    dnsdist_ffi_ring_entry_list_t::entry tmp{entry.name.toString(), entry.requestor.toString(), entry.hasmac ? std::string(reinterpret_cast<const char*>(entry.macaddress.data()), entry.macaddress.size()) : std::string(), entry.size, entry.qtype, entry.protocol, response};
+    dnsdist_ffi_ring_entry_list_t::entry tmp{entry.name.toString(), entry.requestor.toStringWithPort(), entry.hasmac ? std::string(reinterpret_cast<const char*>(entry.macaddress.data()), entry.macaddress.size()) : std::string(), entry.size, entry.qtype, entry.protocol, response};
     list->d_entries.push_back(std::move(tmp));
   }
   else {
-    dnsdist_ffi_ring_entry_list_t::entry tmp{entry.name.toString(), entry.requestor.toString(), std::string(), entry.size, entry.qtype, entry.protocol, response};
+    dnsdist_ffi_ring_entry_list_t::entry tmp{entry.name.toString(), entry.requestor.toStringWithPort(), std::string(), entry.size, entry.qtype, entry.protocol, response};
     list->d_entries.push_back(std::move(tmp));
   }
 #else
-  dnsdist_ffi_ring_entry_list_t::entry tmp{entry.name.toString(), entry.requestor.toString(), std::string(), entry.size, entry.qtype, entry.protocol, response};
+  dnsdist_ffi_ring_entry_list_t::entry tmp{entry.name.toString(), entry.requestor.toStringWithPort(), std::string(), entry.size, entry.qtype, entry.protocol, response};
   list->d_entries.push_back(std::move(tmp));
 #endif
 }
index 6497a455d338d92e548ea823a392a5d0d2666043..adf961eb8b4b30e0cbe3ce1bcb7c10bbeb62974e 100644 (file)
@@ -110,6 +110,10 @@ Stats::Stats() :
     {"latency-doh-avg1000", &latencyDoHAvg1000},
     {"latency-doh-avg10000", &latencyDoHAvg10000},
     {"latency-doh-avg1000000", &latencyDoHAvg1000000},
+    {"latency-doq-avg100", &latencyDoQAvg100},
+    {"latency-doq-avg1000", &latencyDoQAvg1000},
+    {"latency-doq-avg10000", &latencyDoQAvg10000},
+    {"latency-doq-avg1000000", &latencyDoQAvg1000000},
     {"uptime", uptimeOfProcess},
     {"real-memory-usage", getRealMemoryUsage},
     {"special-memory-usage", getSpecialMemoryUsage},
index 37e75d1865a8635be8ec8416c792d797c83f87ee..264054f6728d24e0dd28610abef86b42a7a8b3f8 100644 (file)
@@ -84,6 +84,7 @@ struct Stats
   double latencyTCPAvg100{0}, latencyTCPAvg1000{0}, latencyTCPAvg10000{0}, latencyTCPAvg1000000{0};
   double latencyDoTAvg100{0}, latencyDoTAvg1000{0}, latencyDoTAvg10000{0}, latencyDoTAvg1000000{0};
   double latencyDoHAvg100{0}, latencyDoHAvg1000{0}, latencyDoHAvg10000{0}, latencyDoHAvg1000000{0};
+  double latencyDoQAvg100{0}, latencyDoQAvg1000{0}, latencyDoQAvg10000{0}, latencyDoQAvg1000000{0};
   using statfunction_t = std::function<uint64_t(const std::string&)>;
   using entry_t = std::variant<stat_t*, pdns::stat_t_trait<double>*, double*, statfunction_t>;
   struct EntryPair
index 35591ffd3e64eb65caccc19fba233916d46c13ec..cacf3673746099bfc52b603bc3080f2695240b38 100644 (file)
  */
 
 #include "base64.hh"
+#include "dnsdist-dnsparser.hh"
 #include "dnsdist-nghttp2-in.hh"
 #include "dnsdist-proxy-protocol.hh"
 #include "dnsparser.hh"
 
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
 
 #if 0
 class IncomingDoHCrossProtocolContext : public CrossProtocolContext
@@ -197,10 +198,11 @@ void IncomingHTTP2Connection::handleResponse(const struct timeval& now, TCPRespo
     if (responseDH.get()->tc && state.d_packet && state.d_packet->size() > state.d_proxyProtocolPayloadSize && state.d_packet->size() - state.d_proxyProtocolPayloadSize > sizeof(dnsheader)) {
       vinfolog("Response received from backend %s via UDP, for query %d received from %s via DoH, is truncated, retrying over TCP", response.d_ds->getNameWithAddr(), state.d_streamID, state.origRemote.toStringWithPort());
       auto& query = *state.d_packet;
-      // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
-      auto* queryDH = reinterpret_cast<struct dnsheader*>(&query.at(state.d_proxyProtocolPayloadSize));
-      /* restoring the original ID */
-      queryDH->id = state.origID;
+      dnsdist::PacketMangling::editDNSHeaderFromRawPacket(&query.at(state.d_proxyProtocolPayloadSize), [origID = state.origID](dnsheader& header) {
+        /* restoring the original ID */
+        header.id = origID;
+        return true;
+      });
 
       state.forwardedOverUDP = false;
       bool proxyProtocolPayloadAdded = state.d_proxyProtocolPayloadSize > 0;
@@ -1227,4 +1229,4 @@ bool IncomingHTTP2Connection::active() const
   return !d_connectionDied && d_ioState != nullptr;
 }
 
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
index 020e1c26e312a9913d3c590a81cdba2b3f3e5337..a2e58a45a919bd6bc69569e8974024c2f7249dba 100644 (file)
@@ -22,7 +22,7 @@
 #pragma once
 
 #include "config.h"
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
 #include <nghttp2/nghttp2.h>
 
 #include "dnsdist-tcp-upstream.hh"
@@ -156,4 +156,4 @@ public:
   static void addCustomDynamicHeader(std::vector<nghttp2_nv>& headers, const std::string& name, const std::string_view& value);
 };
 
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
index 163d2df0925e58af8383c85aea5068ee55983a1e..0db65fb38a7749c07f7045be78c0fa7dea1465e9 100644 (file)
@@ -22,9 +22,9 @@
 
 #include "config.h"
 
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
 #include <nghttp2/nghttp2.h>
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
 
 #include "dnsdist-nghttp2.hh"
 #include "dnsdist-nghttp2-in.hh"
@@ -45,7 +45,7 @@ std::atomic<uint64_t> g_dohStatesDumpRequested{0};
 std::unique_ptr<DoHClientCollection> g_dohClientThreads{nullptr};
 std::optional<uint16_t> g_outgoingDoHWorkerThreads{std::nullopt};
 
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
 class DoHConnectionToBackend : public ConnectionToBackend
 {
 public:
@@ -932,7 +932,7 @@ static bool select_next_proto_callback(unsigned char** out, unsigned char* outle
   return true;
 }
 
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
 
 struct DoHClientCollection::DoHWorkerThread
 {
@@ -984,7 +984,7 @@ bool DoHClientCollection::passCrossProtocolQueryToThread(std::unique_ptr<CrossPr
 
 void DoHClientCollection::addThread()
 {
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
   try {
     auto [sender, receiver] = pdns::channel::createObjectQueue<CrossProtocolQuery>(pdns::channel::SenderBlockingMode::SenderNonBlocking, pdns::channel::ReceiverBlockingMode::ReceiverNonBlocking, g_tcpInternalPipeBufferSize);
 
@@ -1014,14 +1014,14 @@ void DoHClientCollection::addThread()
     errlog("Error creating the DoH channel: %s", e.what());
     return;
   }
-#else /* HAVE_NGHTTP2 */
+#else /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
   throw std::runtime_error("DoHClientCollection::addThread() called but nghttp2 support is not available");
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
 }
 
 bool initDoHWorkers()
 {
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
   if (!g_outgoingDoHWorkerThreads) {
     /* Unless the value has been set to 0 explicitly, always start at least one outgoing DoH worker thread, in case a DoH backend
        is added at a later time. */
@@ -1037,7 +1037,7 @@ bool initDoHWorkers()
   return true;
 #else
   return false;
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
 }
 
 bool setupDoHClientProtocolNegotiation(std::shared_ptr<TLSCtx>& ctx)
@@ -1045,20 +1045,20 @@ bool setupDoHClientProtocolNegotiation(std::shared_ptr<TLSCtx>& ctx)
   if (ctx == nullptr) {
     return false;
   }
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
   /* we want to set the ALPN to h2, if only to mitigate the ALPACA attack */
   const std::vector<std::vector<uint8_t>> h2Alpns = {{'h', '2'}};
   ctx->setALPNProtos(h2Alpns);
   ctx->setNextProtocolSelectCallback(select_next_proto_callback);
   return true;
-#else /* HAVE_NGHTTP2 */
+#else /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
   return false;
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
 }
 
 bool sendH2Query(const std::shared_ptr<DownstreamState>& ds, std::unique_ptr<FDMultiplexer>& mplexer, std::shared_ptr<TCPQuerySender>& sender, InternalQuery&& query, bool healthCheck)
 {
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
   struct timeval now
   {
     .tv_sec = 0, .tv_usec = 0
@@ -1077,24 +1077,24 @@ bool sendH2Query(const std::shared_ptr<DownstreamState>& ds, std::unique_ptr<FDM
   }
 
   return true;
-#else /* HAVE_NGHTTP2 */
+#else /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
   return false;
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
 }
 
 size_t clearH2Connections()
 {
   size_t cleared = 0;
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
   cleared = t_downstreamDoHConnectionsManager.clear();
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
   return cleared;
 }
 
 size_t handleH2Timeouts(FDMultiplexer& mplexer, const struct timeval& now)
 {
   size_t got = 0;
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
   auto expiredReadConns = mplexer.getTimeouts(now, false);
   for (const auto& cbData : expiredReadConns) {
     if (cbData.second.type() == typeid(std::shared_ptr<DoHConnectionToBackend>)) {
@@ -1114,27 +1114,27 @@ size_t handleH2Timeouts(FDMultiplexer& mplexer, const struct timeval& now)
       ++got;
     }
   }
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
   return got;
 }
 
 void setDoHDownstreamCleanupInterval(uint16_t max)
 {
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
   DownstreamDoHConnectionsManager::setCleanupInterval(max);
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
 }
 
 void setDoHDownstreamMaxIdleTime(uint16_t max)
 {
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
   DownstreamDoHConnectionsManager::setMaxIdleTime(max);
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
 }
 
 void setDoHDownstreamMaxIdleConnectionsPerBackend(size_t max)
 {
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
   DownstreamDoHConnectionsManager::setMaxIdleConnectionsPerDownstream(max);
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
 }
index 3bc9aeb40cc990a6fcfad2f2e4d30de6cb0e874b..26c48ba90194dccd33bef8471c89fd1cd8271381 100644 (file)
@@ -49,7 +49,7 @@ static std::string getFirstTXTAnswer(const std::string& answer)
     throw std::runtime_error("Looking for a TXT record in an answer smaller than the DNS header");
   }
 
-  const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(answer.data());
+  const dnsheader_aligned dh(answer.data());
   PacketReader pr(answer);
   uint16_t qdcount = ntohs(dh->qdcount);
   uint16_t ancount = ntohs(dh->ancount);
index 35a2befffbae4a9dd08c948ecd4cc1e97eb9b73f..f6b4323e7ffc825cff601f6580b779b0eba38aab 100644 (file)
@@ -817,11 +817,11 @@ bool TCPConnectionToBackend::isXFRFinished(const TCPResponse& response, TCPQuery
         }
         auto raw = unknownContent->getRawContent();
         auto serial = getSerialFromRawSOAContent(raw);
-        if (query.d_xfrMasterSerial == 0) {
+        if (query.d_xfrPrimarySerial == 0) {
           // store the first SOA in our client's connection metadata
-          query.d_xfrMasterSerial = serial;
-          if (query.d_idstate.qtype == QType::IXFR && (query.d_xfrMasterSerial == query.d_ixfrQuerySerial || rfc1982LessThan(query.d_xfrMasterSerial, query.d_ixfrQuerySerial))) {
-            /* This is the first message with a master SOA:
+          query.d_xfrPrimarySerial = serial;
+          if (query.d_idstate.qtype == QType::IXFR && (query.d_xfrPrimarySerial == query.d_ixfrQuerySerial || rfc1982LessThan(query.d_xfrPrimarySerial, query.d_ixfrQuerySerial))) {
+            /* This is the first message with a primary SOA:
                RFC 1995 Section 2:
                  If an IXFR query with the same or newer version number
                  than that of the server is received, it is replied to
@@ -833,16 +833,16 @@ bool TCPConnectionToBackend::isXFRFinished(const TCPResponse& response, TCPQuery
         }
 
         ++query.d_xfrSerialCount;
-        if (serial == query.d_xfrMasterSerial) {
-          ++query.d_xfrMasterSerialCount;
-          // figure out if it's end when receiving master's SOA again
+        if (serial == query.d_xfrPrimarySerial) {
+          ++query.d_xfrPrimarySerialCount;
+          // figure out if it's end when receiving primary's SOA again
           if (query.d_xfrSerialCount == 2) {
             // if there are only two SOA records marks a finished AXFR
             done = true;
             break;
           }
-          if (query.d_xfrMasterSerialCount == 3) {
-            // receiving master's SOA 3 times marks a finished IXFR
+          if (query.d_xfrPrimarySerialCount == 3) {
+            // receiving primary's SOA 3 times marks a finished IXFR
             done = true;
             break;
           }
index aef6cf6ec38af31cf0a95b59379d8cd00a994abc..199cbcab354595109b6113cc52a5026a66ab0633 100644 (file)
@@ -102,10 +102,10 @@ public:
   std::string d_proxyProtocolPayload;
   PacketBuffer d_buffer;
   uint32_t d_ixfrQuerySerial{0};
-  uint32_t d_xfrMasterSerial{0};
+  uint32_t d_xfrPrimarySerial{0};
   uint32_t d_xfrSerialCount{0};
   uint32_t d_downstreamFailures{0};
-  uint8_t d_xfrMasterSerialCount{0};
+  uint8_t d_xfrPrimarySerialCount{0};
   bool d_xfrStarted{false};
   bool d_proxyProtocolPayloadAdded{false};
 };
@@ -126,7 +126,8 @@ struct TCPResponse : public TCPQuery
     TCPQuery(std::move(buffer), std::move(state)), d_connection(std::move(conn)), d_ds(std::move(ds))
   {
     if (d_buffer.size() >= sizeof(dnsheader)) {
-      memcpy(&d_cleartextDH, reinterpret_cast<const dnsheader*>(d_buffer.data()), sizeof(d_cleartextDH));
+      dnsheader_aligned header(d_buffer.data());
+      memcpy(&d_cleartextDH, header.get(), sizeof(d_cleartextDH));
     }
     else {
       memset(&d_cleartextDH, 0, sizeof(d_cleartextDH));
@@ -137,7 +138,8 @@ struct TCPResponse : public TCPQuery
     TCPQuery(std::move(query))
   {
     if (d_buffer.size() >= sizeof(dnsheader)) {
-      memcpy(&d_cleartextDH, reinterpret_cast<const dnsheader*>(d_buffer.data()), sizeof(d_cleartextDH));
+      dnsheader_aligned header(d_buffer.data());
+      memcpy(&d_cleartextDH, header.get(), sizeof(d_cleartextDH));
     }
     else {
       memset(&d_cleartextDH, 0, sizeof(d_cleartextDH));
index 7f995cdf3a704a9a21ef185aed7d1b19600d1e95..8b6b5e61ccd547a8594af97f05ca85ccd4ebff5f 100644 (file)
@@ -30,11 +30,15 @@ dnsdist supports both server's side (sessions) and client's side (tickets) resum
 
 Since server-side sessions cannot be shared between several instances, and pretty much all clients support tickets anyway, we do recommend disabling the sessions by passing ``numberOfStoredSessions=0`` to the :func:`addDOHLocal` (for DNS over HTTPS) and :func:`addTLSLocal` (for DNS over TLS) functions.
 
-By default, dnsdist will generate a new, random STEK at startup and rotate it every 12 hours. It will keep 5 keys in memory, with only the last one marked as active and used to encrypt new tickets while the remaining ones can still be used to decrypt existing tickets after a rotation. The rotation time and the number of keys to keep in memory can be configured via the ``numberOfTicketsKeys`` and ``ticketsKeysRotationDelay`` parameters of the :func:`addDOHLocal` (for DNS over HTTPS) and :func:`addTLSLocal` (for DNS over TLS) functions.
+By default, dnsdist will generate a new, random STEK at startup for each :func:`addTLSLocal` and :func:`addDOHLocal` directive, and rotate these STEKs every 12 hours. For each frontend it will keep 5 keys in memory, with only the last one marked as active and used to encrypt new tickets while the remaining ones can still be used to decrypt existing tickets after a rotation. The rotation time and the number of keys to keep in memory can be configured via the ``numberOfTicketsKeys`` and ``ticketsKeysRotationDelay`` parameters of the :func:`addDOHLocal` (for DNS over HTTPS) and :func:`addTLSLocal` (for DNS over TLS) functions.
+When the automatic rotation mechanism kicks in a new, random key will be added to the list of keys. With the OpenSSL provider, the new key becomes active, so new tickets will be encrypted with this key, and the existing keys become passive and only be used to decrypt existing tickets. With the GnuTLS provider only one key is currently supported so the existing keys are immediately discarded.
+This automatic rotation can be disabled by setting ``ticketsKeysRotationDelay`` to 0.
 
 It is also possible to manually request a STEK rotation using the :func:`getDOHFrontend` (DoH) and :func:`getTLSContext` (DoT) functions to retrieve the bind object, and calling its ``rotateTicketsKey`` method (:meth:`DOHFrontend:rotateTicketsKey`, :meth:`TLSContext:rotateTicketsKey`).
 
-The default settings should be fine for most deployments, but generating a random key for every dnsdist instance will not allow resuming the session from a different instance in a cluster. In that case it is possible to generate the STEK outside of dnsdist, write it to a file, distribute it to all instances using something like rsync over SSH, and load that file from dnsdist. Please remember that the STEK contains very sensitive data, and should be well-protected from access by unauthorized users. It means that special care should be taken to setting the right permissions on that file.
+The default settings should be fine for most deployments, but generating a random key for every dnsdist instance will not allow resuming the session from a different instance in a cluster. It is also not very useful to have a different key for every :func:`addTLSLocal` and :func:`addDOHLocal` directive if you are using the same certificate and key, and it would be much better to use the same STEK to improve the session resumption ratio.
+
+In that case it is possible to generate the STEK outside of dnsdist, write it to a file, distribute it to all instances using something like rsync over SSH, and load that file from dnsdist. Please remember that the STEK contains very sensitive data, and should be well-protected from access by unauthorized users. It means that special care should be taken to setting the right permissions on that file. Automatic rotation should then be disabled by setting ``ticketsKeysRotationDelay`` to 0.
 
 For the OpenSSL provider (DoT, DoH), generating a random STEK in a file is a simple as getting 80 cryptographically secure random bytes and writing them to a file::
 
@@ -49,7 +53,21 @@ The file can then be loaded at startup by using the ``ticketKeyFile`` parameter
 If the file contains several keys, so for example 240 random bytes, dnsdist will load several STEKs, using the last one for encrypting new tickets and all of them to decrypt existing tickets.
 
 In order to rotate the keys at runtime, it is possible to instruct dnsdist to reload the content of the certificates, keys, and STEKs from the same file used at configuration time, for all DoH and DoH binds, by issuing the :func:`reloadAllCertificates` command.
-It can also be done one bind at a time using the :func:`getDOHFrontend` (DoH) and :func:`getTLSContext` (DoT) functions to retrieve the bind object, and calling its ``loadTicketsKeys`` method (:meth:`DOHFrontend.loadTicketsKeys`, :meth:`TLSContext:loadTicketsKeys`).
+It can also be done one bind at a time using the :func:`getDOHFrontend` (DoH) and :func:`getTLSContext` (DoT) functions to retrieve the bind object, and calling its ``loadTicketsKeys`` method (:meth:`DOHFrontend:loadTicketsKeys`, :meth:`TLSContext:loadTicketsKeys`).
+
+One possible way of handling manual rotation of the key would be to first:
+
+- generate ``N`` keys in ``N`` (``1..N``) separate files (for example executing ``dd if=/dev/urandom of=/secure-tmp-fs/N.key bs=80 count=1`` ``N`` times)
+- concatenate the ``N`` files into a single file (``/secure-tmp-fs/STEKs.key``) that you pass to dnsdist's ``ticketKeyFile`` parameter
+
+Then, when the STEK should be rotated:
+
+- generate one new key file (``N+1``)
+- delete the first key file (``1``)
+- concatenate the ``2..N+1`` files into one (``/secure-tmp-fs/STEKs.key``)
+- issue :func:`reloadAllCertificates` via the dnsdist console, or call ``loadTicketsKeys('/secure-tmp-fs/STEKs.key')`` for all frontends
+
+This way dnsdist can still decrypt incoming tickets that were encoded via the previous key (the active one is always the one at the end of the file, and we start by removing the one at the beginning of the file).
 
 Content of the STEK file
 ------------------------
index 0a122dee35d8cfc11603394a8c1eafbf77ae0acb..c8d78a0d67a6a2dd5b31ee91b3f94ee5f59da061 100644 (file)
@@ -116,6 +116,10 @@ Incoming and outgoing DNS over TLS, as well as outgoing DNS over HTTPS, might be
  * supported ciphers depend on the exact kernel version used. ``TLS_AES_128_GCM_SHA256`` might be a good option for testing purpose since it was supported pretty early
  * as of OpenSSL 3.0.7, kTLS can only be used for sending TLS 1.3 packets, not receiving them. Both sending and receiving packets should be working for TLS 1.2.
 
+TLS performance
+---------------
+
+For DNS over HTTPS and DNS over TLS, in addition to the advice above we suggest reading the :doc:`tls-sessions-management` page to learn how to improve TLS session resumption ratio, which has a huge impact on CPU usage and latency.
 
 Rules and Lua
 -------------
index 6458bcae9d6f5103456ee809aa21b797079c2e1f..d2e648cb21e8b8bbb7cc345e33ec79c957e4459e 100644 (file)
@@ -1,6 +1,86 @@
 Changelog
 =========
 
+.. changelog::
+  :version: 1.9.0-alpha3
+  :released: 20th of October 2023
+
+  Please review the :doc:`Upgrade Guide <../upgrade_guide>` before upgrading.
+
+  .. change::
+    :tags: New Features, Protobuf
+    :pullreq: 13185
+
+    Log Extended DNS Errors (EDE) to protobuf
+
+  .. change::
+    :tags: Bugs Fixes
+    :pullreq: 13274
+
+    Enable back h2o support in our packages
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 13275
+    :tickets: 13201
+
+    Add Lua binding to downstream address (Denis Machard)
+
+  .. change::
+    :tags: New Features, DNS over QUIC
+    :pullreq: 13280
+
+    Add support for incoming DNS over QUIC
+
+  .. change::
+    :tags: Bugs Fixes, DNS over HTTPS
+    :pullreq: 13298
+
+    Fix timeouts on incoming DoH connections with nghttp2
+
+  .. change::
+    :tags: Bug Fixes, Metrics
+    :pullreq: 13302
+
+    Fix a typo in 'Client timeouts'  (phonedph1)
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 13305
+
+    Set proper levels when logging messages
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 13310
+
+    Fix several cosmetic issues in eBPF dynamic blocks, update documentation
+
+  .. change::
+    :tags: Improvements, Webserver
+    :pullreq: 13335
+
+    Display the rule name, if any, in the web interface
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 13340
+
+    Netmask: Normalize subnet masks coming from a string
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 13372
+    :tickets: 13280
+
+    Prevent DNS header alignment issues
+
+.. changelog::
+  :version: 1.9.0-alpha2
+  :released: Never
+
+  This version was never released due to a last-minute issue in RPM packaging.
+
 .. changelog::
   :version: 1.8.2
   :released: 11th of October 2023
index a6ae16bc09b08c5d396b9ceba9e687e74d664dee..59f8e5baef4a346398e1a5ce1ffc92f277175d8f 100644 (file)
@@ -92,7 +92,7 @@ changelog_render_pullreq = "https://github.com/PowerDNS/pdns/pull/%s"
 changelog_render_changeset = "https://github.com/PowerDNS/pdns/commit/%s"
 
 changelog_sections = ['New Features', 'Improvements', 'Bug Fixes', 'Removals']
-changelog_inner_tag_sort = ['Security', 'DNS over HTTPS', 'DNS over TLS', 'DNSCrypt', 'DNSTAP', 'Protobuf', 'Performance', 'Webserver', 'Metrics']
+changelog_inner_tag_sort = ['Security', 'DNS over QUIC', 'DNS over HTTPS', 'DNS over TLS', 'DNSCrypt', 'DNSTAP', 'Protobuf', 'Performance', 'Webserver', 'Metrics']
 
 changelog_hide_tags_in_entry = True
 
index 2ad6c449568c8527b61e64f550c5d9103afb14b5..96cab46b8868385597809d149f1e81d61167ad9f 100755 (executable)
@@ -793,6 +793,16 @@ URL Endpoints
   :>json list: A list of metrics related to that pool
   :>json list servers: A list of :json:object:`Server` objects present in that pool
 
+.. http:get:: /api/v1/servers/localhost/rings?maxQueries=NUM&maxResponses=NUM
+
+  .. versionadded:: 1.9.0
+
+  Get the most recent queries and responses from the in-memory ring buffers. Returns up to ``maxQueries``
+  query entries if set, up to ``maxResponses`` responses if set, and the whole content of the ring buffers otherwise.
+
+  :>json list queries: The list of the most recent queries, as :json:object:`RingEntry` objects
+  :>json list responses: The list of the most recent responses, as :json:object:`RingEntry` objects
+
 JSON Objects
 ~~~~~~~~~~~~
 
@@ -969,3 +979,23 @@ JSON Objects
   :property string name: The name of this statistic. See :doc:`../statistics`
   :property string type: "StatisticItem"
   :property integer value: The value for this item
+
+.. json:object:: RingEntry
+
+  This represents an entry in the in-memory ring buffers.
+
+  :property float age: How long ago was the query or response received, in seconds
+  :property integer id: The DNS ID
+  :property string name: The requested domain name
+  :property string requestor: The client IP and port
+  :property integer size: The size of the query or response
+  :property integer qtype: The requested DNS type
+  :property string protocol: The DNS protocol the query or response was received over
+  :property boolean rd: The RD flag
+  :property string mac: The MAC address of the device sending the query
+  :property float latency: The time it took for the response to be sent back to the client, in microseconds
+  :property int rcode: The response code
+  :property boolean tc: The TC flag
+  :property boolean aa: The AA flag
+  :property integer answers: The number of records in the answer section of the response
+  :property string backend: The IP and port of the backend that returned the response, or "Cache" if it was a cache-hit
index 5c87e2bbf5c3900dc7c51c0177fc991d7a6fef50..13b672855a9ca7ac0ebeac13a85314d9d71021f3 100644 (file)
@@ -60,7 +60,7 @@ dnsdist depends on the following libraries:
 * `protobuf <https://developers.google.com/protocol-buffers/>`_ (optional, not needed as of 1.6.0)
 * `quiche <https://github.com/cloudflare/quiche>`_ (optional, incoming DoQ support)
 * `re2 <https://github.com/google/re2>`_ (optional)
-* `TinyCDB <https://www.corpit.ru/mjt/tinycdb.html>` (optional, CDB support)
+* `TinyCDB <https://www.corpit.ru/mjt/tinycdb.html>`_ (optional, CDB support)
 
 Should :program:`dnsdist` be run on a system with systemd, it is highly recommended to have
 the systemd header files (``libsystemd-dev`` on Debian and ``systemd-devel`` on CentOS)
index 8e5d4fc599ec5f16cc4ca8bc7577411660fc341c..6d59930d51c2cbcbfe43cdfe45a68dd8113a5c5c 100644 (file)
@@ -150,7 +150,7 @@ Listen Sockets
   * ``minTLSVersion``: str - Minimum version of the TLS protocol to support. Possible values are 'tls1.0', 'tls1.1', 'tls1.2' and 'tls1.3'. Default is to require at least TLS 1.0.
   * ``numberOfTicketsKeys``: int - The maximum number of tickets keys to keep in memory at the same time. Only one key is marked as active and used to encrypt new tickets while the remaining ones can still be used to decrypt existing tickets after a rotation. Default to 5.
   * ``ticketKeyFile``: str - The path to a file from where TLS tickets keys should be loaded, to support :rfc:`5077`. These keys should be rotated often and never written to persistent storage to preserve forward secrecy. The default is to generate a random key. dnsdist supports several tickets keys to be able to decrypt existing sessions after the rotation. See :doc:`../advanced/tls-sessions-management` for more information.
-  * ``ticketsKeysRotationDelay``: int - Set the delay before the TLS tickets key is rotated, in seconds. Default is 43200 (12h).
+  * ``ticketsKeysRotationDelay``: int - Set the delay before the TLS tickets key is rotated, in seconds. Default is 43200 (12h). A value of 0 disables the automatic rotation, which might be useful when ``ticketKeyFile`` is used.
   * ``sessionTimeout``: int - Set the TLS session lifetime in seconds, this is used both for TLS ticket lifetime and for sessions kept in memory.
   * ``sessionTickets``: bool - Whether session resumption via session tickets is enabled. Default is true, meaning tickets are enabled.
   * ``numberOfStoredSessions``: int - The maximum number of sessions kept in memory at the same time. Default is 20480. Setting this value to 0 disables stored session entirely.
@@ -229,7 +229,7 @@ Listen Sockets
   * ``ciphersTLS13``: str - The ciphers to use for TLS 1.3, when the OpenSSL provider is used. When the GnuTLS provider is used, ``ciphers`` applies regardless of the TLS protocol and this setting is not used.
   * ``numberOfTicketsKeys``: int - The maximum number of tickets keys to keep in memory at the same time, if the provider supports it (GnuTLS doesn't, OpenSSL does). Only one key is marked as active and used to encrypt new tickets while the remaining ones can still be used to decrypt existing tickets after a rotation. Default to 5.
   * ``ticketKeyFile``: str - The path to a file from where TLS tickets keys should be loaded, to support :rfc:`5077`. These keys should be rotated often and never written to persistent storage to preserve forward secrecy. The default is to generate a random key. The OpenSSL provider supports several tickets keys to be able to decrypt existing sessions after the rotation, while the GnuTLS provider only supports one key. See :doc:`../advanced/tls-sessions-management` for more information.
-  * ``ticketsKeysRotationDelay``: int - Set the delay before the TLS tickets key is rotated, in seconds. Default is 43200 (12h).
+  * ``ticketsKeysRotationDelay``: int - Set the delay before the TLS tickets key is rotated, in seconds. Default is 43200 (12h).  A value of 0 disables the automatic rotation, which might be useful when ``ticketKeyFile`` is used.
   * ``sessionTimeout``: int - Set the TLS session lifetime in seconds, this is used both for TLS ticket lifetime and for sessions kept in memory.
   * ``sessionTickets``: bool - Whether session resumption via session tickets is enabled. Default is true, meaning tickets are enabled.
   * ``numberOfStoredSessions``: int - The maximum number of sessions kept in memory at the same time. At this time this is only supported by the OpenSSL provider, as stored sessions are not supported with the GnuTLS one. Default is 20480. Setting this value to 0 disables stored session entirely.
@@ -1662,6 +1662,14 @@ faster than the existing rules.
 
     :param list netmasks: A :class:`NetmaskGroup` object, or a netmask or list of netmasks as strings, like for example "192.0.2.1/24"
 
+  .. method:: DynBlockRulesGroup:removeRange(netmasks)
+
+    .. versionadded:: 1.9.0
+
+    Remove a previously included or excluded range. The range should be an exact match of the existing entry to remove.
+
+    :param list netmasks: A :class:`NetmaskGroup` object, or a netmask or list of netmasks as strings, like for example "192.0.2.1/24"
+
   .. method:: DynBlockRulesGroup:toString()
 
     Return a string describing the rules and range exclusions of this DynBlockRulesGroup.
@@ -1820,6 +1828,11 @@ Other functions
 
   :param str path: The path to the file, usually /etc/resolv.conf
 
+.. function:: getStatisticsCounters()
+
+  This function returns a Lua associative array of metrics, with the metric name as key and the current value
+  of the counter as value.
+
 .. function:: maintenance()
 
   If this function exists, it is called every second to do regular tasks.
index 33e209e5539daf53bf69e14fd337912867cecb5a..4aa675fb1e3a1396e144fc521984579800487dd8 100644 (file)
@@ -279,6 +279,15 @@ This state can be modified from the various hooks.
     :param int code: The EDNS option code
     :param string data: The EDNS option raw data
 
+  .. method:: DNSQuestion:setExtendedDNSError(infoCode [, extraText])
+
+    .. versionadded:: 1.9.0
+
+      Set an Extended DNS Error status that will be added to the response corresponding to the current query.
+
+    :param int infoCode: The EDNS Extended DNS Error code
+    :param string extraText: The optional EDNS Extended DNS Error extra text
+
   .. method:: DNSQuestion:setHTTPResponse(status, body, contentType="")
 
     .. versionadded:: 1.4.0
index 2fb0081eb67cae8d99e8b06f799c67e5aaa65a72..090b5a7701782e51e75a237ffb53db15de602a5a 100644 (file)
@@ -938,10 +938,6 @@ Some actions allow further processing of rules, this is noted in their descripti
 - :func:`NoneAction`
 - :func:`RemoteLogAction`
 - :func:`RemoteLogResponseAction`
-- :func:`SetMaxReturnedTTLResponseAction`
-- :func:`SetMaxReturnedTTLAction`
-- :func:`SetMinTTLResponseAction`
-- :func:`SetMaxTTLResponseAction`
 - :func:`SNMPTrapAction`
 - :func:`SNMPTrapResponseAction`
 - :func:`TeeAction`
@@ -1515,6 +1511,26 @@ The following actions exist.
   :param int option: The EDNS option number
   :param string data: The EDNS0 option raw content
 
+.. function:: SetExtendedDNSErrorAction(infoCode [, extraText])
+
+  .. versionadded:: 1.9.0
+
+  Set an Extended DNS Error status that will be added to the response corresponding to the current query.
+  Subsequent rules are processed after this action.
+
+  :param int infoCode: The EDNS Extended DNS Error code
+  :param string extraText: The optional EDNS Extended DNS Error extra text
+
+.. function:: SetExtendedDNSErrorResponseAction(infoCode [, extraText])
+
+  .. versionadded:: 1.9.0
+
+  Set an Extended DNS Error status that will be added to this response.
+  Subsequent rules are processed after this action.
+
+  :param int infoCode: The EDNS Extended DNS Error code
+  :param string extraText: The optional EDNS Extended DNS Error extra text
+
 .. function:: SetMacAddrAction(option)
 
   .. versionadded:: 1.6.0
index 0d5b5ed1c52f2991011c126c099baba0a7e8b553..664c38df56ff11ba66d2e0b7a43c2539335fc58f 100644 (file)
@@ -68,6 +68,10 @@ doh-response-pipe-full
 ----------------------
 Number of responses dropped because the internal DoH pipe was full.
 
+doq-response-pipe-full
+----------------------
+Number of responses dropped because the internal DoQ pipe was full.
+
 downstream-send-errors
 ----------------------
 Number of errors when sending a query to a backend.
@@ -145,6 +149,22 @@ latency-doh-avg1000000
 ----------------------
 Average response latency, in microseconds, of the last 1000000 packets received over DoH.
 
+latency-doq-avg100
+------------------
+Average response latency, in microseconds, of the last 100 packets received over DoQ.
+
+latency-doq-avg1000
+-------------------
+Average response latency, in microseconds, of the last 1000 packets received over DoQ.
+
+latency-doq-avg10000
+--------------------
+Average response latency, in microseconds, of the last 10000 packets received over DoQ.
+
+latency-doq-avg1000000
+----------------------
+Average response latency, in microseconds, of the last 1000000 packets received over DoQ.
+
 latency-dot-avg100
 ------------------
 Average response latency, in microseconds, of the last 100 packets received over DoT.
index 94782c812192c927b309229039a738620758e91e..47c6d904f2d263ca5bc17f5449dedf438ad37dcc 100644 (file)
@@ -26,6 +26,7 @@
 #include "dns.hh"
 #include "dolog.hh"
 #include "dnsdist-concurrent-connections.hh"
+#include "dnsdist-dnsparser.hh"
 #include "dnsdist-ecs.hh"
 #include "dnsdist-metrics.hh"
 #include "dnsdist-proxy-protocol.hh"
@@ -499,7 +500,7 @@ public:
     DNSResponse dr(dohUnit->ids, dohUnit->response, dohUnit->downstream);
 
     dnsheader cleartextDH{};
-    memcpy(&cleartextDH, dr.getHeader(), sizeof(cleartextDH));
+    memcpy(&cleartextDH, dr.getHeader().get(), sizeof(cleartextDH));
 
     if (!response.isAsync()) {
       static thread_local LocalStateHolder<vector<DNSDistResponseRuleAction>> localRespRuleActions = g_respruleactions.getLocal();
@@ -716,17 +717,20 @@ static void processDOHQuery(DOHUnitUniquePtr&& unit, bool inMainThread = false)
     {
       /* don't keep that pointer around, it will be invalidated if the buffer is ever resized */
       // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
-      auto* dnsHeader = reinterpret_cast<struct dnsheader*>(unit->query.data());
+      const dnsheader_aligned dnsHeader(unit->query.data());
 
-      if (!checkQueryHeaders(dnsHeader, clientState)) {
+      if (!checkQueryHeaders(dnsHeader.get(), clientState)) {
         unit->status_code = 400;
         handleImmediateResponse(std::move(unit), "DoH invalid headers");
         return;
       }
 
       if (dnsHeader->qdcount == 0U) {
-        dnsHeader->rcode = RCode::NotImp;
-        dnsHeader->qr = true;
+        dnsdist::PacketMangling::editDNSHeaderFromPacket(unit->query, [](dnsheader& header) {
+          header.rcode = RCode::NotImp;
+          header.qr = true;
+          return true;
+        });
         unit->response = std::move(unit->query);
 
         handleImmediateResponse(std::move(unit), "DoH empty query");
@@ -751,7 +755,7 @@ static void processDOHQuery(DOHUnitUniquePtr&& unit, bool inMainThread = false)
       // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
     ids.qname = DNSName(reinterpret_cast<const char*>(unit->query.data()), static_cast<int>(unit->query.size()), static_cast<int>(sizeof(dnsheader)), false, &ids.qtype, &ids.qclass);
     DNSQuestion dnsQuestion(ids, unit->query);
-    const uint16_t* flags = getFlagsFromDNSHeader(dnsQuestion.getHeader());
+    const uint16_t* flags = getFlagsFromDNSHeader(dnsQuestion.getHeader().get());
     ids.origFlags = *flags;
     ids.cs = &clientState;
     dnsQuestion.sni = std::move(unit->sni);
@@ -808,6 +812,10 @@ static void processDOHQuery(DOHUnitUniquePtr&& unit, bool inMainThread = false)
 
       /* this moves du->ids, careful! */
       auto cpq = std::make_unique<DoHCrossProtocolQuery>(std::move(unit), false);
+      if (!cpq) {
+        // make linters happy
+        return;
+      }
       cpq->query.d_proxyProtocolPayload = std::move(proxyProtocolPayload);
 
       if (downstream->passCrossProtocolQuery(std::move(cpq))) {
@@ -1322,9 +1330,10 @@ static void on_dnsdist(h2o_socket_t *listener, const char *err)
         dohUnit->query.size() > dohUnit->ids.d_proxyProtocolPayloadSize &&
         (dohUnit->query.size() - dohUnit->ids.d_proxyProtocolPayloadSize) > sizeof(dnsheader)) {
       /* restoring the original ID */
-      // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
-      auto* queryDH = reinterpret_cast<struct dnsheader*>(&dohUnit->query.at(dohUnit->ids.d_proxyProtocolPayloadSize));
-      queryDH->id = dohUnit->ids.origID;
+      dnsdist::PacketMangling::editDNSHeaderFromRawPacket(&dohUnit->query.at(dohUnit->ids.d_proxyProtocolPayloadSize), [oldID=dohUnit->ids.origID](dnsheader& header) {
+        header.id = oldID;
+        return true;
+      });
       dohUnit->ids.forwardedOverUDP = false;
       dohUnit->tcp = true;
       dohUnit->truncated = false;
@@ -1645,7 +1654,7 @@ void DOHUnit::handleUDPResponse(PacketBuffer&& udpResponse, InternalQueryState&&
 
     DNSResponse dnsResponse(dohUnit->ids, udpResponse, dohUnit->downstream);
     dnsheader cleartextDH{};
-    memcpy(&cleartextDH, dnsResponse.getHeader(), sizeof(cleartextDH));
+    memcpy(&cleartextDH, dnsResponse.getHeader().get(), sizeof(cleartextDH));
 
     dnsResponse.ids.du = std::move(dohUnit);
     if (!processResponse(udpResponse, *localRespRuleActions, *localCacheInsertedRespRuleActions, dnsResponse, false)) {
index 9489120191bda6554456b15065cfb423380934ed..e2fc597d132ec43e8bc2dc5bcbde422fce10a2bf 100644 (file)
@@ -140,7 +140,7 @@ public:
     DNSResponse dnsResponse(unit->ids, unit->response, unit->downstream);
 
     dnsheader cleartextDH{};
-    memcpy(&cleartextDH, dnsResponse.getHeader(), sizeof(cleartextDH));
+    memcpy(&cleartextDH, dnsResponse.getHeader().get(), sizeof(cleartextDH));
 
     if (!response.isAsync()) {
 
index 4f3bc695e95e9f5948b801197e2a4cdc242c5b7a..29571e9067d25e2571f06ca71e0f70651387d1f6 100644 (file)
@@ -50,7 +50,7 @@
     </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: 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/>
+      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, DoQ <span id="latency-doq"></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>
index 1db6999dbaa0a0b87d4ab86fda4c58f2f9caa6de..4f9f125509934fd5333d356510eb3eb63a21a853 100644 (file)
@@ -154,6 +154,7 @@ $(document).ready(function() {
                 $("#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));
+                $("#latency-doq").text((data["latency-doq-avg10000"]/1000.0).toFixed(2));
                 if(!gdata["cpu-sys-msec"]) 
                     gdata=data;
 
index e0ea5fc6a17d7d21a86c4adcd18839443dfb7042..0488e0ee83413f46117b710fca0d8724e86346e0 100644 (file)
@@ -1,5 +1,5 @@
 AC_DEFUN([DNSDIST_ENABLE_DNS_OVER_QUIC], [
-  AC_MSG_CHECKING([whether to enable incoming DNS over QUIC (DoH) support])
+  AC_MSG_CHECKING([whether to enable incoming DNS over QUIC (DoQ) support])
   AC_ARG_ENABLE([dns-over-quic],
     AS_HELP_STRING([--enable-dns-over-quic], [enable incoming DNS over QUIC (DoQ) support (requires quiche) @<:@default=no@:>@]),
     [enable_dns_over_quic=$enableval],
index fc1d8d46a5b32b08a38879edf3f9f51d56628959..5c3297bc7821f45861a1788832a22b93c156d29d 100644 (file)
@@ -10,7 +10,7 @@ AC_DEFUN([PDNS_WITH_QUICHE], [
 
   AS_IF([test "x$with_quiche" != "xno"], [
     AS_IF([test "x$with_quiche" = "xyes" -o "x$with_quiche" = "xauto"], [
-      PKG_CHECK_MODULES([QUICHE], [quiche], [
+      PKG_CHECK_MODULES([QUICHE], [quiche >= 0.15.0], [
         [HAVE_QUICHE=1]
         AC_DEFINE([HAVE_QUICHE], [1], [Define to 1 if you have quiche])
       ], [ : ])
index cc29a195d5430acaf71f37b567f141455327949d..52f8076c30f459ae99412034c3fc5c7a488b4fd5 100644 (file)
@@ -451,7 +451,7 @@ BOOST_AUTO_TEST_CASE(test_Overlay)
 
       BOOST_CHECK_EQUAL(record.d_name, target);
       BOOST_CHECK_EQUAL(record.d_class, QClass::IN);
-      BOOST_CHECK_EQUAL(record.d_ttl, 7200);
+      BOOST_CHECK_EQUAL(record.d_ttl, 7200U);
       BOOST_CHECK_EQUAL(record.d_place, 1U);
       BOOST_CHECK_GE(record.d_contentOffset, lastOffset);
       lastOffset = record.d_contentOffset + record.d_contentLength;
index 81897a340d1ca88a152f5e45442af6c89d2e8282..56047a7f0c8e79ae4c5da787f34d42cf3a8b1b0f 100644 (file)
@@ -466,7 +466,7 @@ BOOST_AUTO_TEST_CASE(test_PacketCache)
   ids.queryRealTime.start();
   DNSQuestion dq(ids, query);
   packetCache->get(dq, 0, &key, subnet, dnssecOK, receivedOverUDP);
-  packetCache->insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, ids.qname, QType::A, QClass::IN, response, receivedOverUDP, 0, boost::none);
+  packetCache->insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader().get())), dnssecOK, ids.qname, QType::A, QClass::IN, response, receivedOverUDP, 0, boost::none);
 
   std::string poolName("test-pool");
   auto testPool = std::make_shared<ServerPool>();
@@ -734,7 +734,7 @@ BOOST_AUTO_TEST_CASE(test_RingBuffers)
   for (size_t idx = 0; idx < 2; idx++) {
     BOOST_CHECK(dnsdist_ffi_ring_entry_get_name(list, idx) == qname.toString());
     BOOST_CHECK(dnsdist_ffi_ring_entry_get_type(list, idx) == qtype);
-    BOOST_CHECK(dnsdist_ffi_ring_entry_get_requestor(list, idx) == requestor1.toString());
+    BOOST_CHECK(dnsdist_ffi_ring_entry_get_requestor(list, idx) == requestor1.toStringWithPort());
     BOOST_CHECK(dnsdist_ffi_ring_entry_get_protocol(list, idx) == protocol.toNumber());
     BOOST_CHECK_EQUAL(dnsdist_ffi_ring_entry_get_size(list, idx), size);
     BOOST_CHECK(!dnsdist_ffi_ring_entry_has_mac_address(list, idx));
index 2a479bf2be68a476b147fcc6177f54eb4da63c7c..27364fa3708bf38e0e967ba484fb2e98db52fc78 100644 (file)
@@ -29,7 +29,7 @@
 #include "dnsdist-proxy-protocol.hh"
 #include "dnsdist-nghttp2-in.hh"
 
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
 #include <nghttp2/nghttp2.h>
 
 extern std::function<ProcessQueryResult(DNSQuestion& dnsQuestion, std::shared_ptr<DownstreamState>& selectedBackend)> s_processQuery;
@@ -736,4 +736,4 @@ BOOST_FIXTURE_TEST_CASE(test_IncomingConnection_BackendTimeout, TestFixture)
 }
 
 BOOST_AUTO_TEST_SUITE_END();
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
index b971e4ac15173018fe92fd70808cf5c24fe4ea76..2d86c970061491ba696c62478039384743520350 100644 (file)
@@ -31,7 +31,7 @@
 #include "dnsdist-nghttp2.hh"
 #include "sstuff.hh"
 
-#ifdef HAVE_NGHTTP2
+#if defined(HAVE_DNS_OVER_HTTPS) && defined(HAVE_NGHTTP2)
 #include <nghttp2/nghttp2.h>
 
 BOOST_AUTO_TEST_SUITE(test_dnsdistnghttp2_cc)
@@ -251,7 +251,7 @@ private:
 
       auto& query = conn->d_queries.at(frame->hd.stream_id);
       BOOST_REQUIRE_GT(query.size(), sizeof(dnsheader));
-      auto dh = reinterpret_cast<const dnsheader*>(query.data());
+      const dnsheader_aligned dh(query.data());
       uint16_t id = ntohs(dh->id);
       // cerr<<"got query ID "<<id<<endl;
 
@@ -500,7 +500,7 @@ public:
     }
 
     BOOST_REQUIRE_GT(response.d_buffer.size(), sizeof(dnsheader));
-    auto dh = reinterpret_cast<const dnsheader*>(response.d_buffer.data());
+    const dnsheader_aligned dh(response.d_buffer.data());
     uint16_t id = ntohs(dh->id);
 
     BOOST_REQUIRE_EQUAL(id, d_id);
@@ -1846,4 +1846,4 @@ BOOST_FIXTURE_TEST_CASE(test_ProxyProtocol, TestFixture)
 }
 
 BOOST_AUTO_TEST_SUITE_END();
-#endif /* HAVE_NGHTTP2 */
+#endif /* HAVE_DNS_OVER_HTTPS && HAVE_NGHTTP2 */
index 7b83ad55fc1b4a6d4cd85fa62c78b99bbc36c27b..df48d0c9847a8126383e471e71e869c3a3f3d57d 100644 (file)
@@ -119,12 +119,12 @@ shared_ptr<DNSRecordContent> DNSRecordContent::deserialize(const DNSName& qname,
   PacketReader pr(std::string_view(reinterpret_cast<const char*>(packet.data()), packet.size()), packet.size() - serialized.size() - sizeof(dnsrecordheader));
   /* needed to get the record boundaries right */
   pr.getDnsrecordheader(drh);
-  auto content = DNSRecordContent::mastermake(dr, pr, Opcode::Query);
+  auto content = DNSRecordContent::make(dr, pr, Opcode::Query);
   return content;
 }
 
-std::shared_ptr<DNSRecordContent> DNSRecordContent::mastermake(const DNSRecord &dr,
-                                               PacketReader& pr)
+std::shared_ptr<DNSRecordContent> DNSRecordContent::make(const DNSRecord& dr,
+                                                         PacketReader& pr)
 {
   uint16_t searchclass = (dr.d_type == QType::OPT) ? 1 : dr.d_class; // class is invalid for OPT
 
@@ -136,8 +136,8 @@ std::shared_ptr<DNSRecordContent> DNSRecordContent::mastermake(const DNSRecord &
   return i->second(dr, pr);
 }
 
-std::shared_ptr<DNSRecordContent> DNSRecordContent::mastermake(uint16_t qtype, uint16_t qclass,
-                                               const string& content)
+std::shared_ptr<DNSRecordContent> DNSRecordContent::make(uint16_t qtype, uint16_t qclass,
+                                                         const string& content)
 {
   auto i = getZmakermap().find(pair(qclass, qtype));
   if(i==getZmakermap().end()) {
@@ -147,7 +147,8 @@ std::shared_ptr<DNSRecordContent> DNSRecordContent::mastermake(uint16_t qtype, u
   return i->second(content);
 }
 
-std::shared_ptr<DNSRecordContent> DNSRecordContent::mastermake(const DNSRecord &dr, PacketReader& pr, uint16_t oc) {
+std::shared_ptr<DNSRecordContent> DNSRecordContent::make(const DNSRecord& dr, PacketReader& pr, uint16_t oc)
+{
   // For opcode UPDATE and where the DNSRecord is an answer record, we don't care about content, because this is
   // not used within the prerequisite section of RFC2136, so - we can simply use unknownrecordcontent.
   // For section 3.2.3, we do need content so we need to get it properly. But only for the correct QClasses.
@@ -207,7 +208,7 @@ DNSRecord::DNSRecord(const DNSResourceRecord& rr): d_name(rr.qname)
   d_class = rr.qclass;
   d_place = DNSResourceRecord::ANSWER;
   d_clen = 0;
-  d_content = DNSRecordContent::mastermake(d_type, rr.qclass, rr.content);
+  d_content = DNSRecordContent::make(d_type, rr.qclass, rr.content);
 }
 
 // If you call this and you are not parsing a packet coming from a socket, you are doing it wrong.
@@ -288,7 +289,7 @@ void MOADNSParser::init(bool query, const std::string_view& packet)
       }
       else {
 //        cerr<<"parsing RR, query is "<<query<<", place is "<<dr.d_place<<", type is "<<dr.d_type<<", class is "<<dr.d_class<<endl;
-        dr.setContent(DNSRecordContent::mastermake(dr, pr, d_header.opcode));
+        dr.setContent(DNSRecordContent::make(dr, pr, d_header.opcode));
       }
 
       /* XXX: XPF records should be allowed after TSIG as soon as the actual XPF option code has been assigned:
@@ -768,7 +769,7 @@ static bool checkIfPacketContainsRecords(const PacketBuffer& packet, const std::
   }
 
   try {
-    auto dh = reinterpret_cast<const dnsheader*>(packet.data());
+    const dnsheader_aligned dh(packet.data());
     DNSPacketMangler dpm(const_cast<char*>(reinterpret_cast<const char*>(packet.data())), length);
 
     const uint16_t qdcount = ntohs(dh->qdcount);
@@ -804,7 +805,7 @@ static int rewritePacketWithoutRecordTypes(const PacketBuffer& initialPacket, Pa
     return EINVAL;
   }
   try {
-    const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(initialPacket.data());
+    const dnsheader_aligned dh(initialPacket.data());
 
     if (ntohs(dh->qdcount) == 0)
       return ENOENT;
@@ -979,7 +980,7 @@ uint32_t getDNSPacketMinTTL(const char* packet, size_t length, bool* seenAuthSOA
   }
   try
   {
-    const dnsheader* dh = (const dnsheader*) packet;
+    const dnsheader_aligned dh(packet);
     DNSPacketMangler dpm(const_cast<char*>(packet), length);
 
     const uint16_t qdcount = ntohs(dh->qdcount);
@@ -1026,7 +1027,7 @@ uint32_t getDNSPacketLength(const char* packet, size_t length)
   }
   try
   {
-    const dnsheader* dh = reinterpret_cast<const dnsheader*>(packet);
+    const dnsheader_aligned dh(packet);
     DNSPacketMangler dpm(const_cast<char*>(packet), length);
 
     const uint16_t qdcount = ntohs(dh->qdcount);
@@ -1058,7 +1059,7 @@ uint16_t getRecordsOfTypeCount(const char* packet, size_t length, uint8_t sectio
   }
   try
   {
-    const dnsheader* dh = (const dnsheader*) packet;
+    const dnsheader_aligned dh(packet);
     DNSPacketMangler dpm(const_cast<char*>(packet), length);
 
     const uint16_t qdcount = ntohs(dh->qdcount);
@@ -1148,7 +1149,7 @@ bool getEDNSUDPPayloadSizeAndZ(const char* packet, size_t length, uint16_t* payl
 
   try
   {
-    const dnsheader* dh = (const dnsheader*) packet;
+    const dnsheader_aligned dh(packet);
     DNSPacketMangler dpm(const_cast<char*>(packet), length);
 
     const uint16_t qdcount = ntohs(dh->qdcount);
@@ -1191,13 +1192,12 @@ bool visitDNSPacket(const std::string_view& packet, const std::function<bool(uin
 
   try
   {
-    dnsheader dh;
-    memcpy(&dh, reinterpret_cast<const dnsheader*>(packet.data()), sizeof(dh));
-    uint64_t numrecords = ntohs(dh.ancount) + ntohs(dh.nscount) + ntohs(dh.arcount);
+    const dnsheader_aligned dh(packet.data());
+    uint64_t numrecords = ntohs(dh->ancount) + ntohs(dh->nscount) + ntohs(dh->arcount);
     PacketReader reader(packet);
 
     uint64_t n;
-    for (n = 0; n < ntohs(dh.qdcount) ; ++n) {
+    for (n = 0; n < ntohs(dh->qdcount) ; ++n) {
       (void) reader.getName();
       /* type and class */
       reader.skip(4);
@@ -1206,7 +1206,7 @@ bool visitDNSPacket(const std::string_view& packet, const std::function<bool(uin
     for (n = 0; n < numrecords; ++n) {
       (void) reader.getName();
 
-      uint8_t section = n < ntohs(dh.ancount) ? 1 : (n < (ntohs(dh.ancount) + ntohs(dh.nscount)) ? 2 : 3);
+      uint8_t section = n < ntohs(dh->ancount) ? 1 : (n < (ntohs(dh->ancount) + ntohs(dh->nscount)) ? 2 : 3);
       uint16_t dnstype = reader.get16BitInt();
       uint16_t dnsclass = reader.get16BitInt();
 
index 014087ef35ab9aca79b682be78c82cb72c30ca84..dd87f252643c9923baa6ee08700f409f946213f1 100644 (file)
@@ -192,9 +192,9 @@ struct DNSRecord;
 class DNSRecordContent
 {
 public:
-  static std::shared_ptr<DNSRecordContent> mastermake(const DNSRecord &dr, PacketReader& pr);
-  static std::shared_ptr<DNSRecordContent> mastermake(const DNSRecord &dr, PacketReader& pr, uint16_t opcode);
-  static std::shared_ptr<DNSRecordContent> mastermake(uint16_t qtype, uint16_t qclass, const string& zone);
+  static std::shared_ptr<DNSRecordContent> make(const DNSRecord& dr, PacketReader& pr);
+  static std::shared_ptr<DNSRecordContent> make(const DNSRecord& dr, PacketReader& pr, uint16_t opcode);
+  static std::shared_ptr<DNSRecordContent> make(uint16_t qtype, uint16_t qclass, const string& zone);
   static string upgradeContent(const DNSName& qname, const QType& qtype, const string& content);
 
   virtual std::string getZoneRepresentation(bool noDot=false) const = 0;
index 5e52d407a5f9b5629acfad37d363edc3293a287e..6922869a9bb705c1e729ad00eb8c3c68598fd363 100644 (file)
@@ -200,15 +200,25 @@ try
   bool doIPv6 = g_vm["ipv6"].as<bool>();
   bool doServFailTree = g_vm.count("servfail-tree");
   bool noservfailstats = g_vm.count("no-servfail-stats");
-  int dnserrors=0, parsefail=0;
+  int dnserrors = 0;
+  int parsefail = 0;
   typedef map<uint32_t,uint32_t> cumul_t;
   cumul_t cumul;
-  unsigned int untracked=0, errorresult=0, nonRDQueries=0, queries=0;
-  unsigned int ipv4DNSPackets=0, ipv6DNSPackets=0, fragmented=0, rdNonRAAnswers=0;
-  unsigned int answers=0, nonDNSIP=0, rdFilterMismatch=0;
-  unsigned int dnssecOK=0, edns=0;
-  unsigned int dnssecCD=0, dnssecAD=0;
-  unsigned int reuses=0;
+  unsigned int untracked = 0;
+  unsigned int nonRDQueries = 0;
+  unsigned int queries = 0;
+  unsigned int ipv4DNSPackets = 0;
+  unsigned int ipv6DNSPackets = 0;
+  unsigned int fragmented = 0;
+  unsigned int rdNonRAAnswers = 0;
+  unsigned int answers = 0;
+  unsigned int nonDNSIP = 0;
+  unsigned int rdFilterMismatch = 0;
+  unsigned int dnssecOK = 0;
+  unsigned int edns = 0;
+  unsigned int dnssecCD = 0;
+  unsigned int dnssecAD = 0;
+  unsigned int reuses = 0;
   typedef map<uint16_t,uint32_t> rcodes_t;
   rcodes_t rcodes;
 
@@ -373,8 +383,6 @@ try
             if(!noservfailstats || header.rcode != 2)
               cumul[usecs]++;
 
-            if(header.rcode != 0 && header.rcode!=3)
-              errorresult++;
             ComboAddress rem = pr.getDest();
             rem.sin4.sin_port=0;
 
index 10503d53456d25d5e6b0cfed45e5ef2592aec509..50e81bbb1522bdd781218c77fcdf4276469d31d5 100644 (file)
@@ -220,7 +220,7 @@ public:
   bool unsetPublishCDS(const DNSName& zname);
 
   bool TSIGGrantsAccess(const DNSName& zone, const DNSName& keyname);
-  bool getTSIGForAccess(const DNSName& zone, const ComboAddress& master, DNSName* keyname);
+  bool getTSIGForAccess(const DNSName& zone, const ComboAddress& primary, DNSName* keyname);
 
   void startTransaction(const DNSName& zone, int zone_id)
   {
index 74dc882ab012fffdcdf4301d58f912f6cc06b46b..06ac28ce993d3b33d4d72a425f776aed17310475 100644 (file)
@@ -88,7 +88,7 @@ static void fillOutRRSIG(DNSSECPrivateKey& dpk, const DNSName& signQName, RRSIGR
   rrc.d_signature = rc->sign(msg);
   (*g_signatureCount)++;
   if(doCache) {
-    /* we add some jitter here so not all your slaves start pruning their caches at the very same millisecond */
+    /* we add some jitter here so not all your secondaries start pruning their caches at the very same millisecond */
     int weekno = (time(nullptr) - dns_random(3600)) / (86400*7);  // we just spent milliseconds doing a signature, microsecond more won't kill us
     const static int maxcachesize=::arg().asNum("max-signature-cache-entries", INT_MAX);
 
index 212c3b5f8fb88d63f03b985da4867c7a0720e097..909f08e0b791a69d08025c3d6f1dfb78b77ef868 100644 (file)
@@ -74,7 +74,7 @@ DnstapMessage::DnstapMessage(std::string& buffer, DnstapMessage::MessageType typ
   }
 
   if (packet != nullptr && len >= sizeof(dnsheader)) {
-    const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(packet);
+    const dnsheader_aligned dh(packet);
     if (!dh->qr) {
       pbf_message.add_bytes(DnstapMessageFields::query_message, packet, len);
     } else {
index b35ebc7a9607a3a63f9ef826c343b5fc43ac0e18..7f63177dcd6a8bcddd84721ac12911957d74d627 100644 (file)
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wdeprecated-copy-with-user-provided-copy"
 #include <boost/accumulators/statistics/median.hpp>
 #include <boost/accumulators/statistics/mean.hpp>
 #include <boost/accumulators/accumulators.hpp>
-
 #include <boost/accumulators/statistics.hpp>
+#pragma GCC diagnostic pop
 
 #include <thread>
 
index a28777ab810618f0ba3291ecd2f90526b2b74794..dd88b6f2fbf0f8b16c6b9282ae566cab4a7a8f39 100644 (file)
@@ -58,7 +58,7 @@ inline void dolog(std::ostream& os, const char*s)
 }
 
 template<typename T, typename... Args>
-void dolog(std::ostream& os, const char* s, T value, Args... args)
+void dolog(std::ostream& os, const char* s, T value, const Args&... args)
 {
   while (*s) {
     if (*s == '%') {
@@ -91,7 +91,7 @@ inline void setSyslogFacility(int facility)
 }
 
 template<typename... Args>
-void genlog(std::ostream& stream, int level, bool doSyslog, const char* s, Args... args)
+void genlog(std::ostream& stream, int level, bool doSyslog, const char* s, const Args&... args)
 {
   std::ostringstream str;
   dolog(str, s, args...);
@@ -120,7 +120,7 @@ void genlog(std::ostream& stream, int level, bool doSyslog, const char* s, Args.
 }
 
 template<typename... Args>
-void verboselog(const char* s, Args... args)
+void verboselog(const char* s, const Args&... args)
 {
 #ifdef DNSDIST
   if (g_verboseStream) {
@@ -137,19 +137,19 @@ void verboselog(const char* s, Args... args)
 #define vinfolog if (g_verbose) verboselog
 
 template<typename... Args>
-void infolog(const char* s, Args... args)
+void infolog(const char* s, const Args&... args)
 {
   genlog(std::cout, LOG_INFO, g_syslog, s, args...);
 }
 
 template<typename... Args>
-void warnlog(const char* s, Args... args)
+void warnlog(const char* s, const Args&... args)
 {
   genlog(std::cout, LOG_WARNING, g_syslog, s, args...);
 }
 
 template<typename... Args>
-void errlog(const char* s, Args... args)
+void errlog(const char* s, const Args&... args)
 {
   genlog(std::cout, LOG_ERR, g_syslog, s, args...);
 }
@@ -169,7 +169,7 @@ inline void dolog(const char* s)
 }
 
 template<typename T, typename... Args>
-void dolog(Logger::Urgency u, const char* s, T value, Args... args)
+void dolog(Logger::Urgency u, const char* s, T value, const Args&... args)
 {
   g_log << u;
   while (*s) {
@@ -191,19 +191,19 @@ void dolog(Logger::Urgency u, const char* s, T value, Args... args)
 #define vinfolog if(g_verbose)infolog
 
 template<typename... Args>
-void infolog(const char* s, Args... args)
+void infolog(const char* s, const Args&... args)
 {
   dolog(Logger::Info, s, args...);
 }
 
 template<typename... Args>
-void warnlog(const char* s, Args... args)
+void warnlog(const char* s, const Args&... args)
 {
   dolog(Logger::Warning, s, args...);
 }
 
 template<typename... Args>
-void errlog(const char* s, Args... args)
+void errlog(const char* s, const Args&... args)
 {
   dolog(Logger::Error, s, args...);
 }
index b2b35a8338ecdd16ba951608a14069c25f644b1d..4add3bfbdfaa93e975928fe383429f1051bf8411 100644 (file)
@@ -254,15 +254,15 @@ string DLNotifyRetrieveHandler(const vector<string>& parts, Utility::pid_t /* pp
     return "Failed to parse zone as valid DNS name";
   }
 
-  ComboAddress master_ip;
-  bool override_master = false;
+  ComboAddress primary_ip;
+  bool override_primary = false;
   if (parts.size() == 3) {
     try {
-      master_ip = ComboAddress{parts[2], 53};
+      primary_ip = ComboAddress{parts[2], 53};
     } catch (...) {
       return "Invalid primary address";
     }
-    override_master = true;
+    override_primary = true;
   }
 
   DomainInfo di;
@@ -271,19 +271,19 @@ string DLNotifyRetrieveHandler(const vector<string>& parts, Utility::pid_t /* pp
     return " Zone '" + domain.toString() + "' unknown";
   }
 
-  if (override_master) {
-    di.masters.clear();
-    di.masters.push_back(master_ip);
+  if (override_primary) {
+    di.primaries.clear();
+    di.primaries.push_back(primary_ip);
   }
 
-  if (!override_master && (!di.isSecondaryType() || di.masters.empty()))
+  if (!override_primary && (!di.isSecondaryType() || di.primaries.empty()))
     return "Zone '" + domain.toString() + "' is not a secondary/consumer zone (or has no primary defined)";
 
-  shuffle(di.masters.begin(), di.masters.end(), pdns::dns_random_engine());
-  const auto& master = di.masters.front();
-  Communicator.addSuckRequest(domain, master, SuckRequest::PdnsControl, override_master);
-  g_log << Logger::Warning << "Retrieval request for zone '" << domain << "' from primary '" << master << "' received from operator" << endl;
-  return "Added retrieval request for '" + domain.toLogString() + "' from primary " + master.toLogString();
+  shuffle(di.primaries.begin(), di.primaries.end(), pdns::dns_random_engine());
+  const auto& primary = di.primaries.front();
+  Communicator.addSuckRequest(domain, primary, SuckRequest::PdnsControl, override_primary);
+  g_log << Logger::Warning << "Retrieval request for zone '" << domain << "' from primary '" << primary << "' received from operator" << endl;
+  return "Added retrieval request for '" + domain.toLogString() + "' from primary " + primary.toLogString();
 }
 
 string DLNotifyHostHandler(const vector<string>& parts, Utility::pid_t /* ppid */)
index fb695283264f5f8ed031a67a8a20c046f1b157b5..613b115e91c474a60e475594eb57e37ca4e6fb0c 100644 (file)
@@ -1,6 +1,10 @@
 #pragma once
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-parameter"
+#pragma clang diagnostic ignored "-Wdeprecated-copy-with-user-provided-copy"
 #include <boost/accumulators/accumulators.hpp>
 #include <boost/accumulators/statistics.hpp>
+#pragma clang diagnostic pop
 
 #include <vector>
 #include <fstream>
index 1aa0a0b5186b25b301ed01565eca8068569af2cd..47ca071a4780a978821a8371dd1e7cb8df19cb22 100644 (file)
@@ -332,6 +332,11 @@ union ComboAddress {
     return toStringWithPortExcept(53);
   }
 
+  [[nodiscard]] string toStructuredLogString() const
+  {
+    return toStringWithPort();
+  }
+
   string toByteString() const
   {
     if (isIPv4()) {
@@ -1257,7 +1262,7 @@ public:
   }
 
   //<! checks whether the container is empty.
-  bool empty() const {
+  [[nodiscard]] bool empty() const {
     return (d_size == 0);
   }
 
@@ -1416,6 +1421,13 @@ public:
     tree.erase(nm);
   }
 
+  void deleteMasks(const NetmaskGroup& group)
+  {
+    for (const auto& entry : group.tree) {
+      deleteMask(entry.first);
+    }
+  }
+
   void deleteMask(const std::string& ip)
   {
     if (!ip.empty())
index 7d3bdfb0b5dd74cb94ce56482263c2d1840aa60f..a1592d6f339d332889152c9e3b2245a534528786 100644 (file)
@@ -54,9 +54,9 @@ std::string ixfrdistStats::getStats() {
   if (!domainStats.empty()) {
     stats<<"# HELP "<<prefix<<"soa_serial The SOA serial number of a domain"<<std::endl;
     stats<<"# TYPE "<<prefix<<"soa_serial gauge"<<std::endl;
-    stats<<"# HELP "<<prefix<<"soa_checks_total Number of times a SOA check at the master was attempted"<<std::endl;
+    stats << "# HELP " << prefix << "soa_checks_total Number of times a SOA check at the primary was attempted" << std::endl;
     stats<<"# TYPE "<<prefix<<"soa_checks_total counter"<<std::endl;
-    stats<<"# HELP "<<prefix<<"soa_checks_failed_total Number of times a SOA check at the master failed"<<std::endl;
+    stats << "# HELP " << prefix << "soa_checks_failed_total Number of times a SOA check at the primary failed" << std::endl;
     stats<<"# TYPE "<<prefix<<"soa_checks_failed_total counter"<<std::endl;
     stats<<"# HELP "<<prefix<<"soa_inqueries_total Number of times a SOA query was received"<<std::endl;
     stats<<"# TYPE "<<prefix<<"soa_inqueries_total counter"<<std::endl;
@@ -85,6 +85,19 @@ std::string ixfrdistStats::getStats() {
     stats<<prefix<<"ixfr_failures_total{domain=\""<<d.first<<"\"} "<<d.second.numIXFRFailures<<std::endl;
   }
 
+  if (!notimpStats.empty()) {
+    stats<<"# HELP "<<prefix<<"notimp An unimplemented opcode"<<std::endl;
+    stats<<"# TYPE "<<prefix<<"notimp counter"<<std::endl;
+  }
+
+  for (std::size_t i = 0; i < notimpStats.size() ; i++) {
+    auto val = notimpStats.at(i).load();
+
+    if (val > 0) {
+      stats<<prefix<<"notimp{opcode=\""<<Opcode::to_s(i)<<"\"} "<<val<<std::endl;
+    }
+  }
+
   stats<<"# HELP "<<prefix<<"unknown_domain_inqueries_total Number of queries received for domains unknown to us"<<std::endl;
   stats<<"# TYPE "<<prefix<<"unknown_domain_inqueries_total counter"<<std::endl;
   stats<<prefix<<"unknown_domain_inqueries_total "<<progStats.unknownDomainInQueries<<std::endl;
index 755e57bfb68164e27d69b4f9dc75aa9462626555..69f48f9458d88e1f846641ae54b06259939a82e1 100644 (file)
@@ -24,6 +24,7 @@
 #include <map>
 #include <string>
 
+#include "dns.hh"
 #include "dnsname.hh"
 #include "pdnsexception.hh"
 
@@ -70,6 +71,11 @@ class ixfrdistStats {
       progStats.unknownDomainInQueries += 1;
     }
 
+    void incrementNotImplemented(uint8_t opcode)
+    {
+      notimpStats.at(opcode) ++;
+    }
+
   private:
     class perDomainStat {
       public:
@@ -93,6 +99,7 @@ class ixfrdistStats {
     };
 
     std::map<DNSName, perDomainStat> domainStats;
+    std::array<std::atomic<uint64_t>, 16> notimpStats{};
     programStats progStats;
 
     std::map<DNSName, perDomainStat>::iterator getRegisteredDomain(const DNSName& d) {
index 8fba8199c3e3b17acddcb9179de8c0faa4f52f2e..4a5d9a7dbb03234fc07ee50de3ff5d732db3c75b 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 "dns.hh"
+#include "dnsparser.hh"
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 #include "logger.hh"
 #include "ixfrdist-stats.hh"
 #include "ixfrdist-web.hh"
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
 #include <yaml-cpp/yaml.h>
+#pragma GCC diagnostic pop
 
 /* BEGIN Needed because of deeper dependencies */
 #include "arguments.hh"
@@ -141,7 +146,7 @@ struct ixfrinfo_t {
 
 // Why a struct? This way we can add more options to a domain in the future
 struct ixfrdistdomain_t {
-  set<ComboAddress> masters; // A set so we can do multiple master addresses in the future
+  set<ComboAddress> primaries; // A set so we can do multiple primary addresses in the future
   uint32_t maxSOARefresh{0}; // Cap SOA refresh value to the given value in seconds
 };
 
@@ -151,6 +156,10 @@ static map<DNSName, ixfrdistdomain_t> g_domainConfigs;
 // Map domains and their data
 static LockGuarded<std::map<DNSName, std::shared_ptr<ixfrinfo_t>>> g_soas;
 
+// Queue of received NOTIFYs, already verified against their primary IPs
+// Lazily implemented as a set
+static LockGuarded<std::set<DNSName>> g_notifiesReceived;
+
 // Condition variable for TCP handling
 static std::condition_variable g_tcpHandlerCV;
 static std::queue<pair<int, ComboAddress>> g_tcpRequestFDs;
@@ -160,7 +169,8 @@ namespace po = boost::program_options;
 
 static bool g_exiting = false;
 
-static NetmaskGroup g_acl;
+static NetmaskGroup g_acl;            // networks that can QUERY us
+static NetmaskGroup g_notifySources;  // networks (well, IPs) that can NOTIFY us
 static bool g_compress = false;
 
 static ixfrdistStats g_stats;
@@ -192,20 +202,25 @@ static bool sortSOA(uint32_t i, uint32_t j) {
 
 static void cleanUpDomain(const DNSName& domain, const uint16_t& keep, const string& workdir) {
   string dir = workdir + "/" + domain.toString();
-  DIR *dp;
-  dp = opendir(dir.c_str());
-  if (dp == nullptr) {
-    return;
-  }
   vector<uint32_t> zoneVersions;
-  struct dirent *d;
-  while ((d = readdir(dp)) != nullptr) {
-    if(!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) {
-      continue;
+  {
+    auto dirHandle = std::unique_ptr<DIR, decltype(&closedir)>(opendir(dir.c_str()), closedir);
+    if (!dirHandle) {
+      return;
+    }
+
+    struct dirent* entry = nullptr;
+    // NOLINTNEXTLINE(concurrency-mt-unsafe): readdir is thread-safe nowadays and readdir_r is deprecated
+    while ((entry = readdir(dirHandle.get())) != nullptr) {
+      // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay): this is what dirent is
+      if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
+        continue;
+      }
+      //  NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay): this is what dirent is
+      zoneVersions.push_back(std::stoi(entry->d_name));
     }
-    zoneVersions.push_back(std::stoi(d->d_name));
   }
-  closedir(dp);
+
   g_log<<Logger::Info<<"Found "<<zoneVersions.size()<<" versions of "<<domain<<", asked to keep "<<keep<<", ";
   if (zoneVersions.size() <= keep) {
     g_log<<Logger::Info<<"not cleaning up"<<endl;
@@ -271,7 +286,7 @@ static void updateCurrentZoneInfo(const DNSName& domain, std::shared_ptr<ixfrinf
   // FIXME: also report zone size?
 }
 
-static void updateThread(const string& workdir, const uint16_t& keep, const uint16_t& axfrTimeout, const uint16_t& soaRetry, const uint32_t axfrMaxRecords) {
+static void updateThread(const string& workdir, const uint16_t& keep, const uint16_t& axfrTimeout, const uint16_t& soaRetry, const uint32_t axfrMaxRecords) { // NOLINT(readability-function-cognitive-complexity) 13400 https://github.com/PowerDNS/pdns/issues/13400 Habbie:  ixfrdist: reduce complexity
   setThreadName("ixfrdist/update");
   std::map<DNSName, time_t> lastCheck;
 
@@ -347,24 +362,26 @@ static void updateThread(const string& workdir, const uint16_t& keep, const uint
           refresh = std::min(refresh, domainConfig.second.maxSOARefresh);
         }
       }
-      if (now - zoneLastCheck < refresh) {
+
+
+      if (now - zoneLastCheck < refresh && g_notifiesReceived.lock()->erase(domain) == 0) {
         continue;
       }
 
-      // TODO Keep track of 'down' masters
-      set<ComboAddress>::const_iterator it(domainConfig.second.masters.begin());
-      std::advance(it, dns_random(domainConfig.second.masters.size()));
-      ComboAddress master = *it;
+      // TODO Keep track of 'down' primaries
+      set<ComboAddress>::const_iterator it(domainConfig.second.primaries.begin());
+      std::advance(it, dns_random(domainConfig.second.primaries.size()));
+      ComboAddress primary = *it;
 
       string dir = workdir + "/" + domain.toString();
-      g_log<<Logger::Info<<"Attempting to retrieve SOA Serial update for '"<<domain<<"' from '"<<master.toStringWithPort()<<"'"<<endl;
+      g_log << Logger::Info << "Attempting to retrieve SOA Serial update for '" << domain << "' from '" << primary.toStringWithPort() << "'" << endl;
       shared_ptr<const SOARecordContent> sr;
       try {
         zoneLastCheck = now;
         g_stats.incrementSOAChecks(domain);
-        auto newSerial = getSerialFromMaster(master, domain, sr); // TODO TSIG
+        auto newSerial = getSerialFromPrimary(primary, domain, sr); // TODO TSIG
         if(current_soa != nullptr) {
-          g_log<<Logger::Info<<"Got SOA Serial for "<<domain<<" from "<<master.toStringWithPort()<<": "<< newSerial<<", had Serial: "<<current_soa->d_st.serial;
+          g_log << Logger::Info << "Got SOA Serial for " << domain << " from " << primary.toStringWithPort() << ": " << newSerial << ", had Serial: " << current_soa->d_st.serial;
           if (newSerial == current_soa->d_st.serial) {
             g_log<<Logger::Info<<", not updating."<<endl;
             continue;
@@ -372,13 +389,13 @@ static void updateThread(const string& workdir, const uint16_t& keep, const uint
           g_log<<Logger::Info<<", will update."<<endl;
         }
       } catch (runtime_error &e) {
-        g_log<<Logger::Warning<<"Unable to get SOA serial update for '"<<domain<<"' from master "<<master.toStringWithPort()<<": "<<e.what()<<endl;
+        g_log << Logger::Warning << "Unable to get SOA serial update for '" << domain << "' from primary " << primary.toStringWithPort() << ": " << e.what() << endl;
         g_stats.incrementSOAChecksFailed(domain);
         continue;
       }
       // Now get the full zone!
       g_log<<Logger::Info<<"Attempting to receive full zonedata for '"<<domain<<"'"<<endl;
-      ComboAddress local = master.isIPv4() ? ComboAddress("0.0.0.0") : ComboAddress("::");
+      ComboAddress local = primary.isIPv4() ? ComboAddress("0.0.0.0") : ComboAddress("::");
       TSIGTriplet tt;
 
       // The *new* SOA
@@ -386,7 +403,7 @@ static void updateThread(const string& workdir, const uint16_t& keep, const uint
       uint32_t soaTTL = 0;
       records_t records;
       try {
-        AXFRRetriever axfr(master, domain, tt, &local);
+        AXFRRetriever axfr(primary, domain, tt, &local);
         uint32_t nrecords=0;
         Resolver::res_t nop;
         vector<DNSRecord> chunk;
@@ -474,33 +491,85 @@ static void updateThread(const string& workdir, const uint16_t& keep, const uint
   } /* while (true) */
 } /* updateThread */
 
-static bool checkQuery(const MOADNSParser& mdp, const ComboAddress& saddr, const bool udp = true, const string& logPrefix="") {
-  vector<string> info_msg;
+enum class ResponseType {
+  Unknown,
+  ValidQuery,
+  RefusedOpcode,
+  RefusedQuery,
+  EmptyNoError
+};
 
-  g_log<<Logger::Debug<<logPrefix<<"Had "<<mdp.d_qname<<"|"<<QType(mdp.d_qtype).toString()<<" query from "<<saddr.toStringWithPort()<<endl;
+static ResponseType maybeHandleNotify(const MOADNSParser& mdp, const ComboAddress& saddr, const string& logPrefix="") {
+  if (mdp.d_header.opcode != Opcode::Notify) { // NOLINT(bugprone-narrowing-conversions, cppcoreguidelines-narrowing-conversions) opcode is 4 bits, this is not a dangerous conversion
+    return ResponseType::Unknown;
+  }
+
+  g_log<<Logger::Info<<logPrefix<<"NOTIFY for "<<mdp.d_qname<<"|"<<QType(mdp.d_qtype).toString()<<" "<< Opcode::to_s(mdp.d_header.opcode) <<" from "<<saddr.toStringWithPort()<<endl;
+
+  auto found = g_domainConfigs.find(mdp.d_qname);
+  if (found == g_domainConfigs.end()) {
+    g_log<<Logger::Info<<("Domain name '" + mdp.d_qname.toLogString() + "' is not configured for notification")<<endl;
+    return ResponseType::RefusedQuery;
+  }
+
+  auto primaries = found->second.primaries;
+
+  bool primaryFound = false;
 
-  if (udp && mdp.d_qtype != QType::SOA && mdp.d_qtype != QType::IXFR) {
-    info_msg.push_back("QType is unsupported (" + QType(mdp.d_qtype).toString() + " is not in {SOA,IXFR})");
+  for (const auto& primary : primaries) {
+    if (ComboAddress::addressOnlyEqual()(saddr, primary)) {
+      primaryFound = true;
+      break;
+    }
   }
 
-  if (!udp && mdp.d_qtype != QType::SOA && mdp.d_qtype != QType::IXFR && mdp.d_qtype != QType::AXFR) {
-    info_msg.push_back("QType is unsupported (" + QType(mdp.d_qtype).toString() + " is not in {SOA,IXFR,AXFR})");
+  if (primaryFound) {
+    g_notifiesReceived.lock()->insert(mdp.d_qname);
+    return ResponseType::EmptyNoError;
   }
 
-  {
-    if (g_domainConfigs.find(mdp.d_qname) == g_domainConfigs.end()) {
-      info_msg.push_back("Domain name '" + mdp.d_qname.toLogString() + "' is not configured for distribution");
+  return ResponseType::RefusedQuery;
+}
+
+static ResponseType checkQuery(const MOADNSParser& mdp, const ComboAddress& saddr, const bool udp = true, const string& logPrefix="") {
+  vector<string> info_msg;
+
+  auto ret = ResponseType::ValidQuery;
+
+  g_log<<Logger::Debug<<logPrefix<<"Had "<<mdp.d_qname<<"|"<<QType(mdp.d_qtype).toString()<<" query from "<<saddr.toStringWithPort()<<endl;
+
+  if (mdp.d_header.opcode != Opcode::Query) { // NOLINT(bugprone-narrowing-conversions, cppcoreguidelines-narrowing-conversions) opcode is 4 bits, this is not a dangerous conversion
+    info_msg.push_back("Opcode is unsupported (" + Opcode::to_s(mdp.d_header.opcode) + "), expected QUERY"); // note that we also emit this for a NOTIFY from a wrong source
+    ret = ResponseType::RefusedOpcode;
+  }
+  else {
+    if (udp && mdp.d_qtype != QType::SOA && mdp.d_qtype != QType::IXFR) {
+      info_msg.push_back("QType is unsupported (" + QType(mdp.d_qtype).toString() + " is not in {SOA,IXFR})");
+      ret = ResponseType::RefusedQuery;
     }
-    else {
-      const auto zoneInfo = getCurrentZoneInfo(mdp.d_qname);
-      if (zoneInfo == nullptr) {
-        info_msg.push_back("Domain has not been transferred yet");
+
+    if (!udp && mdp.d_qtype != QType::SOA && mdp.d_qtype != QType::IXFR && mdp.d_qtype != QType::AXFR) {
+      info_msg.push_back("QType is unsupported (" + QType(mdp.d_qtype).toString() + " is not in {SOA,IXFR,AXFR})");
+      ret = ResponseType::RefusedQuery;
+    }
+
+    {
+      if (g_domainConfigs.find(mdp.d_qname) == g_domainConfigs.end()) {
+        info_msg.push_back("Domain name '" + mdp.d_qname.toLogString() + "' is not configured for distribution");
+        ret = ResponseType::RefusedQuery;
+      }
+      else {
+        const auto zoneInfo = getCurrentZoneInfo(mdp.d_qname);
+        if (zoneInfo == nullptr) {
+          info_msg.emplace_back("Domain has not been transferred yet");
+          ret = ResponseType::RefusedQuery;
+        }
       }
     }
   }
 
-  if (!info_msg.empty()) {
-    g_log<<Logger::Warning<<logPrefix<<"Refusing "<<mdp.d_qname<<"|"<<QType(mdp.d_qtype).toString()<<" query from "<<saddr.toStringWithPort();
+  if (!info_msg.empty()) {  // which means ret is not SOA
+    g_log<<Logger::Warning<<logPrefix<<"Refusing "<<mdp.d_qname<<"|"<<QType(mdp.d_qtype).toString()<<" "<< Opcode::to_s(mdp.d_header.opcode) <<" from "<<saddr.toStringWithPort();
     g_log<<Logger::Warning<<": ";
     bool first = true;
     for (const auto& s : info_msg) {
@@ -511,9 +580,26 @@ static bool checkQuery(const MOADNSParser& mdp, const ComboAddress& saddr, const
       g_log<<Logger::Warning<<s;
     }
     g_log<<Logger::Warning<<endl;
-    return false;
+    // fall through to return below
   }
 
+  return ret;
+}
+
+/*
+ * Returns a vector<uint8_t> that represents the full empty NOERROR response.
+ * QNAME is read from mdp.
+ */
+static bool makeEmptyNoErrorPacket(const MOADNSParser& mdp, vector<uint8_t>& packet) {
+  DNSPacketWriter pw(packet, mdp.d_qname, mdp.d_qtype);
+  pw.getHeader()->opcode = mdp.d_header.opcode;
+  pw.getHeader()->id = mdp.d_header.id;
+  pw.getHeader()->rd = mdp.d_header.rd;
+  pw.getHeader()->qr = 1;
+  pw.getHeader()->aa = 1;
+
+  pw.commit();
+
   return true;
 }
 
@@ -529,6 +615,7 @@ static bool makeSOAPacket(const MOADNSParser& mdp, vector<uint8_t>& packet) {
   }
 
   DNSPacketWriter pw(packet, mdp.d_qname, mdp.d_qtype);
+  pw.getHeader()->opcode = mdp.d_header.opcode;
   pw.getHeader()->id = mdp.d_header.id;
   pw.getHeader()->rd = mdp.d_header.rd;
   pw.getHeader()->qr = 1;
@@ -547,6 +634,7 @@ static bool makeSOAPacket(const MOADNSParser& mdp, vector<uint8_t>& packet) {
  */
 static bool makeRefusedPacket(const MOADNSParser& mdp, vector<uint8_t>& packet) {
   DNSPacketWriter pw(packet, mdp.d_qname, mdp.d_qtype);
+  pw.getHeader()->opcode = mdp.d_header.opcode;
   pw.getHeader()->id = mdp.d_header.id;
   pw.getHeader()->rd = mdp.d_header.rd;
   pw.getHeader()->qr = 1;
@@ -555,6 +643,21 @@ static bool makeRefusedPacket(const MOADNSParser& mdp, vector<uint8_t>& packet)
   return true;
 }
 
+/*
+ * Returns a vector<uint8_t> that represents the full NOTIMP response to a
+ * query. QNAME and type are read from mdp.
+ */
+static bool makeNotimpPacket(const MOADNSParser& mdp, vector<uint8_t>& packet) {
+  DNSPacketWriter pw(packet, mdp.d_qname, mdp.d_qtype);
+  pw.getHeader()->opcode = mdp.d_header.opcode;
+  pw.getHeader()->id = mdp.d_header.id;
+  pw.getHeader()->rd = mdp.d_header.rd;
+  pw.getHeader()->qr = 1;
+  pw.getHeader()->rcode = RCode::NotImp;
+
+  return true;
+}
+
 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);
@@ -779,11 +882,17 @@ static bool handleIXFR(int fd, const MOADNSParser& mdp, const shared_ptr<const S
   return true;
 }
 
-static bool allowedByACL(const ComboAddress& addr) {
+static bool allowedByACL(const ComboAddress& addr, bool forNotify = false) {
+  if (forNotify) {
+    return g_notifySources.match(addr);
+  }
+
   return g_acl.match(addr);
 }
 
-static void handleUDPRequest(int fd, boost::any&) {
+static void handleUDPRequest(int fd, boost::any& /*unused*/)
+try
+{
   // TODO make the buffer-size configurable
   char buf[4096];
   ComboAddress saddr;
@@ -806,14 +915,29 @@ static void handleUDPRequest(int fd, boost::any&) {
     return;
   }
 
-  if (!allowedByACL(saddr)) {
-    g_log<<Logger::Warning<<"UDP query from "<<saddr.toString()<<" is not allowed, dropping"<<endl;
+  if (!allowedByACL(saddr, true) && !allowedByACL(saddr, false)) {
+    g_log<<Logger::Warning<<"UDP query from "<<saddr.toString()<<" did not match any valid query or NOTIFY source, dropping"<<endl;
     return;
   }
 
-  MOADNSParser mdp(true, string(buf, res));
+  MOADNSParser mdp(true, string(&buf[0], static_cast<size_t>(res)));
   vector<uint8_t> packet;
-  if (checkQuery(mdp, saddr)) {
+
+  ResponseType respt = ResponseType::Unknown;
+
+  if (allowedByACL(saddr, true)) {
+    respt = maybeHandleNotify(mdp, saddr);
+  }
+  else if (!allowedByACL(saddr)) {
+    g_log<<Logger::Warning<<"UDP query from "<<saddr.toString()<<" is not allowed, dropping"<<endl;
+    return;
+  }
+
+  if (respt == ResponseType::Unknown) {
+    // query was not handled yet (so not a valid NOTIFY)
+    respt = checkQuery(mdp, saddr);
+  }
+  if (respt == ResponseType::ValidQuery) {
     /* RFC 1995 Section 2
      *    Transport of a query may be by either UDP or TCP.  If an IXFR query
      *    is via UDP, the IXFR server may attempt to reply using UDP if the
@@ -827,9 +951,14 @@ static void handleUDPRequest(int fd, boost::any&) {
      */
     g_stats.incrementSOAinQueries(mdp.d_qname); // FIXME: this also counts IXFR queries (but the response is the same as to a SOA query)
     makeSOAPacket(mdp, packet);
-  } else {
+  } else if (respt == ResponseType::EmptyNoError) {
+    makeEmptyNoErrorPacket(mdp, packet);
+  } else if (respt == ResponseType::RefusedQuery) {
     g_stats.incrementUnknownDomainInQueries(mdp.d_qname);
     makeRefusedPacket(mdp, packet);
+  } else if (respt == ResponseType::RefusedOpcode) {
+    g_stats.incrementNotImplemented(mdp.d_header.opcode);
+    makeNotimpPacket(mdp, packet);
   }
 
   if(sendto(fd, &packet[0], packet.size(), 0, (struct sockaddr*) &saddr, fromlen) < 0) {
@@ -838,6 +967,10 @@ static void handleUDPRequest(int fd, boost::any&) {
   }
   return;
 }
+catch(std::exception& e) {
+  return;
+}
+
 
 static void handleTCPRequest(int fd, boost::any&) {
   ComboAddress saddr;
@@ -857,7 +990,9 @@ static void handleTCPRequest(int fd, boost::any&) {
     return;
   }
 
-  if (!allowedByACL(saddr)) {
+  // we allow the connection if this is a legit client or a legit NOTIFY source
+  // need to check per-operation later
+  if (!allowedByACL(saddr) && !allowedByACL(saddr, true)) {
     g_log<<Logger::Warning<<"TCP query from "<<saddr.toString()<<" is not allowed, dropping"<<endl;
     close(cfd);
     return;
@@ -909,13 +1044,37 @@ static void tcpWorker(int tid) {
     try {
       MOADNSParser mdp(true, string(buf, res));
 
-      if (!checkQuery(mdp, saddr, false, prefix)) {
+      ResponseType respt = ResponseType::Unknown;
+
+      // this code is duplicated from the UDP path
+      if (allowedByACL(saddr, true)) {
+        respt = maybeHandleNotify(mdp, saddr);
+      }
+      else if (!allowedByACL(saddr)) {
+        close(cfd);
+        continue;
+      }
+
+      if (respt == ResponseType::Unknown) {
+        respt = checkQuery(mdp, saddr, false, prefix);
+      }
+
+      if (respt != ResponseType::ValidQuery && respt != ResponseType::EmptyNoError) { // on TCP, we currently do not bother with sending useful errors
         close(cfd);
         continue;
       }
 
-      if (mdp.d_qtype == QType::SOA) {
-        vector<uint8_t> packet;
+      vector<uint8_t> packet;
+
+      if (respt == ResponseType::EmptyNoError) {
+        bool ret = makeEmptyNoErrorPacket(mdp, packet);
+        if (!ret) {
+          close(cfd);
+          continue;
+        }
+        sendPacketOverTCP(cfd, packet);
+      }
+      else if (mdp.d_qtype == QType::SOA) {
         bool ret = makeSOAPacket(mdp, packet);
         if (!ret) {
           close(cfd);
@@ -1112,13 +1271,17 @@ static bool parseAndCheckConfig(const string& configpath, YAML::Node& config) {
       }
       try {
         if (!domain["master"]) {
-          g_log<<Logger::Error<<"Domain '"<<domain["domain"].as<string>()<<"' has no master configured!"<<endl;
+          g_log << Logger::Error << "Domain '" << domain["domain"].as<string>() << "' has no primary configured!" << endl;
           retval = false;
           continue;
         }
         domain["master"].as<ComboAddress>();
+
+        auto notifySource = domain["master"].as<ComboAddress>();
+
+        g_notifySources.addMask(notifySource);
       } catch (const runtime_error &e) {
-        g_log<<Logger::Error<<"Unable to read domain '"<<domain["domain"].as<string>()<<"' master address: "<<e.what()<<endl;
+        g_log << Logger::Error << "Unable to read domain '" << domain["domain"].as<string>() << "' primary address: " << e.what() << endl;
         retval = false;
       }
       if (domain["max-soa-refresh"]) {
@@ -1266,7 +1429,7 @@ static std::optional<IXFRDistConfiguration> parseConfiguration(int argc, char**
     for (auto const &domain : config["domains"]) {
       set<ComboAddress> s;
       s.insert(domain["master"].as<ComboAddress>());
-      g_domainConfigs[domain["domain"].as<DNSName>()].masters = s;
+      g_domainConfigs[domain["domain"].as<DNSName>()].primaries = s;
       if (domain["max-soa-refresh"].IsDefined()) {
         g_domainConfigs[domain["domain"].as<DNSName>()].maxSOARefresh = domain["max-soa-refresh"].as<uint32_t>();
       }
@@ -1294,6 +1457,8 @@ static std::optional<IXFRDistConfiguration> parseConfiguration(int argc, char**
       g_log<<Logger::Error<<"Error printing ACL: "<<exp.what()<<endl;
     }
 
+    g_log<<Logger::Notice<<"NOTIFY accepted from "<<g_notifySources.toString()<<"."<<endl;
+
     if (config["compress"].IsDefined()) {
       g_compress = config["compress"].as<bool>();
       if (g_compress) {
index 4715e1dcd32769315a2502ac1cab1b866f051407..cff51b52eb3ad841f06a77f3c215a6218736a33a 100644 (file)
 #include <cinttypes>
 #include <dirent.h>
 #include <cerrno>
+#include <sys/stat.h>
+
 #include "ixfrutils.hh"
 #include "sstuff.hh"
 #include "dnssecinfra.hh"
 #include "zoneparser-tng.hh"
 #include "dnsparser.hh"
 
-uint32_t getSerialFromMaster(const ComboAddress& master, const DNSName& zone, shared_ptr<const SOARecordContent>& sr, const TSIGTriplet& tt, const uint16_t timeout)
+uint32_t getSerialFromPrimary(const ComboAddress& primary, 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);
@@ -43,8 +45,8 @@ uint32_t getSerialFromMaster(const ComboAddress& master, const DNSName& zone, sh
     addTSIG(pw, trc, tt.name, tt.secret, "", false);
   }
 
-  Socket s(master.sin4.sin_family, SOCK_DGRAM);
-  s.connect(master);
+  Socket s(primary.sin4.sin_family, SOCK_DGRAM);
+  s.connect(primary);
   string msg((const char*)&packet[0], packet.size());
   s.writen(msg);
 
@@ -75,18 +77,23 @@ uint32_t getSerialFromMaster(const ComboAddress& master, const DNSName& zone, sh
 
 uint32_t getSerialFromDir(const std::string& dir)
 {
-  uint32_t ret=0;
-  DIR* dirhdl=opendir(dir.c_str());
-  if(!dirhdl)
+  uint32_t ret = 0;
+  auto dirhdl = std::unique_ptr<DIR, decltype(&closedir)>(opendir(dir.c_str()), closedir);
+  if (!dirhdl) {
     throw runtime_error("Could not open IXFR directory '" + dir + "': " + stringerror());
-  struct dirent *entry;
+  }
 
-  while((entry = readdir(dirhdl))) {
+  struct dirent* entry = nullptr;
+  // NOLINTNEXTLINE(concurrency-mt-unsafe): readdir is thread-safe nowadays and readdir_r is deprecated
+  while ((entry = readdir(dirhdl.get())) != nullptr) {
     uint32_t num = atoi(entry->d_name);
-    if(std::to_string(num) == entry->d_name)
+    // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay): this is what dirent is
+    auto name = std::string_view(entry->d_name, strlen(entry->d_name));
+    if (std::to_string(num) == name) {
       ret = max(num, ret);
+    }
   }
-  closedir(dirhdl);
+
   return ret;
 }
 
@@ -123,32 +130,35 @@ void writeZoneToDisk(const records_t& records, const DNSName& zone, const std::s
 {
   DNSRecord soa;
   auto serial = getSerialFromRecords(records, soa);
-  string fname=directory +"/"+std::to_string(serial);
-  auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(fopen((fname+".partial").c_str(), "w"), fclose);
-  if (!fp) {
+  string fname = directory + "/" + std::to_string(serial);
+  /* ensure that the partial zone file will only be accessible by the current user, not even
+     by other users in the same group, and certainly not by other users. */
+  umask(S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+  auto filePtr = std::unique_ptr<FILE, int(*)(FILE*)>(fopen((fname+".partial").c_str(), "w"), fclose);
+  if (!filePtr) {
     throw runtime_error("Unable to open file '"+fname+".partial' for writing: "+stringerror());
   }
 
   records_t soarecord;
   soarecord.insert(soa);
-  if (fprintf(fp.get(), "$ORIGIN %s\n", zone.toString().c_str()) < 0) {
+  if (fprintf(filePtr.get(), "$ORIGIN %s\n", zone.toString().c_str()) < 0) {
     string error = "Error writing to zone file for " + zone.toLogString() + " in file " + fname + ".partial" + ": " + stringerror();
-    fp.reset();
+    filePtr.reset();
     unlink((fname+".partial").c_str());
     throw std::runtime_error(error);
   }
 
   try {
-    writeRecords(fp.get(), soarecord);
-    writeRecords(fp.get(), records);
-    writeRecords(fp.get(), soarecord);
+    writeRecords(filePtr.get(), soarecord);
+    writeRecords(filePtr.get(), records);
+    writeRecords(filePtr.get(), soarecord);
   } catch (runtime_error &e) {
-    fp.reset();
+    filePtr.reset();
     unlink((fname+".partial").c_str());
     throw runtime_error("Error closing zone file for " + zone.toLogString() + " in file " + fname + ".partial" + ": " + e.what());
   }
 
-  if (fclose(fp.release()) != 0) {
+  if (fclose(filePtr.release()) != 0) {
     string error = "Error closing zone file for " + zone.toLogString() + " in file " + fname + ".partial" + ": " + stringerror();
     unlink((fname+".partial").c_str());
     throw std::runtime_error(error);
index 7e31efb52dac7d29e02d306005905457173ecccd..10285029c0d3383a0dd1726625cc1c01bd5d58c3 100644 (file)
@@ -56,7 +56,7 @@ typedef multi_index_container <
     > /* indexed_by */
 > /* multi_index_container */ records_t;
 
-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 getSerialFromPrimary(const ComboAddress& primary, 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);
index 620402ab0e568a7c78f90c426990f12690af7ccd..a8e0c3cba1b321eddbd933de840128c6178711ec 100644 (file)
@@ -101,7 +101,7 @@ int main(int argc, char** argv) {
 
     /* goal in life:
        in directory/zone-name we leave files with their name the serial number
-       at startup, retrieve current SOA SERIAL for domain from master server
+       at startup, retrieve current SOA SERIAL for domain from primary server
 
        compare with what the best is we have in our directory, IXFR from that.
        Store result in memory, read that best zone in memory, apply deltas, write it out.
@@ -109,7 +109,7 @@ int main(int argc, char** argv) {
        Next up, loop this every REFRESH seconds */
 
     DNSName zone(argv[4]);
-    ComboAddress master(argv[2], atoi(argv[3]));
+    ComboAddress primary(argv[2], atoi(argv[3]));
     string directory(argv[5]);
     records_t records;
 
@@ -141,9 +141,9 @@ int main(int argc, char** argv) {
     }
     catch(std::exception& e) {
       cout<<"Could not load zone from disk: "<<e.what()<<endl;
-      cout<<"Retrieving latest from master "<<master.toStringWithPort()<<endl;
-      ComboAddress local = master.sin4.sin_family == AF_INET ? ComboAddress("0.0.0.0") : ComboAddress("::");
-      AXFRRetriever axfr(master, zone, tt, &local);
+      cout << "Retrieving latest from primary " << primary.toStringWithPort() << endl;
+      ComboAddress local = primary.sin4.sin_family == AF_INET ? ComboAddress("0.0.0.0") : ComboAddress("::");
+      AXFRRetriever axfr(primary, zone, tt, &local);
       unsigned int nrecords=0;
       Resolver::res_t nop;
       vector<DNSRecord> chunk;
@@ -178,7 +178,7 @@ int main(int argc, char** argv) {
       cout<<"Checking for update, our serial number is "<<ourSerial<<".. ";
       cout.flush();
       shared_ptr<const SOARecordContent> sr;
-      uint32_t serial = getSerialFromMaster(master, zone, sr, tt);
+      uint32_t serial = getSerialFromPrimary(primary, zone, sr, tt);
       if(ourSerial == serial) {
         unsigned int sleepTime = sr ? sr->d_st.refresh : 60;
         cout<<"still up to date, their serial is "<<serial<<", sleeping "<<sleepTime<<" seconds"<<endl;
@@ -187,7 +187,7 @@ int main(int argc, char** argv) {
       }
 
       cout<<"got new serial: "<<serial<<", initiating IXFR!"<<endl;
-      auto deltas = getIXFRDeltas(master, zone, ourSoa, 20, false, tt);
+      auto deltas = getIXFRDeltas(primary, zone, ourSoa, 20, false, tt);
       cout<<"Got "<<deltas.size()<<" deltas, applying.."<<endl;
 
       for(const auto& delta : deltas) {
index 7be8348261958b6d3afb0fe0817d8c7cd87857b8..a77d665157b1b366f6a6166d4e207c748311cd4d 100644 (file)
@@ -32,6 +32,8 @@
 #include <openssl/core.h>
 #include <openssl/core_names.h>
 #include <openssl/evp.h>
+#else
+#include <openssl/hmac.h>
 #endif
 
 #ifdef HAVE_LIBSODIUM
@@ -200,7 +202,7 @@ std::pair<bool, std::string> libssl_load_provider(const std::string& providerNam
 #endif /* HAVE_LIBSSL && OPENSSL_VERSION_MAJOR >= 3 && HAVE_TLS_PROVIDERS */
 
 #if defined(HAVE_LIBSSL) && !defined(HAVE_TLS_PROVIDERS)
-std::pair<bool, std::string> libssl_load_engine(const std::string& engineName, const std::optional<std::string>& defaultString)
+std::pair<bool, std::string> libssl_load_engine([[maybe_unused]] const std::string& engineName, [[maybe_unused]] const std::optional<std::string>& defaultString)
 {
 #ifdef OPENSSL_NO_ENGINE
   return { false, "OpenSSL has been built without engine support" };
@@ -288,12 +290,9 @@ int libssl_ticket_key_callback(SSL* /* s */, OpenSSLTLSTicketKeysRing& keyring,
   return 1;
 }
 
-static long libssl_server_name_callback(SSL* ssl, int* al, void* arg)
+static int libssl_server_name_callback(SSL* ssl, int* /* alert */, void* /* arg */)
 {
-  (void) al;
-  (void) arg;
-
-  if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name)) {
+  if (SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name) != nullptr) {
     return SSL_TLSEXT_ERR_OK;
   }
 
index 637e97d67ee6ba590bf60c8b6698c431e290ac58..c08a8e6b4ebb28a098cf831faecd7d8f8ec4065f 100644 (file)
@@ -69,7 +69,7 @@ struct is_to_string_available<T, std::void_t<decltype(std::to_string(std::declva
 {
 };
 
-// Same mechanism for t.toLogString()
+// Same mechanism for t.toLogString() and t.toStructuredLogString()
 template <typename T, typename = void>
 struct is_toLogString_available : std::false_type
 {
@@ -80,6 +80,16 @@ struct is_toLogString_available<T, std::void_t<decltype(std::declval<T>().toLogS
 {
 };
 
+template <typename T, typename = void>
+struct is_toStructuredLogString_available : std::false_type
+{
+};
+
+template <typename T>
+struct is_toStructuredLogString_available<T, std::void_t<decltype(std::declval<T>().toStructuredLogString())>> : std::true_type
+{
+};
+
 template <typename T, typename = void>
 struct is_toString_available : std::false_type
 {
@@ -103,6 +113,9 @@ struct Loggable : public Logr::Loggable
     if constexpr (std::is_same_v<T, std::string>) {
       return _t;
     }
+    else if constexpr (is_toStructuredLogString_available<T>::value) {
+      return _t.toStructuredLogString();
+    }
     else if constexpr (is_toLogString_available<T>::value) {
       return _t.toLogString();
     }
@@ -202,19 +215,21 @@ extern bool g_slogStructured;
 // SLOG(g_log<<Logger::Warning<<"Unable to parse configuration file '"<<configname<<"'"<<endl,
 //      startupLog->error("No such file", "Unable to parse configuration file", "config_file", Logging::Loggable(configname));
 //
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
 #define SLOG(oldStyle, slogCall) \
-  if (true) {                    \
+  do {                           \
     if (g_slogStructured) {      \
       slogCall;                  \
     }                            \
     else {                       \
       oldStyle;                  \
     }                            \
-  }
+  } while (0)
 
 #else // No structured logging (e.g. auth)
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
 #define SLOG(oldStyle, slogCall) \
   do {                           \
     oldStyle;                    \
-  } while (0);
+  } while (0)
 #endif // RECURSOR
index 2eae10d9495e1dabdc5d454b4909fec106d74d87..b150be8328689f3c946a0e0a705d9f56c016be4d 100644 (file)
@@ -217,7 +217,7 @@ 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.setContent(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::make(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);
@@ -232,7 +232,7 @@ void BaseLua4::prepareContext() {
         ret=aaaarec->getCA(53);
       return ret;
     });
-  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))); });
+  d_lw->registerFunction<void (DNSRecord::*)(const std::string&)>("changeContent", [](DNSRecord& dr, const std::string& newContent) { dr.setContent(shared_ptr<DNSRecordContent>(DNSRecordContent::make(dr.d_type, 1, newContent))); });
 
   // pdnsload
   d_lw->writeFunction("pdnslog", [](const std::string& msg, boost::optional<int> loglevel) {
index e3c7f52c0b2f59c388abc1969ffc19603e8de003..c3358044abb9689797cdc9f75061f70cacc900cb 100644 (file)
@@ -1178,9 +1178,9 @@ std::vector<shared_ptr<DNSRecordContent>> luaSynth(const std::string& code, cons
 
     for(const auto& content_it: contents) {
       if(qtype==QType::TXT)
-        ret.push_back(DNSRecordContent::mastermake(qtype, QClass::IN, '"'+content_it+'"' ));
+        ret.push_back(DNSRecordContent::make(qtype, QClass::IN, '"' + content_it + '"'));
       else
-        ret.push_back(DNSRecordContent::mastermake(qtype, QClass::IN, content_it ));
+        ret.push_back(DNSRecordContent::make(qtype, QClass::IN, content_it));
     }
   } catch(std::exception &e) {
     g_log << Logger::Info << "Lua record ("<<query<<"|"<<QType(qtype).toString()<<") reported: " << e.what();
index 4bbc865f6bed5f0d16d1bab96412442b2c4f1d1b..bb5464f286be964696a41fbc0cb09ca103af514c 100644 (file)
@@ -1377,23 +1377,27 @@ DNSName getTSIGAlgoName(TSIGHashEnum& algoEnum)
 uint64_t getOpenFileDescriptors(const std::string&)
 {
 #ifdef __linux__
-  DIR* dirhdl=opendir(("/proc/"+std::to_string(getpid())+"/fd/").c_str());
-  if(!dirhdl)
+  auto dirHandle = std::unique_ptr<DIR, decltype(&closedir)>(opendir(("/proc/"+std::to_string(getpid())+"/fd/").c_str()), closedir);
+  if (!dirHandle) {
     return 0;
+  }
 
-  struct dirent *entry;
-  int ret=0;
-  while((entry = readdir(dirhdl))) {
+  int ret = 0;
+  struct dirent* entry = nullptr;
+  // NOLINTNEXTLINE(concurrency-mt-unsafe): readdir is thread-safe nowadays and readdir_r is deprecated
+  while ((entry = readdir(dirHandle.get())) != nullptr) {
     uint32_t num;
     try {
+      // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay): this is what dirent is
       pdns::checked_stoi_into(num, entry->d_name);
     } catch (...) {
       continue; // was not a number.
     }
-    if(std::to_string(num) == entry->d_name)
+    // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay): this is what dirent is
+    if (std::to_string(num) == entry->d_name) {
       ret++;
+    }
   }
-  closedir(dirhdl);
   return ret;
 
 #elif defined(__OpenBSD__)
index d83b8393d1f66bdfb92504f52c41f931f5d5fd98..ff1f5bcb969e38c675c7ae94a94a618c8c6679c7 100644 (file)
@@ -295,7 +295,7 @@ int PacketHandler::doChaosRequest(const DNSPacket& p, std::unique_ptr<DNSPacket>
       }
       else
         content=mode;
-      rr.dr.setContent(DNSRecordContent::mastermake(QType::TXT, 1, "\""+content+"\""));
+      rr.dr.setContent(DNSRecordContent::make(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.setContent(DNSRecordContent::mastermake(QType::TXT, 1, tid));
+      rr.dr.setContent(DNSRecordContent::make(QType::TXT, 1, tid));
     }
     else {
       r->setRcode(RCode::Refused);
@@ -975,23 +975,23 @@ How MySQLBackend would implement this:
 
 */
 
-int PacketHandler::trySuperMaster(const DNSPacket& p, const DNSName& tsigkeyname)
+int PacketHandler::tryAutoPrimary(const DNSPacket& p, const DNSName& tsigkeyname)
 {
   if(p.d_tcp)
   {
     // do it right now if the client is TCP
     // rarely happens
-    return trySuperMasterSynchronous(p, tsigkeyname);
+    return tryAutoPrimarySynchronous(p, tsigkeyname);
   }
   else
   {
     // queue it if the client is on UDP
-    Communicator.addTrySuperMasterRequest(p);
+    Communicator.addTryAutoPrimaryRequest(p);
     return 0;
   }
 }
 
-int PacketHandler::trySuperMasterSynchronous(const DNSPacket& p, const DNSName& tsigkeyname)
+int PacketHandler::tryAutoPrimarySynchronous(const DNSPacket& p, const DNSName& tsigkeyname)
 {
   ComboAddress remote = p.getInnerRemote();
   if(p.hasEDNSSubnet() && pdns::isAddressTrustedNotificationProxy(remote)) {
@@ -1022,7 +1022,7 @@ int PacketHandler::trySuperMasterSynchronous(const DNSPacket& p, const DNSName&
   }
 
   if(!haveNS) {
-    g_log<<Logger::Error<<"While checking for supermaster, did not find NS for "<<p.qdomain<<" at: "<< remote <<endl;
+    g_log << Logger::Error << "While checking for autoprimary, did not find NS for " << p.qdomain << " at: " << remote << endl;
     return RCode::ServFail;
   }
 
@@ -1030,12 +1030,12 @@ int PacketHandler::trySuperMasterSynchronous(const DNSPacket& p, const DNSName&
   DNSBackend *db;
 
   if (!::arg().mustDo("allow-unsigned-autoprimary") && tsigkeyname.empty()) {
-    g_log<<Logger::Error<<"Received unsigned NOTIFY for "<<p.qdomain<<" from potential supermaster "<<remote<<". Refusing."<<endl;
+    g_log << Logger::Error << "Received unsigned NOTIFY for " << p.qdomain << " from potential autoprimary " << remote << ". Refusing." << endl;
     return RCode::Refused;
   }
 
-  if(!B.superMasterBackend(remote.toString(), p.qdomain, nsset, &nameserver, &account, &db)) {
-    g_log<<Logger::Error<<"Unable to find backend willing to host "<<p.qdomain<<" for potential supermaster "<<remote<<". Remote nameservers: "<<endl;
+  if (!B.autoPrimaryBackend(remote.toString(), p.qdomain, nsset, &nameserver, &account, &db)) {
+    g_log << Logger::Error << "Unable to find backend willing to host " << p.qdomain << " for potential autoprimary " << remote << ". Remote nameservers: " << endl;
     for(const auto& rr: nsset) {
       if(rr.qtype==QType::NS)
         g_log<<Logger::Error<<rr.content<<endl;
@@ -1043,10 +1043,10 @@ int PacketHandler::trySuperMasterSynchronous(const DNSPacket& p, const DNSName&
     return RCode::Refused;
   }
   try {
-    db->createSlaveDomain(remote.toString(), p.qdomain, nameserver, account);
+    db->createSecondaryDomain(remote.toString(), p.qdomain, nameserver, account);
     DomainInfo di;
     if (!db->getDomainInfo(p.qdomain, di, false)) {
-      g_log << Logger::Error << "Failed to create " << p.qdomain << " for potential supermaster " << remote << endl;
+      g_log << Logger::Error << "Failed to create " << p.qdomain << " for potential autoprimary " << remote << endl;
       return RCode::ServFail;
     }
     g_zoneCache.add(p.qdomain, di.id);
@@ -1057,10 +1057,10 @@ int PacketHandler::trySuperMasterSynchronous(const DNSPacket& p, const DNSName&
     }
   }
   catch(PDNSException& ae) {
-    g_log<<Logger::Error<<"Database error trying to create "<<p.qdomain<<" for potential supermaster "<<remote<<": "<<ae.reason<<endl;
+    g_log << Logger::Error << "Database error trying to create " << p.qdomain << " for potential autoprimary " << remote << ": " << ae.reason << endl;
     return RCode::ServFail;
   }
-  g_log<<Logger::Warning<<"Created new slave zone '"<<p.qdomain<<"' from supermaster "<<remote<<endl;
+  g_log << Logger::Warning << "Created new secondary zone '" << p.qdomain << "' from autoprimary " << remote << endl;
   return RCode::NoError;
 }
 
@@ -1070,14 +1070,14 @@ int PacketHandler::processNotify(const DNSPacket& p)
      was this notification from an approved address?
      was this notification approved by TSIG?
      We determine our internal SOA id (via UeberBackend)
-     We determine the SOA at our (known) master
-     if master is higher -> do stuff
+     We determine the SOA at our (known) primary
+     if primary is higher -> do stuff
   */
 
   g_log<<Logger::Debug<<"Received NOTIFY for "<<p.qdomain<<" from "<<p.getRemoteString()<<endl;
 
   if(!::arg().mustDo("secondary") && s_forwardNotify.empty()) {
-    g_log<<Logger::Warning<<"Received NOTIFY for "<<p.qdomain<<" from "<<p.getRemoteString()<<" but slave support is disabled in the configuration"<<endl;
+    g_log << Logger::Warning << "Received NOTIFY for " << p.qdomain << " from " << p.getRemoteString() << " but secondary support is disabled in the configuration" << endl;
     return RCode::Refused;
   }
 
@@ -1112,16 +1112,16 @@ int PacketHandler::processNotify(const DNSPacket& p)
   DomainInfo di;
   if(!B.getDomainInfo(p.qdomain, di, false) || !di.backend) {
     if(::arg().mustDo("autosecondary")) {
-      g_log<<Logger::Warning<<"Received NOTIFY for "<<p.qdomain<<" from "<<p.getRemoteString()<<" for which we are not authoritative, trying supermaster"<<endl;
-      return trySuperMaster(p, p.getTSIGKeyname());
+      g_log << Logger::Warning << "Received NOTIFY for " << p.qdomain << " from " << p.getRemoteString() << " for which we are not authoritative, trying autoprimary" << endl;
+      return tryAutoPrimary(p, p.getTSIGKeyname());
     }
     g_log<<Logger::Notice<<"Received NOTIFY for "<<p.qdomain<<" from "<<p.getRemoteString()<<" for which we are not authoritative (Refused)"<<endl;
     return RCode::Refused;
   }
 
   if(pdns::isAddressTrustedNotificationProxy(p.getInnerRemote())) {
-    if(di.masters.empty()) {
-      g_log<<Logger::Warning<<"Received NOTIFY for "<<p.qdomain<<" from trusted-notification-proxy "<<p.getRemoteString()<<", zone does not have any masters defined (Refused)"<<endl;
+    if (di.primaries.empty()) {
+      g_log << Logger::Warning << "Received NOTIFY for " << p.qdomain << " from trusted-notification-proxy " << p.getRemoteString() << ", zone does not have any primaries defined (Refused)" << endl;
       return RCode::Refused;
     }
     g_log<<Logger::Notice<<"Received NOTIFY for "<<p.qdomain<<" from trusted-notification-proxy "<<p.getRemoteString()<<endl;
@@ -1130,8 +1130,8 @@ int PacketHandler::processNotify(const DNSPacket& p)
     g_log << Logger::Warning << "Received NOTIFY for " << p.qdomain << " from " << p.getRemoteString() << " but we are primary (Refused)" << endl;
     return RCode::Refused;
   }
-  else if(!di.isMaster(p.getInnerRemote())) {
-    g_log<<Logger::Warning<<"Received NOTIFY for "<<p.qdomain<<" from "<<p.getRemoteString()<<" which is not a master (Refused)"<<endl;
+  else if (!di.isPrimary(p.getInnerRemote())) {
+    g_log << Logger::Warning << "Received NOTIFY for " << p.qdomain << " from " << p.getRemoteString() << " which is not a primary (Refused)" << endl;
     return RCode::Refused;
   }
 
@@ -1146,7 +1146,7 @@ int PacketHandler::processNotify(const DNSPacket& p)
   if(::arg().mustDo("secondary")) {
     g_log<<Logger::Notice<<"Received NOTIFY for "<<p.qdomain<<" from "<<p.getRemoteString()<<" - queueing check"<<endl;
     di.receivedNotify = true;
-    Communicator.addSlaveCheckRequest(di, p.getInnerRemote());
+    Communicator.addSecondaryCheckRequest(di, p.getInnerRemote());
   }
   return 0;
 }
index be224dcca5e739e75b6deca1f7b3be03ac6db9f5..8af3bde2c9a83b7ba01c30e9d19f241a539a3231 100644 (file)
@@ -60,7 +60,7 @@ public:
  
   UeberBackend *getBackend();
 
-  int trySuperMasterSynchronous(const DNSPacket& p, const DNSName& tsigkeyname);
+  int tryAutoPrimarySynchronous(const DNSPacket& p, const DNSName& tsigkeyname);
   static NetmaskGroup s_allowNotifyFrom;
   static set<string> s_forwardNotify;
   static bool s_SVCAutohints;
@@ -68,7 +68,7 @@ public:
   static const std::shared_ptr<CDSRecordContent> s_deleteCDSContent;
 
 private:
-  int trySuperMaster(const DNSPacket& p, const DNSName& tsigkeyname);
+  int tryAutoPrimary(const DNSPacket& p, const DNSName& tsigkeyname);
   int processNotify(const DNSPacket& );
   void addRootReferral(DNSPacket& r);
   int doChaosRequest(const DNSPacket& p, std::unique_ptr<DNSPacket>& r, DNSName &target) const;
index 4b7687da1ff4efd96222cdf29ddac7d73a4f22b3..a3d6d148a4f0a5fbcaec27eed215fc0b564f8693 100644 (file)
@@ -1,4 +1,5 @@
 
+#include <boost/smart_ptr/make_shared_array.hpp>
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
@@ -260,7 +261,7 @@ static int checkZone(DNSSECKeeper &dk, UeberBackend &B, const DNSName& zone, con
       return 1;
     }
   } catch(const PDNSException &e) {
-    if (di.kind == DomainInfo::Slave) {
+    if (di.kind == DomainInfo::Secondary) {
       cout << "[Error] non-IP address for primaries: " << e.reason << endl;
       numerrors++;
     }
@@ -409,7 +410,7 @@ static int checkZone(DNSSECKeeper &dk, UeberBackend &B, const DNSName& zone, con
       rr.content = "\""+rr.content+"\"";
 
     try {
-      shared_ptr<DNSRecordContent> drc(DNSRecordContent::mastermake(rr.qtype.getCode(), QClass::IN, rr.content));
+      shared_ptr<DNSRecordContent> drc(DNSRecordContent::make(rr.qtype.getCode(), QClass::IN, rr.content));
       string tmp=drc->serialize(rr.qname);
       tmp = drc->getZoneRepresentation(true);
       if (rr.qtype.getCode() != QType::AAAA) {
@@ -445,7 +446,7 @@ static int checkZone(DNSSECKeeper &dk, UeberBackend &B, const DNSName& zone, con
     }
 
     if (rr.qtype.getCode() == QType::SVCB || rr.qtype.getCode() == QType::HTTPS) {
-      shared_ptr<DNSRecordContent> drc(DNSRecordContent::mastermake(rr.qtype.getCode(), QClass::IN, rr.content));
+      shared_ptr<DNSRecordContent> drc(DNSRecordContent::make(rr.qtype.getCode(), QClass::IN, rr.content));
       // I, too, like to live dangerously
       auto svcbrc = std::dynamic_pointer_cast<SVCBBaseRecordContent>(drc);
       if (svcbrc->getPriority() == 0 && svcbrc->hasParams()) {
@@ -775,7 +776,7 @@ static int checkZone(DNSSECKeeper &dk, UeberBackend &B, const DNSName& zone, con
 
   for (auto const &rr : checkCNAME) {
     DNSName target;
-    shared_ptr<DNSRecordContent> drc(DNSRecordContent::mastermake(rr.qtype.getCode(), QClass::IN, rr.content));
+    shared_ptr<DNSRecordContent> drc(DNSRecordContent::make(rr.qtype.getCode(), QClass::IN, rr.content));
     switch (rr.qtype) {
       case QType::MX:
         target = std::dynamic_pointer_cast<MXRecordContent>(drc)->d_mxname;
@@ -1469,7 +1470,7 @@ static int loadZone(const DNSName& zone, const string& fname) {
         haveSOA = true;
     }
     try {
-      DNSRecordContent::mastermake(rr.qtype, QClass::IN, rr.content);
+      DNSRecordContent::make(rr.qtype, QClass::IN, rr.content);
     }
     catch (const PDNSException &pe) {
       cerr<<"Bad record content in record for "<<rr.qname<<"|"<<rr.qtype.toString()<<": "<<pe.reason<<endl;
@@ -1540,7 +1541,8 @@ static int createZone(const DNSName &zone, const DNSName& nsname) {
   return EXIT_SUCCESS;
 }
 
-static int createSlaveZone(const vector<string>& cmds) {
+static int createSecondaryZone(const vector<string>& cmds)
+{
   UeberBackend B;
   DomainInfo di;
   DNSName zone(cmds.at(1));
@@ -1548,12 +1550,12 @@ static int createSlaveZone(const vector<string>& cmds) {
     cerr << "Zone '" << zone << "' exists already" << endl;
     return EXIT_FAILURE;
   }
-  vector<ComboAddress> masters;
+  vector<ComboAddress> primaries;
   for (unsigned i=2; i < cmds.size(); i++) {
-    masters.emplace_back(cmds.at(i), 53);
+    primaries.emplace_back(cmds.at(i), 53);
   }
-  cerr << "Creating secondary zone '" << zone << "', with primaries '" << comboAddressVecToString(masters) << "'" << endl;
-  B.createDomain(zone, DomainInfo::Slave, masters, "");
+  cerr << "Creating secondary zone '" << zone << "', with primaries '" << comboAddressVecToString(primaries) << "'" << endl;
+  B.createDomain(zone, DomainInfo::Secondary, primaries, "");
   if(!B.getDomainInfo(zone, di)) {
     cerr << "Zone '" << zone << "' was not created!" << endl;
     return EXIT_FAILURE;
@@ -1561,7 +1563,8 @@ static int createSlaveZone(const vector<string>& cmds) {
   return EXIT_SUCCESS;
 }
 
-static int changeSlaveZoneMaster(const vector<string>& cmds) {
+static int changeSecondaryZonePrimary(const vector<string>& cmds)
+{
   UeberBackend B;
   DomainInfo di;
   DNSName zone(cmds.at(1));
@@ -1569,13 +1572,13 @@ static int changeSlaveZoneMaster(const vector<string>& cmds) {
     cerr << "Zone '" << zone << "' doesn't exist" << endl;
     return EXIT_FAILURE;
   }
-  vector<ComboAddress> masters;
+  vector<ComboAddress> primaries;
   for (unsigned i=2; i < cmds.size(); i++) {
-    masters.emplace_back(cmds.at(i), 53);
+    primaries.emplace_back(cmds.at(i), 53);
   }
-  cerr << "Updating secondary zone '" << zone << "', primaries to '" << comboAddressVecToString(masters) << "'" << endl;
+  cerr << "Updating secondary zone '" << zone << "', primaries to '" << comboAddressVecToString(primaries) << "'" << endl;
   try {
-    di.backend->setMasters(zone, masters);
+    di.backend->setPrimaries(zone, primaries);
     return EXIT_SUCCESS;
   }
   catch (PDNSException& e) {
@@ -1657,7 +1660,7 @@ static int addOrReplaceRecord(bool addOrReplace, const vector<string>& cmds) {
     cout<<"Current records for "<<rr.qname<<" IN "<<rr.qtype.toString()<<" will be replaced"<<endl;
   }
   for(auto i = contentStart ; i < cmds.size() ; ++i) {
-    rr.content = DNSRecordContent::mastermake(rr.qtype.getCode(), QClass::IN, cmds.at(i))->getZoneRepresentation(true);
+    rr.content = DNSRecordContent::make(rr.qtype.getCode(), QClass::IN, cmds.at(i))->getZoneRepresentation(true);
 
     newrrs.push_back(rr);
   }
@@ -1677,12 +1680,12 @@ static int addOrReplaceRecord(bool addOrReplace, const vector<string>& cmds) {
   return EXIT_SUCCESS;
 }
 
-// addSuperMaster add a new autoprimary
-static int addSuperMaster(const std::string &IP, const std::string &nameserver, const std::string &account)
+// addAutoPrimary add a new autoprimary
+static int addAutoPrimary(const std::string& IP, const std::string& nameserver, const std::string& account)
 {
   UeberBackend B("default");
   const AutoPrimary primary(IP, nameserver, account);
-  if ( B.superMasterAdd(primary) ){
+  if (B.autoPrimaryAdd(primary)) {
     return EXIT_SUCCESS;
   }
   cerr<<"could not find a backend with autosecondary support"<<endl;
@@ -1895,19 +1898,19 @@ static void verifyCrypto(const string& zone)
     if(rr.qtype.getCode() == QType::DNSKEY) {
       cerr<<"got DNSKEY!"<<endl;
       apex=rr.qname;
-      drc = *std::dynamic_pointer_cast<DNSKEYRecordContent>(DNSRecordContent::mastermake(QType::DNSKEY, QClass::IN, rr.content));
+      drc = *std::dynamic_pointer_cast<DNSKEYRecordContent>(DNSRecordContent::make(QType::DNSKEY, QClass::IN, rr.content));
     }
     else if(rr.qtype.getCode() == QType::RRSIG) {
       cerr<<"got RRSIG"<<endl;
-      rrc = *std::dynamic_pointer_cast<RRSIGRecordContent>(DNSRecordContent::mastermake(QType::RRSIG, QClass::IN, rr.content));
+      rrc = *std::dynamic_pointer_cast<RRSIGRecordContent>(DNSRecordContent::make(QType::RRSIG, QClass::IN, rr.content));
     }
     else if(rr.qtype.getCode() == QType::DS) {
       cerr<<"got DS"<<endl;
-      dsrc = *std::dynamic_pointer_cast<DSRecordContent>(DNSRecordContent::mastermake(QType::DS, QClass::IN, rr.content));
+      dsrc = *std::dynamic_pointer_cast<DSRecordContent>(DNSRecordContent::make(QType::DS, QClass::IN, rr.content));
     }
     else {
       qname = rr.qname;
-      toSign.insert(DNSRecordContent::mastermake(rr.qtype.getCode(), QClass::IN, rr.content));
+      toSign.insert(DNSRecordContent::make(rr.qtype.getCode(), QClass::IN, rr.content));
     }
   }
 
@@ -2067,8 +2070,8 @@ static bool showZone(DNSSECKeeper& dk, const DNSName& zone, bool exportDS = fals
       }
     }
     else if (di.isSecondaryType()) {
-      cout << "Primar" << addS(di.masters, "y", "ies") << ": ";
-      for(const auto& m : di.masters)
+      cout << "Primar" << addS(di.primaries, "y", "ies") << ": ";
+      for (const auto& m : di.primaries)
         cout<<m.toStringWithPort()<<" ";
       cout<<endl;
       struct tm tm;
@@ -2298,8 +2301,7 @@ static bool secureZone(DNSSECKeeper& dk, const DNSName& zone)
     return false;
   }
 
-  if(di.kind == DomainInfo::Slave)
-  {
+  if (di.kind == DomainInfo::Secondary) {
     cerr << "Warning! This is a secondary zone! If this was a mistake, please run" << endl;
     cerr<<"pdnsutil disable-dnssec "<<zone<<" right now!"<<endl;
   }
@@ -2361,9 +2363,9 @@ static int testSchema(DNSSECKeeper& dk, const DNSName& zone)
   cout<<"Constructing UeberBackend"<<endl;
   UeberBackend B("default");
   cout<<"Picking first backend - if this is not what you want, edit launch line!"<<endl;
-  DNSBackend *db = B.backends[0];
+  DNSBackend *db = B.backends[0].get();
   cout << "Creating secondary zone " << zone << endl;
-  db->createSlaveDomain("127.0.0.1", zone, "", "_testschema");
+  db->createSecondaryDomain("127.0.0.1", zone, "", "_testschema");
   cout << "Secondary zone created" << endl;
 
   DomainInfo di;
@@ -2505,6 +2507,7 @@ static int addOrSetMeta(const DNSName& zone, const string& kind, const vector<st
   return 0;
 }
 
+// NOLINTNEXTLINE(readability-function-cognitive-complexity): TODO Clean this function up.
 int main(int argc, char** argv)
 try
 {
@@ -2755,7 +2758,7 @@ try
     // DNSResourceRecord rr;
     // rr.qtype = DNSRecordContent::TypeToNumber(cmds.at(1));
     // rr.content = cmds.at(2);
-    auto drc = DNSRecordContent::mastermake(DNSRecordContent::TypeToNumber(cmds.at(1)), QClass::IN, cmds.at(2));
+    auto drc = DNSRecordContent::make(DNSRecordContent::TypeToNumber(cmds.at(1)), QClass::IN, cmds.at(2));
     cout<<makeLuaString(drc->serialize(DNSName(), true))<<endl;
 
     return 0;
@@ -3112,19 +3115,19 @@ try
     }
     return createZone(DNSName(cmds.at(1)), cmds.size() > 2 ? DNSName(cmds.at(2)) : DNSName());
   }
-  else if (cmds.at(0) == "create-secondary-zone" || cmds.at(0) == "create-slave-zone") {
+  else if (cmds.at(0) == "create-secondary-zone") {
     if(cmds.size() < 3 ) {
       cerr << "Syntax: pdnsutil create-secondary-zone ZONE primary-ip [primary-ip..]" << endl;
       return 0;
     }
-    return createSlaveZone(cmds);
+    return createSecondaryZone(cmds);
   }
-  else if (cmds.at(0) == "change-secondary-zone-primary" || cmds.at(0) == "change-slave-zone-master") {
+  else if (cmds.at(0) == "change-secondary-zone-primary") {
     if(cmds.size() < 3 ) {
       cerr << "Syntax: pdnsutil change-secondary-zone-primary ZONE primary-ip [primary-ip..]" << endl;
       return 0;
     }
-    return changeSlaveZoneMaster(cmds);
+    return changeSecondaryZonePrimary(cmds);
   }
   else if (cmds.at(0) == "add-record") {
     if(cmds.size() < 5) {
@@ -3133,12 +3136,12 @@ try
     }
     return addOrReplaceRecord(true, cmds);
   }
-  else if (cmds.at(0) == "add-autoprimary" || cmds.at(0) == "add-supermaster") {
+  else if (cmds.at(0) == "add-autoprimary" || cmds.at(0) == "add-autoprimary") {
     if(cmds.size() < 3) {
       cerr << "Syntax: pdnsutil add-autoprimary IP NAMESERVER [account]" << endl;
       return 0;
     }
-    exit(addSuperMaster(cmds.at(1), cmds.at(2), cmds.size() > 3 ? cmds.at(3) : ""));
+    exit(addAutoPrimary(cmds.at(1), cmds.at(2), cmds.size() > 3 ? cmds.at(3) : ""));
   }
   else if (cmds.at(0) == "remove-autoprimary") {
     if(cmds.size() < 3) {
@@ -3796,9 +3799,9 @@ try
     }
     DNSName zname(cmds.at(1));
     string name = cmds.at(2);
-    if (cmds.at(3) == "primary" || cmds.at(3) == "master" || cmds.at(3) == "producer")
+    if (cmds.at(3) == "primary" || cmds.at(3) == "producer")
       metaKey = "TSIG-ALLOW-AXFR";
-    else if (cmds.at(3) == "secondary" || cmds.at(3) == "consumer" || cmds.at(3) == "slave")
+    else if (cmds.at(3) == "secondary" || cmds.at(3) == "consumer")
       metaKey = "AXFR-MASTER-TSIG";
     else {
       cerr << "Invalid parameter '" << cmds.at(3) << "', expected primary or secondary type" << endl;
@@ -3841,9 +3844,9 @@ try
     }
     DNSName zname(cmds.at(1));
     string name = cmds.at(2);
-    if (cmds.at(3) == "primary" || cmds.at(3) == "producer" || cmds.at(3) == "master")
+    if (cmds.at(3) == "primary" || cmds.at(3) == "producer")
       metaKey = "TSIG-ALLOW-AXFR";
-    else if (cmds.at(3) == "secondary" || cmds.at(3) == "consumer" || cmds.at(3) == "slave")
+    else if (cmds.at(3) == "secondary" || cmds.at(3) == "consumer")
       metaKey = "AXFR-MASTER-TSIG";
     else {
       cerr << "Invalid parameter '" << cmds.at(3) << "', expected primary or secondary type" << endl;
@@ -4080,19 +4083,27 @@ try
   }
   else if (cmds.at(0) == "b2b-migrate") {
     if (cmds.size() < 3) {
-      cerr<<"Usage: b2b-migrate OLD NEW"<<endl;
+      cerr << "Usage: b2b-migrate OLD NEW" << endl;
+      return 1;
+    }
+
+    if (cmds.at(1) == cmds.at(2)) {
+      cerr << "Error: b2b-migrate OLD NEW: OLD cannot be the same as NEW" << endl;
       return 1;
     }
 
-    DNSBackend *src = nullptr;
-    DNSBackend *tgt = nullptr;
+    unique_ptr<DNSBackend> src{nullptr};
+    unique_ptr<DNSBackend> tgt{nullptr};
 
-    for(DNSBackend *b : BackendMakers().all()) {
-      if (b->getPrefix() == cmds.at(1))
-        src = b;
-      if (b->getPrefix() == cmds.at(2))
-        tgt = b;
+    for (auto& backend : BackendMakers().all()) {
+      if (backend->getPrefix() == cmds.at(1)) {
+         src = std::move(backend);
+      }
+      else if (backend->getPrefix() == cmds.at(2)) {
+         tgt = std::move(backend);
+      }
     }
+
     if (src == nullptr) {
       cerr << "Unknown source backend '" << cmds.at(1) << "'" << endl;
       return 1;
@@ -4118,7 +4129,8 @@ try
       DNSResourceRecord rr;
       cout<<"Processing '"<<di.zone<<"'"<<endl;
       // create zone
-      if (!tgt->createDomain(di.zone, di.kind, di.masters, di.account)) throw PDNSException("Failed to create zone");
+      if (!tgt->createDomain(di.zone, di.kind, di.primaries, di.account))
+         throw PDNSException("Failed to create zone");
       if (!tgt->getDomainInfo(di.zone, di_new)) throw PDNSException("Failed to create zone");
       // move records
       if (!src->list(di.zone, di.id, true)) throw PDNSException("Failed to list records");
@@ -4190,21 +4202,22 @@ try
       return 1;
     }
 
-    DNSBackend *db = nullptr;
+    std::unique_ptr<DNSBackend> matchingBackend{nullptr};
 
-    for(DNSBackend *b : BackendMakers().all()) {
-      if (b->getPrefix() == cmds.at(1))
-        db = b;
+    for (auto& backend : BackendMakers().all()) {
+      if (backend->getPrefix() == cmds.at(1)) {
+        matchingBackend = std::move(backend);
+      }
     }
 
-    if (db == nullptr) {
+    if (matchingBackend == nullptr) {
       cerr << "Unknown backend '" << cmds.at(1) << "'" << endl;
       return 1;
     }
 
-    for(auto i=next(begin(cmds),2); i != end(cmds); ++i) {
-      cerr<<"== "<<*i<<endl;
-      cout<<db->directBackendCmd(*i);
+    for (auto i = next(begin(cmds), 2); i != end(cmds); ++i) {
+      cerr << "== " << *i << endl;
+      cout << matchingBackend->directBackendCmd(*i);
     }
 
     return 0;
index 6f6fcf35032332c04ebb1661aebce37060426f15..e8c1dceae7d6c131ea1567b19cd8f32628a1d3ba 100644 (file)
@@ -85,7 +85,7 @@ void pdns::ProtoZero::Message::addRRsFromPacket(const char* packet, const size_t
     return;
   }
 
-  const struct dnsheader* dh = reinterpret_cast<const struct dnsheader*>(packet);
+  const dnsheader_aligned dh(packet);
 
   if (ntohs(dh->ancount) == 0) {
     return;
index f1f1a504c6168ebb183fed9e7271396609e27750..241e0386d19da438306d8f386fe043c23bfee72c 100644 (file)
@@ -35,6 +35,7 @@ AC_DEFINE([RECURSOR], [1],
 m4_pattern_forbid([^_?PKG_[A-Z_]+$], [*** pkg.m4 missing, please install pkg-config])
 
 AX_CXX_COMPILE_STDCXX_17([noext], [mandatory])
+PDNS_CHECK_CARGO([1.64])
 
 # Rust runtime used dlopen from its static lib
 LT_INIT([dlopen])
diff --git a/pdns/recursordist/docs/appendices/structuredlogging.rst b/pdns/recursordist/docs/appendices/structuredlogging.rst
new file mode 100644 (file)
index 0000000..d483663
--- /dev/null
@@ -0,0 +1,102 @@
+Structured Logging Dictionary
+=============================
+
+This page describes the common entries of the Structured Logging component.
+Currently there are two possible values for :ref:`setting-structured-logging-backend`:
+
+- The ``default`` text based backend
+- The ``systemd-journal`` backend
+
+The ``default`` backend
+-----------------------
+The default backend uses a text representation of the key-value pairs.
+A line is constructed by appending all key-value pairs as ``key="value"``, separated by spaces.
+The output is written by passing the resulting text line to the standard error stream and also to ``syslog`` if :ref:`setting-disable-syslog` is false.
+Depending on the value of :ref:`setting-log-timestamp` a timestamp is prepended to the log line.
+
+An example line (including prepended timestamp) looks like this::
+
+  Oct 18 08:45:21 msg="Raised soft limit on number of filedescriptors to match max-mthreads and threads settings" subsystem="config" level="0" prio="Warning" tid="0" ts="1697611521.119" limit="6469"
+
+- Key names are not quoted.
+- Values are quoted with double quotes.
+- If a value contains a double quote, it is escaped with a backslash.
+- Backslashes in the value are escaped by prepending a backslash.
+
+The following keys are always present:
+
++-------------+------------------+--------------------------------------+---------------------------------------+
+| **Key**     | **Type**         | **Example**                          | **Remarks**                           |
++-------------+------------------+--------------------------------------+---------------------------------------+
+|``msg``      |``string``        | ``"Launching distributor threads"``  |Value is the same for all instances of |
+|             |                  |                                      |this log entry, together with          |
+|             |                  |                                      |``subsystem`` it uniquely identifies   |
+|             |                  |                                      |the log message.                       |
++-------------+------------------+--------------------------------------+---------------------------------------+
+|``subsystem``|``string``        |``"incoming"``                        |Uniquely identifies the log            |
+|             |                  |                                      |entry together with the value of       |
+|             |                  |                                      |``msg``.                               |
++-------------+------------------+--------------------------------------+---------------------------------------+
+| ``level``   |``number``        |``"0"``                               |The detail level of the log entry, do  |
+|             |                  |                                      |not confuse with                       |
+|             |                  |                                      |:ref:`setting-loglevel`. Not actively  |
+|             |                  |                                      |used currently.                        |
++-------------+------------------+--------------------------------------+---------------------------------------+
+| ``prio``    |``enum``          |``"Notice"``                          |One of ``Alert=1``, ``Critical=2``,    |
+|             |                  |                                      |``Error=3``, ``Warning=4``,            |
+|             |                  |                                      |``Notice=5``, ``Info=6``,              |
+|             |                  |                                      |``Debug=7``. A log entry will only     |
+|             |                  |                                      |produced if its ``prio`` is equal or   |
+|             |                  |                                      |lower than :ref:`setting-loglevel`.    |
++-------------+------------------+--------------------------------------+---------------------------------------+
+| ``tid``     |``number``        |``"2"``                               |The Posix worker thread id that        |
+|             |                  |                                      |produced the log entry. If not produced|
+|             |                  |                                      |by a worker thread, the value is zero. |
++-------------+------------------+--------------------------------------+---------------------------------------+
+| ``ts``      |``number``        |``"1697614303.039"``                  |Number of seconds since the Unix epoch,|
+|             |                  |                                      |including fractional part.             |
++-------------+------------------+--------------------------------------+---------------------------------------+
+
+A log entry can also have zero or more additional key-value pairs. Common keys are:
+
++-------------+---------------------+--------------------------------------+---------------------------------------+
+| **Key**     | **Type**            |**Example**                           | **Remarks**                           |
++-------------+---------------------+--------------------------------------+---------------------------------------+
+|``error``    |``string``           |``"No such file or directory"``       |An error cause.                        |
++-------------+---------------------+--------------------------------------+---------------------------------------+
+|``address``  |``ip address:port``  |``"[::]:5301"``                       |An IP: port combination.               |
++-------------+---------------------+--------------------------------------+---------------------------------------+
+|``addresses``|``list of subnets``  |``"127.0.0.0/8 ::ffff:0:0/96"``       |A list of subnets, space separated.    |
++-------------+---------------------+--------------------------------------+---------------------------------------+
+|``path``     |``filesystem path``  |``"tmp/api-dir/apizones"``            |                                       |
++-------------+---------------------+--------------------------------------+---------------------------------------+
+|``proto``    |``string``           |``"udp"``                             |                                       |
++-------------+---------------------+--------------------------------------+---------------------------------------+
+|``qname``    |``DNS name``         |``"example.com"``                     |                                       |
++-------------+---------------------+--------------------------------------+---------------------------------------+
+|``qtype``    |``DNS Query Type``   |``"AAAA"``                            |Text representation of DNS query type. |
++-------------+---------------------+--------------------------------------+---------------------------------------+
+| ``rcode``   |``DNS Response Code``|``"3"``                               |Numeric DNS response code              |
++-------------+---------------------+--------------------------------------+---------------------------------------+
+|``mtid``     |``Number``           |``"234"``                             |The id of the MThread that produced the|
+|             |                     |                                      |log entry.                             |
++-------------+---------------------+--------------------------------------+---------------------------------------+
+
+The ``systemd-journal`` backend
+-------------------------------
+The ``systemd-journal`` structured logging backend uses mostly the same keys and values as the default backend, with the exceptions:
+
+- keys are capitalized as required for ``systemd-journal``.
+- ``msg`` is translated to ``MESSAGE``.
+- ``prio`` is translated to ``PRIORITY``.
+- ``ts`` is translated to ``TIMESTAMP``.
+- If the original key is in a list of keys special to ``systemd-journal``, it is capitalized and prepended by ``PDNS_``.
+  The list of special keys is: message, message_id, priority, code_file, code_line, code_func, errno, invocation_id, user_invocation_id, syslog_facility, syslog_identifier, syslog_pid, syslog_timestamp, syslog_raw, documentation, tid, unit, user_unit, object_pid.
+
+To use this logging backend, add the ``--structured-logging-backend=systemd-journal`` to the command line in the systemd unit file.
+Note that adding it to the recursor configuration file does not work as expected, as this file is processed after the logging has been set up.
+
+To query the log, use a command similar to::
+
+  # journalctl -r -n 1 -o json-pretty -u pdns-recursor.service
+
index 333a683743cce2c0a08a282742e915348962918e..19e2bbb12c54869b64cc0dd343fce34d6cdc84a9 100644 (file)
@@ -1,5 +1,65 @@
 Changelogs for 4.9.X
 ====================
+.. changelog::
+  :version: 4.9.2
+  :released: 8th of November 2023
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 13449
+    :tickets: 13383, 13409
+
+    Handle serve stale logic in getRootNXTrust().
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 13411
+    :tickets: 13353
+
+    If serving stale, wipe CNAME records from cache when we get a NODATA negative response for them.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 13412
+    :tickets: 13408
+
+    Handle stack memory on NetBSD as on OpenBSD.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 13286
+    :tickets: 13092
+
+    Prevent two cases of copy of data that can be moved.
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 13284
+    :tickets: 13210
+
+    Remove Before=nss-lookup.target line from systemd unit file.
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 13283
+    :tickets: 13278
+
+    Prevent lookups for unsupported qtypes or rcode != 0 to submit refresh tasks.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 13282
+    :tickets: 13209
+
+    Implement a more fair way to prune the aggressive cache.
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 13176
+    :tickets: 13102
+
+    Do not assume the records are in a particular order when determining if an answer is NODATA.
+
 .. changelog::
   :version: 4.9.1
   :released: 25th of August 2023
index c079e08a50e61d9533bd62bcb76c88c37f3bba8c..8bc0767d71d41e8df42ac0d73231be25057186e0 100644 (file)
@@ -1,5 +1,73 @@
 Changelogs for 5.0.X
 ====================
+
+.. changelog::
+  :version: 5.0.0-beta1
+  :released: 10th of November 2023
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 13468
+
+    Fix ubsan error: using a value of 80 for bool.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 13462
+
+    Be more memory efficient handling RPZ updates.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 13464
+
+    Change default of extended-resolution-errors setting to true.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 13455
+
+    Move a few settings from recursor to outgoing section.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 13446
+
+    For structured logging always log addresses including port.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 13438
+
+    Teach configure to check for cargo version and require >= 1.64.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 13410
+    :tickets: 12612
+
+    Tidy cache and only copy values if non-expired entry was found.
+
+  .. change::
+    :tags: Bug Fixes
+    :pullreq: 13409
+    :tickets: 13383
+
+    Handle serve stale logic in getRootNXTrust().
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 13432,13430
+    :tickets: 13430
+
+    Add endbr64 instructions in the right spots for OpenBSD/amd64.
+
+  .. change::
+    :tags: Improvements
+    :pullreq: 13408
+
+    Handle stack memory on NetBSD as on OpenBSD (Tom Ivar Helbekkmo)
+
 .. changelog::
   :version: 5.0.0-alpha2
   :released: 17th of October 2023
index 9da78abea32ea3c8b760727cd86902b1a28c2429..f08a8ac09a0085e70a2c074240eb6b33af0c5be2 100644 (file)
@@ -32,6 +32,7 @@ New settings
 Changed settings
 ^^^^^^^^^^^^^^^^
 - The :ref:`setting-loglevel` can now be set to a level below 3 (error).
+- The :ref:`setting-extended-resolution-errors` now defaults to enabled.
 
 4.8.0 to 4.9.0
 --------------
index cc46516dbf61104429bd3940b1efa66a92e63945..e1b0e61640037cfb2f6a03730c3848ebb0c3d010 100644 (file)
@@ -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.setContent(DNSRecordContent::mastermake(QType::CNAME, QClass::IN, getKindToString(d_kind)));
+    dr.setContent(DNSRecordContent::make(QType::CNAME, QClass::IN, getKindToString(d_kind)));
     result.push_back(std::move(dr));
   }
 
@@ -786,7 +786,7 @@ void DNSFilterEngine::Zone::dumpAddrPolicy(FILE* fp, const Netmask& nm, const DN
 void DNSFilterEngine::Zone::dump(FILE* fp) const
 {
   /* fake the SOA record */
-  auto soa = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "fake.RPZ. hostmaster.fake.RPZ. " + std::to_string(d_serial) + " " + std::to_string(d_refresh) + " 600 3600000 604800");
+  auto soa = DNSRecordContent::make(QType::SOA, QClass::IN, "fake.RPZ. hostmaster.fake.RPZ. " + std::to_string(d_serial) + " " + std::to_string(d_refresh) + " 600 3600000 604800");
   fprintf(fp, "%s IN SOA %s\n", d_domain.toString().c_str(), soa->getZoneRepresentation().c_str());
 
   for (const auto& pair : d_qpolName) {
index ead82293af9d50f41ed35f03d0d52965242abc98..05ab56b1fa0e1bd89172008e4f288d363b1e895d 100644 (file)
@@ -27,8 +27,8 @@
 #include <sys/mman.h>
 #include <unistd.h>
 
-// On OpenBSD mem used as stack should be marked MAP_STACK
-#ifdef __OpenBSD__
+// On OpenBSD and NetBSD mem used as stack should be marked MAP_STACK
+#if defined(__OpenBSD__) || defined(__NetBSD__)
 #define PDNS_MAP_STACK MAP_STACK
 #else
 #define PDNS_MAP_STACK 0
@@ -82,8 +82,8 @@ struct lazy_allocator
     const auto padding = getAlignmentPadding(requestedSize, pageSize);
     const size_type allocatedSize = requestedSize + padding + (pageSize * 2);
 
-#ifdef __OpenBSD__
-    // OpenBSD does not like mmap MAP_STACK regions that have
+#if defined(__OpenBSD__) || defined(__NetBSD__)
+    // OpenBSD and NetBSD don't like mmap MAP_STACK regions that have
     // PROT_NONE, so allocate r/w and mprotect the guard pages
     // explicitly.
     const int protection = PROT_READ | PROT_WRITE;
@@ -96,7 +96,7 @@ struct lazy_allocator
     }
     char* basePointer = static_cast<char*>(p);
     void* usablePointer = basePointer + pageSize;
-#ifdef __OpenBSD__
+#if defined(__OpenBSD__) || defined(__NetBSD__)
     int res = mprotect(basePointer, pageSize, PROT_NONE);
     if (res != 0) {
       munmap(p, allocatedSize);
index a22f54d6bf391f199135fc8d9d861c092e531010..985f9bf043c4a02edc78b8c997e4fa1deef4e439 100644 (file)
@@ -135,7 +135,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.setContent(DNSRecordContent::mastermake(type, QClass::IN, content));
+  dr.setContent(DNSRecordContent::make(type, QClass::IN, content));
   records.push_back(dr);
 }
 
@@ -239,7 +239,7 @@ void RecursorLua4::postPrepareContext()
     [](DNSFilterEngine::Policy& pol, const std::string& content) {
       // Only CNAMES for now, when we ever add a d_custom_type, there will be pain
       pol.d_custom.clear();
-      pol.d_custom.push_back(DNSRecordContent::mastermake(QType::CNAME, QClass::IN, content));
+      pol.d_custom.push_back(DNSRecordContent::make(QType::CNAME, QClass::IN, content));
     }
   );
   d_lw->registerFunction("getDH", &DNSQuestion::getDH);
@@ -296,7 +296,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.setContent(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::make(dr.d_type, QClass::IN, newContent)); });
   d_lw->registerFunction("addAnswer", &DNSQuestion::addAnswer);
   d_lw->registerFunction("addRecord", &DNSQuestion::addRecord);
   d_lw->registerFunction("getRecords", &DNSQuestion::getRecords);
@@ -1030,7 +1030,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.setContent(DNSRecordContent::mastermake(type, QClass::IN, std::string(content, contentSize)));
+    dr.setContent(DNSRecordContent::make(type, QClass::IN, std::string(content, contentSize)));
     ref->params.records.push_back(std::move(dr));
 
     return true;
@@ -1173,7 +1173,7 @@ bool pdns_postresolve_ffi_handle_set_record(pdns_postresolve_ffi_handle_t* ref,
       r.setContent(DNSRecordContent::deserialize(r.d_name, r.d_type, string(content, contentLen)));
     }
     else {
-      r.setContent(DNSRecordContent::mastermake(r.d_type, QClass::IN, string(content, contentLen)));
+      r.setContent(DNSRecordContent::make(r.d_type, QClass::IN, string(content, contentLen)));
     }
 
     return true;
@@ -1202,7 +1202,7 @@ bool pdns_postresolve_ffi_handle_add_record(pdns_postresolve_ffi_handle_t* ref,
       dr.setContent(DNSRecordContent::deserialize(dr.d_name, dr.d_type, string(content, contentLen)));
     }
     else {
-      dr.setContent(DNSRecordContent::mastermake(type, QClass::IN, string(content, contentLen)));
+      dr.setContent(DNSRecordContent::make(type, QClass::IN, string(content, contentLen)));
     }
     ref->handle.d_dq.currentRecords->push_back(std::move(dr));
 
diff --git a/pdns/recursordist/m4/ax_compare_version.m4 b/pdns/recursordist/m4/ax_compare_version.m4
new file mode 120000 (symlink)
index 0000000..e9020c1
--- /dev/null
@@ -0,0 +1 @@
+../../../m4/ax_compare_version.m4
\ No newline at end of file
diff --git a/pdns/recursordist/m4/pdns_check_cargo.m4 b/pdns/recursordist/m4/pdns_check_cargo.m4
new file mode 100644 (file)
index 0000000..cd39bc4
--- /dev/null
@@ -0,0 +1,13 @@
+AC_DEFUN([PDNS_CHECK_CARGO], [
+  AC_REQUIRE([AC_PROG_SED])
+
+  AC_CHECK_PROG(CARGO, [cargo], [cargo], $CARGO)
+  AS_IF(test x$CARGO = x,
+    AC_MSG_ERROR([cargo is required])
+  )
+  minimum=$1
+  cargo_version=`$CARGO --version | $SED -e 's/^cargo //g'`
+  AX_COMPARE_VERSION([$cargo_version],[lt],[$minimum], [
+    AC_MSG_ERROR([need at least cargo version $minimum])
+  ])
+])
index dd3eb707baf10c2907e6b2dbd47d5819886a8458..e489b40e1515455811cbdae48bea2ecb5aa3e9e9 100644 (file)
@@ -32,6 +32,17 @@ using boost::context::make_fcontext;
 using boost::context::detail::make_fcontext;
 #endif /* BOOST_VERSION < 106100 */
 
+// __CET__ is set by the compiler if relevant, so far only relevant/tested for amd64 on OpenBSD
+#if defined(__amd64__)
+#if __CET__ & 0x1
+#define CET_ENDBR __asm("endbr64")
+#else
+#define CET_ENDBR
+#endif
+#else
+#define CET_ENDBR
+#endif
+
 #ifdef PDNS_USE_VALGRIND
 #include <valgrind/valgrind.h>
 #endif /* PDNS_USE_VALGRIND */
@@ -132,6 +143,7 @@ extern "C"
                   static_cast<fcontext_t>(args->prev_ctx), 0);
 #else
     transfer_t res = jump_fcontext(t.fctx, 0);
+    CET_ENDBR;
     /* we got switched back from pdns_swapcontext() */
     if (res.data) {
       /* if res.data is not a nullptr, it holds a pointer to the context
@@ -203,6 +215,7 @@ void pdns_swapcontext(pdns_ucontext_t& __restrict octx, pdns_ucontext_t const& _
     std::rethrow_exception(origctx->exception);
 #else
   transfer_t res = jump_fcontext(static_cast<fcontext_t>(ctx.uc_mcontext), &octx.uc_mcontext);
+  CET_ENDBR;
   if (res.data) {
     /* if res.data is not a nullptr, it holds a pointer to the context
        we just switched from, and we need to fill it to be able to
@@ -235,6 +248,7 @@ void pdns_makecontext(pdns_ucontext_t& ctx, std::function<void(void)>& start)
 #else
   transfer_t res = jump_fcontext(static_cast<fcontext_t>(ctx.uc_mcontext),
                                  &args);
+  CET_ENDBR;
   /* back from threadwrapper, updating the context */
   ctx.uc_mcontext = res.fctx;
 #endif
index af6cd1fa6aa9b858993e448dc5648be250a390a1..9b0b347180fe2770f6fec9a21f60e81740832795 100644 (file)
@@ -53,35 +53,20 @@ size_t NegCache::size() const
  * \param ne       A NegCacheEntry that is filled when there is a cache entry
  * \return         true if ne was filled out, false otherwise
  */
-bool NegCache::getRootNXTrust(const DNSName& qname, const struct timeval& now, NegCacheEntry& ne, bool serveStale, bool refresh)
+bool NegCache::getRootNXTrust(const DNSName& qname, const struct timeval& now, NegCacheEntry& negEntry, bool serveStale, bool refresh)
 {
   // Never deny the root.
-  if (qname.isRoot())
+  if (qname.isRoot()) {
     return false;
+  }
 
-  // An 'ENT' QType entry, used as "whole name" in the neg-cache context.
-  static const QType qtnull(0);
   DNSName lastLabel = qname.getLastLabel();
-
-  auto& map = getMap(lastLabel);
-  auto content = map.lock();
-
-  negcache_t::const_iterator ni = content->d_map.find(std::tie(lastLabel, qtnull));
-
-  while (ni != content->d_map.end() && ni->d_name == lastLabel && ni->d_auth.isRoot() && ni->d_qtype == qtnull) {
-    if (!refresh && (serveStale || ni->d_servedStale > 0) && ni->d_ttd <= now.tv_sec && ni->d_servedStale < s_maxServedStaleExtensions) {
-      updateStaleEntry(now.tv_sec, ni, QType::A);
-    }
-    // We have something
-    if (now.tv_sec < ni->d_ttd) {
-      ne = *ni;
-      moveCacheItemToBack<SequenceTag>(content->d_map, ni);
-      return true;
-    }
-    if (ni->d_servedStale == 0 && !serveStale) {
-      moveCacheItemToFront<SequenceTag>(content->d_map, ni);
-    }
-    ++ni;
+  NegCacheEntry found;
+  // An 'ENT' QType entry, used as "whole name" in the neg-cache context.
+  auto exists = get(lastLabel, QType::ENT, now, found, true, serveStale, refresh);
+  if (exists && found.d_auth.isRoot()) {
+    negEntry = found;
+    return true;
   }
   return false;
 }
@@ -287,7 +272,7 @@ void NegCache::clear()
 void NegCache::prune(time_t now, size_t maxEntries)
 {
   size_t cacheSize = size();
-  pruneMutexCollectionsVector<SequenceTag>(now, *this, d_maps, maxEntries, cacheSize);
+  pruneMutexCollectionsVector<SequenceTag>(now, d_maps, maxEntries, cacheSize);
 }
 
 /*!
index 86c3b562f428e3e1b636cb1c33f5bcfd3bc9c554..d0d87ee4004180359af5c72c1f8fabf4379e5a86 100644 (file)
@@ -95,7 +95,7 @@ public:
   void add(const NegCacheEntry& ne);
   void updateValidationStatus(const DNSName& qname, QType qtype, vState newState, boost::optional<time_t> capTTD);
   bool get(const DNSName& qname, QType qtype, const struct timeval& now, NegCacheEntry& ne, bool typeMustMatch = false, bool serverStale = false, bool refresh = false);
-  bool getRootNXTrust(const DNSName& qname, const struct timeval& now, NegCacheEntry& ne, bool serveStale, bool refresh);
+  bool getRootNXTrust(const DNSName& qname, const struct timeval& now, NegCacheEntry& negEntry, bool serveStale, bool refresh);
   size_t count(const DNSName& qname);
   size_t count(const DNSName& qname, QType qtype);
   void prune(time_t now, size_t maxEntries);
@@ -140,6 +140,7 @@ private:
       uint64_t d_contended_count{0};
       uint64_t d_acquired_count{0};
       void invalidate() {}
+      void preRemoval(const NegCacheEntry& /* entry */) {}
     };
 
     LockGuardedTryHolder<MapCombo::LockedContent> lock()
@@ -188,7 +189,4 @@ private:
   {
     return d_maps.at(qname.hash() % d_maps.size());
   }
-
-public:
-  void preRemoval(MapCombo::LockedContent& /* map */, const NegCacheEntry& /* entry */) {}
 };
index 6ecbce1b78ecb0c096c236710975434fb41870dc..9d7d10a3d4cbf535765f507083dcd9b8754b8530 100644 (file)
@@ -870,11 +870,16 @@ static void dumpTrace(const string& trace, const timeval& timev)
   fprintf(filep.get(), " us === START OF TRACE %s ===\n", timebuf.data());
   fprintf(filep.get(), "%s", trace.c_str());
   isoDateTimeMillis(now, timebuf.data(), timebuf.size());
-  fprintf(filep.get(), "=== END OF TRACE %s ===\n", timebuf.data());
   if (ferror(filep.get()) != 0) {
     int err = errno;
     SLOG(g_log << Logger::Error << "Problems writing to trace file: " << stringerror(err) << endl,
          g_slog->withName("trace")->error(Logr::Error, err, "Problems writing to trace file"));
+    // There's no guarantee the message below will end up in the stream, but we try our best
+    clearerr(filep.get());
+    fprintf(filep.get(), "=== TRACE %s TRUNCATED; USE FILE ARGUMENT INSTEAD OF `-' ===\n", timebuf.data());
+  }
+  else {
+    fprintf(filep.get(), "=== END OF TRACE %s ===\n", timebuf.data());
   }
   // fclose by unique_ptr does implicit flush
 }
@@ -1842,10 +1847,10 @@ void startDoResolve(void* arg) // NOLINT(readability-function-cognitive-complexi
 
     if (comboWriter->d_mdp.d_header.opcode == static_cast<unsigned>(Opcode::Query)) {
       if (resolver.d_outqueries != 0 || resolver.d_authzonequeries != 0) {
-        g_recCache->cacheMisses++;
+        g_recCache->incCacheMisses();
       }
       else {
-        g_recCache->cacheHits++;
+        g_recCache->incCacheHits();
       }
     }
 
@@ -2365,7 +2370,6 @@ static string* doProcessUDPQuestion(const std::string& question, const ComboAddr
 
 static void handleNewUDPQuestion(int fileDesc, FDMultiplexer::funcparam_t& /* var */) // NOLINT(readability-function-cognitive-complexity): https://github.com/PowerDNS/pdns/issues/12791
 {
-  ssize_t len = 0;
   static const size_t maxIncomingQuerySize = g_proxyProtocolACL.empty() ? 512 : (512 + g_proxyProtocolMaximumSize);
   static thread_local std::string data;
   ComboAddress fromaddr; // the address the query is coming from
@@ -2389,7 +2393,7 @@ static void handleNewUDPQuestion(int fileDesc, FDMultiplexer::funcparam_t& /* va
     fromaddr.sin6.sin6_family = AF_INET6; // this makes sure fromaddr is big enough
     fillMSGHdr(&msgh, &iov, &cbuf, sizeof(cbuf), data.data(), data.size(), &fromaddr);
 
-    if ((len = recvmsg(fileDesc, &msgh, 0)) >= 0) {
+    if (ssize_t len = recvmsg(fileDesc, &msgh, 0); len >= 0) {
       eventTrace.clear();
       eventTrace.setEnabled(SyncRes::s_event_trace_enabled != 0);
       eventTrace.add(RecEventTrace::ReqRecv);
index 96d12941705d5e85e6197bad77921e7af831a5b3..83c48cd432c3a4826032a5f8f914892b26aa1d40 100644 (file)
@@ -109,8 +109,8 @@ static void parseRPZParameters(rpzOptions_t& have, std::shared_ptr<DNSFilterEngi
     defpol->d_kind = (DNSFilterEngine::PolicyKind)boost::get<uint32_t>(have["defpol"]);
     defpol->setName(polName);
     if (defpol->d_kind == DNSFilterEngine::PolicyKind::Custom) {
-      defpol->d_custom.push_back(DNSRecordContent::mastermake(QType::CNAME, QClass::IN,
-                                                              boost::get<string>(have["defcontent"])));
+      defpol->d_custom.push_back(DNSRecordContent::make(QType::CNAME, QClass::IN,
+                                                        boost::get<string>(have["defcontent"])));
 
       if (have.count("defttl") != 0) {
         defpol->d_ttl = static_cast<int32_t>(boost::get<uint32_t>(have["defttl"]));
@@ -884,7 +884,8 @@ void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& de
     catch (const PDNSException& exp) {
       // exp is the exception that was thrown from inside the lambda
       SLOG(g_log << exp.reason << std::endl,
-           lci.d_slog->error(Logr::Error, exp.reason, "Exception loading Lua", "exception", Logging::Loggable("PDNSException")))    }
+           lci.d_slog->error(Logr::Error, exp.reason, "Exception loading Lua", "exception", Logging::Loggable("PDNSException")));
+    }
     throw;
   }
   catch (std::exception& err) {
index dc0d3345ab6ba4f35075440b451061ca82f913c0..9cc1cde07ab463162800dd5ed8a213c02def9da4 100644 (file)
@@ -1072,8 +1072,8 @@ static void doStats()
   static time_t lastOutputTime;
   static uint64_t lastQueryCount;
 
-  uint64_t cacheHits = g_recCache->cacheHits;
-  uint64_t cacheMisses = g_recCache->cacheMisses;
+  uint64_t cacheHits = g_recCache->getCacheHits();
+  uint64_t cacheMisses = g_recCache->getCacheMisses();
   uint64_t cacheSize = g_recCache->size();
   auto rc_stats = g_recCache->stats();
   auto pc_stats = g_packetCache ? g_packetCache->stats() : std::pair<uint64_t, uint64_t>{0, 0};
@@ -2354,7 +2354,7 @@ private:
     0, 0
   };
   struct timeval period;
-  const string name;
+  string name;
 };
 
 static void houseKeepingWork(Logr::log_t log)
@@ -2788,7 +2788,7 @@ static void recursorThread()
     if (threadInfo.isHandler()) {
       if (::arg().mustDo("webserver")) {
         SLOG(g_log << Logger::Warning << "Enabling web server" << endl,
-             log->info(Logr::Info, "Enabling web server"))
+             log->info(Logr::Info, "Enabling web server"));
         try {
           rws = make_unique<RecursorWebServer>(t_fdm.get());
         }
@@ -2837,11 +2837,11 @@ static void recursorThread()
   }
   catch (PDNSException& ae) {
     SLOG(g_log << Logger::Error << "Exception: " << ae.reason << endl,
-         log->error(Logr::Error, ae.reason, "Exception in RecursorThread", "exception", Logging::Loggable("PDNSException")))
+         log->error(Logr::Error, ae.reason, "Exception in RecursorThread", "exception", Logging::Loggable("PDNSException")));
   }
   catch (std::exception& e) {
     SLOG(g_log << Logger::Error << "STL Exception: " << e.what() << endl,
-         log->error(Logr::Error, e.what(), "Exception in RecursorThread", "exception", Logging::Loggable("std::exception")))
+         log->error(Logr::Error, e.what(), "Exception in RecursorThread", "exception", Logging::Loggable("std::exception")));
   }
   catch (...) {
     SLOG(g_log << Logger::Error << "any other exception in main: " << endl,
index 8854ce12e0747ba9f366d12b28b59a9ff7c5dab1..8b65110e0fb0af41396e5f650ca99320742b3875 100644 (file)
@@ -54,7 +54,7 @@ void TCPOutConnectionManager::cleanup(const struct timeval& now)
 void TCPOutConnectionManager::store(const struct timeval& now, const ComboAddress& ip, Connection&& connection)
 {
   ++connection.d_numqueries;
-  if (s_maxQueries > 0 && connection.d_numqueries > s_maxQueries) {
+  if (s_maxQueries > 0 && connection.d_numqueries >= s_maxQueries) {
     return;
   }
 
index 3d6dfc1901fcb58e3ae5665e4fe885f41cc93ebc..186befa61c067fbf153fb9f7485eec65238d945a 100644 (file)
@@ -1102,16 +1102,6 @@ static uint64_t doGetCacheBytes()
   return g_recCache->bytes();
 }
 
-static uint64_t doGetCacheHits()
-{
-  return g_recCache->cacheHits;
-}
-
-static uint64_t doGetCacheMisses()
-{
-  return g_recCache->cacheMisses;
-}
-
 static uint64_t doGetMallocated()
 {
   // this turned out to be broken
@@ -1291,8 +1281,8 @@ static void registerAllStats1()
   addGetStat("ipv6-questions", [] { return g_Counters.sum(rec::Counter::ipv6qcounter); });
   addGetStat("tcp-questions", [] { return g_Counters.sum(rec::Counter::tcpqcounter); });
 
-  addGetStat("cache-hits", doGetCacheHits);
-  addGetStat("cache-misses", doGetCacheMisses);
+  addGetStat("cache-hits", []() { return g_recCache->getCacheHits(); });
+  addGetStat("cache-misses", []() { return g_recCache->getCacheMisses(); });
   addGetStat("cache-entries", doGetCacheSize);
   addGetStat("max-cache-entries", []() { return g_maxCacheEntries.load(); });
   addGetStat("max-packetcache-entries", []() { return g_maxPacketCacheEntries.load(); });
index f19176a141517c93160a7af672cc24c5572fe768..0b54090e058a9e7b28ec86ca7bce677d562d2789 100644 (file)
@@ -254,7 +254,7 @@ void RecursorPacketCache::insertResponsePacket(unsigned int tag, uint32_t qhash,
 void RecursorPacketCache::doPruneTo(time_t now, size_t maxSize)
 {
   size_t cacheSize = size();
-  pruneMutexCollectionsVector<SequencedTag>(now, *this, d_maps, maxSize, cacheSize);
+  pruneMutexCollectionsVector<SequencedTag>(now, d_maps, maxSize, cacheSize);
 }
 
 uint64_t RecursorPacketCache::doDump(int file)
index 0e51cea628f0de42ceaeffa5c68b5ea61fafc427..17b618563eba72a334bd4c1d94c33f036d589732 100644 (file)
@@ -183,6 +183,7 @@ private:
       uint64_t d_contended_count{0};
       uint64_t d_acquired_count{0};
       void invalidate() {}
+      void preRemoval(const Entry& /* entry */) {}
     };
 
     LockGuardedTryHolder<MapCombo::LockedContent> lock()
@@ -241,9 +242,4 @@ private:
   static 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 12067195c5e8c00c9078f0adf05db97c3725a17e..95cfdc1658a2f5b4972289e8176b94f1ffe04cd3 100644 (file)
@@ -10,7 +10,6 @@
 #include "dnsrecords.hh"
 #include "arguments.hh"
 #include "syncres.hh"
-#include "recursor_cache.hh"
 #include "namespaces.hh"
 #include "cachecleaner.hh"
 #include "rec-taskqueue.hh"
@@ -130,32 +129,37 @@ static void updateDNSSECValidationStateFromCache(boost::optional<vState>& state,
   else if (stateUpdate == vState::NTA) {
     state = vState::Insecure;
   }
-  else if (vStateIsBogus(stateUpdate)) {
-    state = stateUpdate;
-  }
-  else if (stateUpdate == vState::Indeterminate) {
+  else if (vStateIsBogus(stateUpdate) || stateUpdate == vState::Indeterminate) {
     state = stateUpdate;
   }
-  else if (stateUpdate == vState::Insecure) {
+  else if (stateUpdate == vState::Insecure || stateUpdate == vState::Secure) {
     if (!vStateIsBogus(*state) && *state != vState::Indeterminate) {
       state = stateUpdate;
     }
   }
-  else if (stateUpdate == vState::Secure) {
-    if (!vStateIsBogus(*state) && *state != vState::Indeterminate) {
-      state = stateUpdate;
-    }
+}
+
+template <typename T>
+static void ptrAssign(T* ptr, const T& value)
+{
+  if (ptr != nullptr) {
+    *ptr = value;
   }
 }
 
-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)
+time_t MemRecursorCache::handleHit(time_t now, 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;
+  if (ttd <= now) {
+    // Expired, don't bother returning contents. Callers *MUST* check return value of get(), and only look at the entry
+    // if it returned > 0
+    return ttd;
+  }
   origTTL = entry->d_orig_ttl;
 
-  if (variable != nullptr && (!entry->d_netmask.empty() || entry->d_rtag)) {
-    *variable = true;
+  if (!entry->d_netmask.empty() || entry->d_rtag) {
+    ptrAssign(variable, true);
   }
 
   if (res != nullptr) {
@@ -187,14 +191,8 @@ time_t MemRecursorCache::handleHit(MapCombo::LockedContent& content, MemRecursor
   if (wasAuth != nullptr) {
     *wasAuth = *wasAuth && entry->d_auth;
   }
-
-  if (fromAuthZone != nullptr) {
-    *fromAuthZone = entry->d_authZone;
-  }
-
-  if (fromAuthIP != nullptr) {
-    *fromAuthIP = entry->d_from;
-  }
+  ptrAssign(fromAuthZone, entry->d_authZone);
+  ptrAssign(fromAuthIP, entry->d_from);
 
   moveCacheItemToBack<SequencedTag>(content.d_map, entry);
 
@@ -268,15 +266,13 @@ MemRecursorCache::cache_t::const_iterator MemRecursorCache::getEntryUsingECSInde
         /* we need auth data and the best match is not authoritative */
         return map.d_map.end();
       }
-      else {
-        /* this netmask-specific entry has expired */
-        moveCacheItemToFront<SequencedTag>(map.d_map, entry);
-        // XXX when serving stale, it should be kept, but we don't want a match wth lookupBestMatch()...
-        ecsIndex->removeNetmask(best);
-        if (ecsIndex->isEmpty()) {
-          map.d_ecsIndex.erase(ecsIndex);
-          break;
-        }
+      /* this netmask-specific entry has expired */
+      moveCacheItemToFront<SequencedTag>(map.d_map, entry);
+      // XXX when serving stale, it should be kept, but we don't want a match wth lookupBestMatch()...
+      ecsIndex->removeNetmask(best);
+      if (ecsIndex->isEmpty()) {
+        map.d_ecsIndex.erase(ecsIndex);
+        break;
       }
     }
   }
@@ -300,7 +296,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 /* qtype */, const OptTag& rtag)
 {
   // MUTEX SHOULD BE ACQUIRED
   if (!map.d_cachecachevalid || map.d_cachedqname != qname || map.d_cachedrtag != rtag) {
@@ -313,14 +309,15 @@ MemRecursorCache::Entries MemRecursorCache::getEntries(MapCombo::LockedContent&
   return map.d_cachecache;
 }
 
-bool MemRecursorCache::entryMatches(MemRecursorCache::OrderedTagIterator_t& entry, const QType qt, bool requireAuth, const ComboAddress& who)
+bool MemRecursorCache::entryMatches(MemRecursorCache::OrderedTagIterator_t& entry, const QType qtype, bool requireAuth, const ComboAddress& who)
 {
   // This code assumes that if a routing tag is present, it matches
   // MUTEX SHOULD BE ACQUIRED
-  if (requireAuth && !entry->d_auth)
+  if (requireAuth && !entry->d_auth) {
     return false;
+  }
 
-  bool match = (entry->d_qtype == qt || qt == QType::ANY || (qt == QType::ADDR && (entry->d_qtype == QType::A || entry->d_qtype == QType::AAAA)))
+  bool match = (entry->d_qtype == qtype || qtype == QType::ANY || (qtype == QType::ADDR && (entry->d_qtype == QType::A || entry->d_qtype == QType::AAAA)))
     && (entry->d_netmask.empty() || entry->d_netmask.match(who));
   return match;
 }
@@ -343,35 +340,32 @@ time_t MemRecursorCache::fakeTTD(MemRecursorCache::OrderedTagIterator_t& entry,
       if (refresh) {
         return -1;
       }
-      else {
-        if (!entry->d_submitted) {
-          pushRefreshTask(qname, qtype, entry->d_ttd, entry->d_netmask);
-          entry->d_submitted = true;
-        }
+      if (!entry->d_submitted) {
+        pushRefreshTask(qname, qtype, entry->d_ttd, entry->d_netmask);
+        entry->d_submitted = true;
       }
     }
   }
   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<const 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 qtype, 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;
-  bool serveStale = flags & ServeStale;
+  bool requireAuth = (flags & RequireAuth) != 0;
+  bool refresh = (flags & Refresh) != 0;
+  bool serveStale = (flags & ServeStale) != 0;
 
   boost::optional<vState> cachedState{boost::none};
-  uint32_t origTTL;
+  uint32_t origTTL = 0;
 
   if (res != nullptr) {
     res->clear();
   }
-  const uint16_t qtype = qt.getCode();
-  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;
-  }
+
+  // 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
+  ptrAssign(wasAuth, true);
 
   auto& shard = getMap(qname);
   auto lockedShard = shard.lock();
@@ -384,11 +378,11 @@ time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qt, F
 
       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);
+        ret = handleHit(now, *lockedShard, entryA, 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);
+        time_t ttdAAAA = handleHit(now, *lockedShard, entryAAAA, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP);
         if (ret > 0) {
           ret = std::min(ret, ttdAAAA);
         }
@@ -397,29 +391,27 @@ time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qt, F
         }
       }
 
-      if (state && cachedState) {
-        *state = *cachedState;
+      if (cachedState && ret > 0) {
+        ptrAssign(state, *cachedState);
       }
 
       return ret > 0 ? (ret - now) : ret;
     }
-    else {
-      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;
-        }
-        return fakeTTD(entry, qname, qtype, ret, now, origTTL, refresh);
+    auto entry = getEntryUsingECSIndex(*lockedShard, now, qname, qtype, requireAuth, who, serveStale);
+    if (entry != lockedShard->d_map.end()) {
+      time_t ret = handleHit(now, *lockedShard, entry, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP);
+      if (cachedState && ret > now) {
+        ptrAssign(state, *cachedState);
       }
-      return -1;
+      return fakeTTD(entry, qname, qtype, ret, now, origTTL, refresh);
     }
+    return -1;
   }
 
   if (routingTag) {
-    auto entries = getEntries(*lockedShard, qname, qt, routingTag);
+    auto entries = getEntries(*lockedShard, qname, qtype, routingTag);
     bool found = false;
-    time_t ttd;
+    time_t ttd{};
 
     if (entries.first != entries.second) {
       OrderedTagIterator_t firstIndexIterator;
@@ -439,30 +431,28 @@ time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qt, F
 
         handleServeStaleBookkeeping(now, serveStale, firstIndexIterator);
 
-        ttd = handleHit(*lockedShard, firstIndexIterator, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP);
+        ttd = handleHit(now, *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
+        if (qtype != QType::ANY && qtype != QType::ADDR) { // normally if we have a hit, we are done
           break;
         }
       }
       if (found) {
-        if (state && cachedState) {
-          *state = *cachedState;
+        if (cachedState && ttd > now) {
+          ptrAssign(state, *cachedState);
         }
         return fakeTTD(firstIndexIterator, qname, qtype, ttd, now, origTTL, refresh);
       }
-      else {
-        return -1;
-      }
+      return -1;
     }
   }
   // Try (again) without tag
-  auto entries = getEntries(*lockedShard, qname, qt, boost::none);
+  auto entries = getEntries(*lockedShard, qname, qtype, boost::none);
 
   if (entries.first != entries.second) {
     OrderedTagIterator_t firstIndexIterator;
     bool found = false;
-    time_t ttd;
+    time_t ttd{};
 
     for (auto i = entries.first; i != entries.second; ++i) {
       firstIndexIterator = lockedShard->d_map.project<OrderedTag>(i);
@@ -480,15 +470,15 @@ time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qt, F
 
       handleServeStaleBookkeeping(now, serveStale, firstIndexIterator);
 
-      ttd = handleHit(*lockedShard, firstIndexIterator, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP);
+      ttd = handleHit(now, *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
+      if (qtype != QType::ANY && qtype != QType::ADDR) { // normally if we have a hit, we are done
         break;
       }
     }
     if (found) {
-      if (state && cachedState) {
-        *state = *cachedState;
+      if (cachedState && ttd > now) {
+        ptrAssign(state, *cachedState);
       }
       return fakeTTD(firstIndexIterator, qname, qtype, ttd, now, origTTL, refresh);
     }
@@ -539,7 +529,7 @@ 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<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, time_t ttl_time)
+void MemRecursorCache::replace(time_t now, const DNSName& qname, const QType qtype, 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, time_t ttl_time)
 {
   auto& shard = getMap(qname);
   auto lockedShard = shard.lock();
@@ -551,7 +541,7 @@ void MemRecursorCache::replace(time_t now, const DNSName& qname, const QType qt,
 
   // We only store with a tag if we have an ednsmask and the tag is available
   // We only store an ednsmask if we do not have a tag and we do have a mask.
-  auto key = std::tuple(qname, qt.getCode(), ednsmask ? routingTag : boost::none, (ednsmask && !routingTag) ? *ednsmask : Netmask());
+  auto key = std::tuple(qname, qtype.getCode(), ednsmask ? routingTag : boost::none, (ednsmask && !routingTag) ? *ednsmask : Netmask());
   bool isNew = false;
   cache_t::iterator stored = lockedShard->d_map.find(key);
   if (stored == lockedShard->d_map.end()) {
@@ -568,70 +558,70 @@ void MemRecursorCache::replace(time_t now, const DNSName& qname, const QType qt,
   if (isNew || stored->d_ttd <= now) {
     /* don't bother building an ecsIndex if we don't have any netmask-specific entries */
     if (!routingTag && ednsmask && !ednsmask->empty()) {
-      auto ecsIndexKey = std::tuple(qname, qt.getCode());
+      auto ecsIndexKey = std::tuple(qname, qtype.getCode());
       auto ecsIndex = lockedShard->d_ecsIndex.find(ecsIndexKey);
       if (ecsIndex == lockedShard->d_ecsIndex.end()) {
-        ecsIndex = lockedShard->d_ecsIndex.insert(ECSIndexEntry(qname, qt.getCode())).first;
+        ecsIndex = lockedShard->d_ecsIndex.insert(ECSIndexEntry(qname, qtype.getCode())).first;
       }
       ecsIndex->addMask(*ednsmask);
     }
   }
 
   time_t maxTTD = std::numeric_limits<time_t>::max();
-  CacheEntry ce = *stored; // this is a COPY
-  ce.d_qtype = qt.getCode();
+  CacheEntry cacheEntry = *stored; // this is a COPY
+  cacheEntry.d_qtype = qtype.getCode();
 
-  if (!isNew && !ce.shouldReplace(now, auth, state, refresh)) {
+  if (!isNew && !cacheEntry.shouldReplace(now, auth, state, refresh)) {
     return;
   }
 
-  ce.d_state = state;
+  cacheEntry.d_state = state;
 
   // refuse any attempt to *raise* the TTL of auth NS records, as it would make it possible
   // for an auth to keep a "ghost" zone alive forever, even after the delegation is gone from
   // the parent
   // BUT make sure that we CAN refresh the root
-  if (ce.d_auth && auth && qt == QType::NS && !isNew && !qname.isRoot()) {
-    maxTTD = ce.d_ttd;
+  if (cacheEntry.d_auth && auth && qtype == QType::NS && !isNew && !qname.isRoot()) {
+    maxTTD = cacheEntry.d_ttd;
   }
 
   if (auth) {
-    ce.d_auth = true;
+    cacheEntry.d_auth = true;
   }
 
-  ce.d_signatures = signatures;
-  ce.d_authorityRecs = authorityRecs;
-  ce.d_records.clear();
-  ce.d_records.reserve(content.size());
-  ce.d_authZone = authZone;
+  cacheEntry.d_signatures = signatures;
+  cacheEntry.d_authorityRecs = authorityRecs;
+  cacheEntry.d_records.clear();
+  cacheEntry.d_records.reserve(content.size());
+  cacheEntry.d_authZone = authZone;
   if (from) {
-    ce.d_from = *from;
+    cacheEntry.d_from = *from;
   }
   else {
-    ce.d_from = ComboAddress();
+    cacheEntry.d_from = ComboAddress();
   }
 
-  for (const auto& i : content) {
+  for (const auto& record : content) {
     /* Yes, we have altered the d_ttl value by adding time(nullptr) to it
        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
+    cacheEntry.d_ttd = min(maxTTD, static_cast<time_t>(record.d_ttl)); // XXX this does weird things if TTLs differ in the set
 
-    ce.d_orig_ttl = ce.d_ttd - ttl_time;
+    cacheEntry.d_orig_ttl = cacheEntry.d_ttd - ttl_time;
     // Even though we record the time the ttd was computed, there still seems to be a case where the computed
     // d_orig_ttl can wrap.
     // So santize the computed ce.d_orig_ttl to be on the safe side
-    if (ce.d_orig_ttl < SyncRes::s_minimumTTL || ce.d_orig_ttl > SyncRes::s_maxcachettl) {
-      ce.d_orig_ttl = SyncRes::s_minimumTTL;
+    if (cacheEntry.d_orig_ttl < SyncRes::s_minimumTTL || cacheEntry.d_orig_ttl > SyncRes::s_maxcachettl) {
+      cacheEntry.d_orig_ttl = SyncRes::s_minimumTTL;
     }
-    ce.d_records.push_back(i.getContent());
+    cacheEntry.d_records.push_back(record.getContent());
   }
 
   if (!isNew) {
     moveCacheItemToBack<SequencedTag>(lockedShard->d_map, stored);
   }
-  ce.d_submitted = false;
-  ce.d_servedStale = 0;
-  lockedShard->d_map.replace(stored, ce);
+  cacheEntry.d_submitted = false;
+  cacheEntry.d_servedStale = 0;
+  lockedShard->d_map.replace(stored, cacheEntry);
 }
 
 size_t MemRecursorCache::doWipeCache(const DNSName& name, bool sub, const QType qtype)
@@ -644,15 +634,15 @@ size_t MemRecursorCache::doWipeCache(const DNSName& name, bool sub, const QType
     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);
+    auto iter = range.first;
+    while (iter != range.second) {
+      if (iter->d_qtype == qtype || qtype == 0xffff) {
+        iter = idx.erase(iter);
         count++;
         shard.decEntriesCount();
       }
       else {
-        ++i;
+        ++iter;
       }
     }
 
@@ -668,17 +658,18 @@ size_t MemRecursorCache::doWipeCache(const DNSName& name, bool sub, const QType
     }
   }
   else {
-    for (auto& mc : d_maps) {
-      auto map = mc.lock();
+    for (auto& content : d_maps) {
+      auto map = content.lock();
       map->d_cachecachevalid = false;
       auto& idx = map->d_map.get<OrderedTag>();
       for (auto i = idx.lower_bound(name); i != idx.end();) {
-        if (!i->d_qname.isPartOf(name))
+        if (!i->d_qname.isPartOf(name)) {
           break;
+        }
         if (i->d_qtype == qtype || qtype == 0xffff) {
           count++;
           i = idx.erase(i);
-          mc.decEntriesCount();
+          content.decEntriesCount();
         }
         else {
           ++i;
@@ -686,8 +677,9 @@ size_t MemRecursorCache::doWipeCache(const DNSName& name, bool sub, const QType
       }
       auto& ecsIdx = map->d_ecsIndex.get<OrderedTag>();
       for (auto i = ecsIdx.lower_bound(name); i != ecsIdx.end();) {
-        if (!i->d_qname.isPartOf(name))
+        if (!i->d_qname.isPartOf(name)) {
           break;
+        }
         if (i->d_qtype == qtype || qtype == 0xffff) {
           i = ecsIdx.erase(i);
         }
@@ -710,29 +702,28 @@ bool MemRecursorCache::doAgeCache(time_t now, const DNSName& name, const QType q
     return false;
   }
 
-  CacheEntry ce = *iter;
-  if (ce.d_ttd < now) {
+  CacheEntry cacheEntry = *iter;
+  if (cacheEntry.d_ttd < now) {
     return false; // would be dead anyhow
   }
 
-  uint32_t maxTTL = static_cast<uint32_t>(ce.d_ttd - now);
+  auto maxTTL = static_cast<uint32_t>(cacheEntry.d_ttd - now);
   if (maxTTL > newTTL) {
     lockedShard->d_cachecachevalid = false;
 
     time_t newTTD = now + newTTL;
 
-    if (ce.d_ttd > newTTD) {
-      ce.d_ttd = newTTD;
-      lockedShard->d_map.replace(iter, ce);
+    if (cacheEntry.d_ttd > newTTD) {
+      cacheEntry.d_ttd = newTTD;
+      lockedShard->d_map.replace(iter, cacheEntry);
     }
     return true;
   }
   return false;
 }
 
-bool MemRecursorCache::updateValidationStatus(time_t now, const DNSName& qname, const QType qt, const ComboAddress& who, const OptTag& routingTag, bool requireAuth, vState newState, boost::optional<time_t> capTTD)
+bool MemRecursorCache::updateValidationStatus(time_t now, const DNSName& qname, const QType qtype, const ComboAddress& who, const OptTag& routingTag, bool requireAuth, vState newState, boost::optional<time_t> capTTD)
 {
-  uint16_t qtype = qt.getCode();
   if (qtype == QType::ANY) {
     throw std::runtime_error("Trying to update the DNSSEC validation status of all (via ANY) records for " + qname.toLogString());
   }
@@ -740,8 +731,8 @@ bool MemRecursorCache::updateValidationStatus(time_t now, const DNSName& qname,
     throw std::runtime_error("Trying to update the DNSSEC validation status of several (via ADDR) records for " + qname.toLogString());
   }
 
-  auto& mc = getMap(qname);
-  auto map = mc.lock();
+  auto& content = getMap(qname);
+  auto map = content.lock();
 
   bool updated = false;
   if (!map->d_ecsIndex.empty() && !routingTag) {
@@ -757,7 +748,7 @@ bool MemRecursorCache::updateValidationStatus(time_t now, const DNSName& qname,
     return true;
   }
 
-  auto entries = getEntries(*map, qname, qt, routingTag);
+  auto entries = getEntries(*map, qname, qtype, routingTag);
 
   for (auto i = entries.first; i != entries.second; ++i) {
     auto firstIndexIterator = map->d_map.project<OrderedTag>(i);
@@ -778,19 +769,19 @@ bool MemRecursorCache::updateValidationStatus(time_t now, const DNSName& qname,
   return updated;
 }
 
-uint64_t MemRecursorCache::doDump(int fd, size_t maxCacheEntries)
+uint64_t MemRecursorCache::doDump(int fileDesc, size_t maxCacheEntries)
 {
-  int newfd = dup(fd);
+  int newfd = dup(fileDesc);
   if (newfd == -1) {
     return 0;
   }
-  auto fp = std::unique_ptr<FILE, int (*)(FILE*)>(fdopen(newfd, "w"), fclose);
-  if (!fp) { // dup probably failed
+  auto filePtr = std::unique_ptr<FILE, int (*)(FILE*)>(fdopen(newfd, "w"), fclose);
+  if (!filePtr) { // dup probably failed
     close(newfd);
     return 0;
   }
 
-  fprintf(fp.get(), "; main record cache dump follows\n;\n");
+  fprintf(filePtr.get(), "; main record cache dump follows\n;\n");
   uint64_t count = 0;
   size_t shardNumber = 0;
   size_t min = std::numeric_limits<size_t>::max();
@@ -798,41 +789,41 @@ uint64_t MemRecursorCache::doDump(int fd, size_t maxCacheEntries)
   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);
+    fprintf(filePtr.get(), "; record cache shard %zu; size %zu\n", shardNumber, shardSize);
     min = std::min(min, shardSize);
     max = std::max(max, shardSize);
     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) {
+    for (const auto& recordSet : sidx) {
+      for (const auto& record : recordSet.d_records) {
         count++;
         try {
-          fprintf(fp.get(), "%s %" PRIu32 " %" PRId64 " IN %s %s ; (%s) auth=%i zone=%s from=%s nm=%s rtag=%s ss=%hd\n", i.d_qname.toString().c_str(), i.d_orig_ttl, static_cast<int64_t>(i.d_ttd - now), i.d_qtype.toString().c_str(), j->getZoneRepresentation().c_str(), vStateToString(i.d_state).c_str(), i.d_auth, i.d_authZone.toLogString().c_str(), i.d_from.toString().c_str(), i.d_netmask.empty() ? "" : i.d_netmask.toString().c_str(), !i.d_rtag ? "" : i.d_rtag.get().c_str(), i.d_servedStale);
+          fprintf(filePtr.get(), "%s %" PRIu32 " %" PRId64 " IN %s %s ; (%s) auth=%i zone=%s from=%s nm=%s rtag=%s ss=%hd\n", recordSet.d_qname.toString().c_str(), recordSet.d_orig_ttl, static_cast<int64_t>(recordSet.d_ttd - now), recordSet.d_qtype.toString().c_str(), record->getZoneRepresentation().c_str(), vStateToString(recordSet.d_state).c_str(), static_cast<int>(recordSet.d_auth), recordSet.d_authZone.toLogString().c_str(), recordSet.d_from.toString().c_str(), recordSet.d_netmask.empty() ? "" : recordSet.d_netmask.toString().c_str(), !recordSet.d_rtag ? "" : recordSet.d_rtag.get().c_str(), recordSet.d_servedStale);
         }
         catch (...) {
-          fprintf(fp.get(), "; error printing '%s'\n", i.d_qname.empty() ? "EMPTY" : i.d_qname.toString().c_str());
+          fprintf(filePtr.get(), "; error printing '%s'\n", recordSet.d_qname.empty() ? "EMPTY" : recordSet.d_qname.toString().c_str());
         }
       }
-      for (const auto& sig : i.d_signatures) {
+      for (const auto& sig : recordSet.d_signatures) {
         count++;
         try {
-          fprintf(fp.get(), "%s %" PRIu32 " %" PRId64 " IN RRSIG %s ; %s\n", i.d_qname.toString().c_str(), i.d_orig_ttl, static_cast<int64_t>(i.d_ttd - now), sig->getZoneRepresentation().c_str(), i.d_netmask.empty() ? "" : i.d_netmask.toString().c_str());
+          fprintf(filePtr.get(), "%s %" PRIu32 " %" PRId64 " IN RRSIG %s ; %s\n", recordSet.d_qname.toString().c_str(), recordSet.d_orig_ttl, static_cast<int64_t>(recordSet.d_ttd - now), sig->getZoneRepresentation().c_str(), recordSet.d_netmask.empty() ? "" : recordSet.d_netmask.toString().c_str());
         }
         catch (...) {
-          fprintf(fp.get(), "; error printing '%s'\n", i.d_qname.empty() ? "EMPTY" : i.d_qname.toString().c_str());
+          fprintf(filePtr.get(), "; error printing '%s'\n", recordSet.d_qname.empty() ? "EMPTY" : recordSet.d_qname.toString().c_str());
         }
       }
     }
   }
-  fprintf(fp.get(), "; main record cache size: %zu/%zu shards: %zu min/max shard size: %zu/%zu\n", size(), maxCacheEntries, d_maps.size(), min, max);
+  fprintf(filePtr.get(), "; main record cache size: %zu/%zu shards: %zu min/max shard size: %zu/%zu\n", size(), maxCacheEntries, d_maps.size(), min, max);
   return count;
 }
 
 void MemRecursorCache::doPrune(time_t now, size_t keep)
 {
   size_t cacheSize = size();
-  pruneMutexCollectionsVector<SequencedTag>(now, *this, d_maps, keep, cacheSize);
+  pruneMutexCollectionsVector<SequencedTag>(now, d_maps, keep, cacheSize);
 }
 
 namespace boost
index ccbcad2b507c96296cd4e61f054f081b82e576c6..360e97958c681869b38a97b0f02ed3720ddab3d9 100644 (file)
@@ -54,43 +54,61 @@ public:
   // The time a stale cache entry is extended
   static constexpr uint32_t s_serveStaleExtensionPeriod = 30;
 
-  size_t size() const;
-  size_t bytes();
-  pair<uint64_t, uint64_t> stats();
-  size_t ecsIndexSize();
+  [[nodiscard]] size_t size() const;
+  [[nodiscard]] size_t bytes();
+  [[nodiscard]] pair<uint64_t, uint64_t> stats();
+  [[nodiscard]] size_t ecsIndexSize();
 
-  typedef boost::optional<std::string> OptTag;
+  using OptTag = boost::optional<std::string>;
 
-  typedef uint8_t Flags;
+  using Flags = uint8_t;
   static constexpr Flags None = 0;
   static constexpr Flags RequireAuth = 1 << 0;
   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<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);
+  [[nodiscard]] time_t get(time_t, const DNSName& qname, QType qtype, 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<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, time_t ttl_time = time(nullptr));
+  void replace(time_t, const DNSName& qname, QType qtype, 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, time_t ttl_time = time(nullptr));
 
   void doPrune(time_t now, size_t keep);
-  uint64_t doDump(int fd, size_t maxCacheEntries);
+  uint64_t doDump(int fileDesc, size_t maxCacheEntries);
 
   size_t doWipeCache(const DNSName& name, bool sub, QType qtype = 0xffff);
   bool doAgeCache(time_t now, const DNSName& name, QType qtype, uint32_t newTTL);
-  bool updateValidationStatus(time_t now, const DNSName& qname, QType qt, const ComboAddress& who, const OptTag& routingTag, bool requireAuth, vState newState, boost::optional<time_t> capTTD);
-
-  pdns::stat_t cacheHits{0}, cacheMisses{0};
+  bool updateValidationStatus(time_t now, const DNSName& qname, QType qtype, const ComboAddress& who, const OptTag& routingTag, bool requireAuth, vState newState, boost::optional<time_t> capTTD);
 
   static void resetStaticsForTests();
 
+  [[nodiscard]] auto getCacheHits() const
+  {
+    return cacheHits.load();
+  }
+  [[nodiscard]] auto getCacheMisses() const
+  {
+    return cacheMisses.load();
+  }
+
+  void incCacheHits()
+  {
+    ++cacheHits;
+  }
+  void incCacheMisses()
+  {
+    ++cacheMisses;
+  }
+
 private:
+  pdns::stat_t cacheHits{0}, cacheMisses{0};
+
   struct CacheEntry
   {
     CacheEntry(const std::tuple<DNSName, QType, OptTag, Netmask>& key, bool auth) :
-      d_qname(std::get<0>(key)), d_netmask(std::get<3>(key).getNormalized()), d_rtag(std::get<2>(key)), d_state(vState::Indeterminate), d_ttd(0), d_orig_ttl{0}, d_servedStale(0), d_qtype(std::get<1>(key)), d_auth(auth), d_submitted(false)
+      d_qname(std::get<0>(key)), d_netmask(std::get<3>(key).getNormalized()), d_rtag(std::get<2>(key)), d_qtype(std::get<1>(key)), d_auth(auth)
     {
     }
 
-    typedef vector<std::shared_ptr<const DNSRecordContent>> records_t;
+    using records_t = vector<std::shared_ptr<const DNSRecordContent>>;
 
     bool isStale(time_t now) const
     {
@@ -98,9 +116,7 @@ private:
       if (s_maxServedStaleExtensions > 0) {
         return d_ttd + static_cast<time_t>(s_maxServedStaleExtensions) * std::min(s_serveStaleExtensionPeriod, d_orig_ttl) < now;
       }
-      else {
-        return d_ttd < now;
-      }
+      return d_ttd < now;
     }
 
     bool isEntryUsable(time_t now, bool serveStale) const
@@ -119,13 +135,13 @@ private:
     ComboAddress d_from;
     Netmask d_netmask;
     OptTag d_rtag;
-    mutable vState d_state;
-    mutable time_t d_ttd;
-    uint32_t d_orig_ttl;
-    mutable uint16_t d_servedStale;
+    mutable vState d_state{vState::Indeterminate};
+    mutable time_t d_ttd{0};
+    uint32_t d_orig_ttl{0};
+    mutable uint16_t d_servedStale{0};
     QType d_qtype;
     bool d_auth;
-    mutable bool d_submitted; // whether this entry has been queued for refetch
+    mutable bool d_submitted{false}; // whether this entry has been queued for refetch
   };
 
   /* The ECS Index (d_ecsIndex) keeps track of whether there is any ECS-specific
@@ -141,32 +157,32 @@ private:
   class ECSIndexEntry
   {
   public:
-    ECSIndexEntry(const DNSName& qname, QType qtype) :
-      d_nmt(), d_qname(qname), d_qtype(qtype)
+    ECSIndexEntry(DNSName qname, QType qtype) :
+      d_qname(std::move(qname)), d_qtype(qtype)
     {
     }
 
-    Netmask lookupBestMatch(const ComboAddress& addr) const
+    [[nodiscard]] Netmask lookupBestMatch(const ComboAddress& addr) const
     {
-      const auto best = d_nmt.lookup(addr);
+      const auto* best = d_nmt.lookup(addr);
       if (best != nullptr) {
         return best->first;
       }
 
-      return Netmask();
+      return {};
     }
 
-    void addMask(const Netmask& nm) const
+    void addMask(const Netmask& netmask) const
     {
-      d_nmt.insert(nm).second = true;
+      d_nmt.insert(netmask).second = true;
     }
 
-    void removeNetmask(const Netmask& nm) const
+    void removeNetmask(const Netmask& netmask) const
     {
-      d_nmt.erase(nm);
+      d_nmt.erase(netmask);
     }
 
-    bool isEmpty() const
+    [[nodiscard]] bool isEmpty() const
     {
       return d_nmt.empty();
     }
@@ -189,7 +205,7 @@ private:
   {
   };
 
-  typedef multi_index_container<
+  using cache_t = multi_index_container<
     CacheEntry,
     indexed_by<
       ordered_unique<tag<OrderedTag>,
@@ -199,19 +215,18 @@ private:
                        member<CacheEntry, QType, &CacheEntry::d_qtype>,
                        member<CacheEntry, OptTag, &CacheEntry::d_rtag>,
                        member<CacheEntry, Netmask, &CacheEntry::d_netmask>>,
-                     composite_key_compare<CanonDNSNameCompare, std::less<QType>, std::less<OptTag>, std::less<Netmask>>>,
+                     composite_key_compare<CanonDNSNameCompare, std::less<>, std::less<>, std::less<>>>,
       sequenced<tag<SequencedTag>>,
       hashed_non_unique<tag<NameAndRTagOnlyHashedTag>,
                         composite_key<
                           CacheEntry,
                           member<CacheEntry, DNSName, &CacheEntry::d_qname>,
-                          member<CacheEntry, OptTag, &CacheEntry::d_rtag>>>>>
-    cache_t;
+                          member<CacheEntry, OptTag, &CacheEntry::d_rtag>>>>>;
 
-  typedef MemRecursorCache::cache_t::index<MemRecursorCache::OrderedTag>::type::iterator OrderedTagIterator_t;
-  typedef MemRecursorCache::cache_t::index<MemRecursorCache::NameAndRTagOnlyHashedTag>::type::iterator NameAndRTagOnlyHashedTagIterator_t;
+  using OrderedTagIterator_t = MemRecursorCache::cache_t::index<MemRecursorCache::OrderedTag>::type::iterator;
+  using NameAndRTagOnlyHashedTagIterator_t = MemRecursorCache::cache_t::index<MemRecursorCache::NameAndRTagOnlyHashedTag>::type::iterator;
 
-  typedef multi_index_container<
+  using ecsIndex_t = multi_index_container<
     ECSIndexEntry,
     indexed_by<
       hashed_unique<tag<HashedTag>,
@@ -224,16 +239,19 @@ private:
                        ECSIndexEntry,
                        member<ECSIndexEntry, DNSName, &ECSIndexEntry::d_qname>,
                        member<ECSIndexEntry, QType, &ECSIndexEntry::d_qtype>>,
-                     composite_key_compare<CanonDNSNameCompare, std::less<QType>>>>>
-    ecsIndex_t;
+                     composite_key_compare<CanonDNSNameCompare, std::less<>>>>>;
 
-  typedef std::pair<NameAndRTagOnlyHashedTagIterator_t, NameAndRTagOnlyHashedTagIterator_t> Entries;
+  using Entries = std::pair<NameAndRTagOnlyHashedTagIterator_t, NameAndRTagOnlyHashedTagIterator_t>;
 
   struct MapCombo
   {
-    MapCombo() {}
+    MapCombo() = default;
+    ~MapCombo() = default;
     MapCombo(const MapCombo&) = delete;
     MapCombo& operator=(const MapCombo&) = delete;
+    MapCombo(MapCombo&&) = delete;
+    MapCombo& operator=(MapCombo&&) = delete;
+
     struct LockedContent
     {
       cache_t d_map;
@@ -249,6 +267,22 @@ private:
       {
         d_cachecachevalid = false;
       }
+
+      void preRemoval(const CacheEntry& entry)
+      {
+        if (entry.d_netmask.empty()) {
+          return;
+        }
+
+        auto key = std::tie(entry.d_qname, entry.d_qtype);
+        auto ecsIndexEntry = d_ecsIndex.find(key);
+        if (ecsIndexEntry != d_ecsIndex.end()) {
+          ecsIndexEntry->removeNetmask(entry.d_netmask);
+          if (ecsIndexEntry->isEmpty()) {
+            d_ecsIndex.erase(ecsIndexEntry);
+          }
+        }
+      }
     };
 
     LockGuardedTryHolder<LockedContent> lock()
@@ -295,30 +329,13 @@ private:
 
   static time_t fakeTTD(OrderedTagIterator_t& entry, const DNSName& qname, QType qtype, time_t ret, time_t now, uint32_t origTTL, bool refresh);
 
-  bool entryMatches(OrderedTagIterator_t& entry, QType qt, bool requireAuth, const ComboAddress& who);
-  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<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&);
+  static bool entryMatches(OrderedTagIterator_t& entry, QType qtype, bool requireAuth, const ComboAddress& who);
+  static Entries getEntries(MapCombo::LockedContent& map, const DNSName& qname, QType qtype, const OptTag& rtag);
+  static cache_t::const_iterator getEntryUsingECSIndex(MapCombo::LockedContent& map, time_t now, const DNSName& qname, QType qtype, bool requireAuth, const ComboAddress& who, bool serveStale);
 
-public:
-  void preRemoval(MapCombo::LockedContent& map, const CacheEntry& entry)
-  {
-    if (entry.d_netmask.empty()) {
-      return;
-    }
-
-    auto key = std::tie(entry.d_qname, entry.d_qtype);
-    auto ecsIndexEntry = map.d_ecsIndex.find(key);
-    if (ecsIndexEntry != map.d_ecsIndex.end()) {
-      ecsIndexEntry->removeNetmask(entry.d_netmask);
-      if (ecsIndexEntry->isEmpty()) {
-        map.d_ecsIndex.erase(ecsIndexEntry);
-      }
-    }
-  }
+  static time_t handleHit(time_t now, 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);
+  static void updateStaleEntry(time_t now, OrderedTagIterator_t& entry);
+  static void handleServeStaleBookkeeping(time_t, bool, OrderedTagIterator_t&);
 };
 
 namespace boost
index dd82ee3d034d7e33f1b91448b3267d160697056d..12770b636d51a4fdb4793bf3b05c43e80b14dc1a 100644 (file)
@@ -176,7 +176,7 @@ static SyncRes::AuthDomain makeSOAAndNSNodes(DNSRecord& dr, T content)
   dr.d_place = DNSResourceRecord::ANSWER;
   dr.d_ttl = 86400;
   dr.d_type = QType::SOA;
-  dr.setContent(DNSRecordContent::mastermake(QType::SOA, 1, "localhost. root 1 604800 86400 2419200 604800"));
+  dr.setContent(DNSRecordContent::make(QType::SOA, 1, "localhost. root 1 604800 86400 2419200 604800"));
 
   SyncRes::AuthDomain ad;
   ad.d_rdForward = false;
@@ -229,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.setContent(DNSRecordContent::mastermake(recType, QClass::IN, address.toStringNoInterface()));
+  dr.setContent(DNSRecordContent::make(recType, QClass::IN, address.toStringNoInterface()));
   entry->second.d_records.insert(dr);
 }
 
@@ -247,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.setContent(DNSRecordContent::mastermake(QType::PTR, 1, DNSName(canonicalHostname).toString()));
+  dr.setContent(DNSRecordContent::make(QType::PTR, 1, DNSName(canonicalHostname).toString()));
   ad.d_records.insert(dr);
 
   addToDomainMap(newMap, std::move(ad), dr.d_name, log, false, true);
index 5b603c4da4dbc10232232fb3e6442183a5011ffe..8e09f19cbfd9447df86e19bedbeaf6d521aefaa5 100644 (file)
@@ -62,16 +62,16 @@ bool primeHints(time_t now)
   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)
+static void convertServersForAD(const std::string& zone, const std::string& input, SyncRes::AuthDomain& authDomain, const char* sepa, Logr::log_t log, bool verbose = true)
 {
   vector<string> servers;
   stringtok(servers, input, sepa);
-  ad.d_servers.clear();
+  authDomain.d_servers.clear();
 
   vector<string> addresses;
-  for (auto server = servers.begin(); server != servers.end(); ++server) {
-    ComboAddress addr = parseIPAndPort(*server, 53);
-    ad.d_servers.push_back(addr);
+  for (auto& server : servers) {
+    ComboAddress addr = parseIPAndPort(server, 53);
+    authDomain.d_servers.push_back(addr);
     if (verbose) {
       addresses.push_back(addr.toStringWithPort());
     }
@@ -79,24 +79,24 @@ static void convertServersForAD(const std::string& zone, const std::string& inpu
   if (verbose) {
     if (!g_slogStructured) {
       g_log << Logger::Info << "Redirecting queries for zone '" << zone << "' ";
-      if (ad.d_rdForward) {
+      if (authDomain.d_rdForward) {
         g_log << "with recursion ";
       }
       g_log << "to: ";
       bool first = true;
-      for (const auto& a : addresses) {
+      for (const auto& address : addresses) {
         if (!first) {
           g_log << ", ";
         }
         else {
           first = false;
         }
-        g_log << a;
+        g_log << address;
       }
       g_log << endl;
     }
     else {
-      log->info(Logr::Info, "Redirecting queries", "zone", Logging::Loggable(zone), "recursion", Logging::Loggable(ad.d_rdForward), "addresses", Logging::IterLoggable(addresses.begin(), addresses.end()));
+      log->info(Logr::Info, "Redirecting queries", "zone", Logging::Loggable(zone), "recursion", Logging::Loggable(authDomain.d_rdForward), "addresses", Logging::IterLoggable(addresses.begin(), addresses.end()));
     }
   }
 }
@@ -104,7 +104,7 @@ static void convertServersForAD(const std::string& zone, const std::string& inpu
 static void* pleaseUseNewSDomainsMap(std::shared_ptr<SyncRes::domainmap_t> newmap)
 {
   SyncRes::setDomainMap(std::move(newmap));
-  return 0;
+  return nullptr;
 }
 
 string reloadZoneConfiguration(bool yaml)
index c99480fea3150136b1a60e596ee144084eba4661..9ebae34c21741bc1c72999dd3dad14f55c3e31f4 100644 (file)
@@ -389,12 +389,10 @@ void RPZIXFRTracker(const std::vector<ComboAddress>& primaries, const boost::opt
 {
   setThreadName("rec/rpzixfr");
   bool isPreloaded = sr != nullptr;
-  auto luaconfsLocal = g_luaconfs.getLocal();
-
   auto logger = g_slog->withName("rpz");
 
   /* we can _never_ modify this zone directly, we need to do a full copy then replace the existing zone */
-  std::shared_ptr<DNSFilterEngine::Zone> oldZone = luaconfsLocal->dfe.getZone(zoneIdx);
+  std::shared_ptr<DNSFilterEngine::Zone> oldZone = g_luaconfs.getLocal()->dfe.getZone(zoneIdx);
   if (!oldZone) {
     SLOG(g_log << Logger::Error << "Unable to retrieve RPZ zone with index " << zoneIdx << " from the configuration, exiting" << endl,
          logger->error(Logr::Error, "Unable to retrieve RPZ zone from configuration", "index", Logging::Loggable(zoneIdx)));
@@ -444,7 +442,8 @@ void RPZIXFRTracker(const std::vector<ComboAddress>& primaries, const boost::opt
         incRPZFailedTransfers(polName);
       }
     }
-
+    // Release newZone before (long) sleep to reduce memory usage
+    newZone = nullptr;
     if (!sr) {
       sleep(refresh);
     }
@@ -453,6 +452,8 @@ void RPZIXFRTracker(const std::vector<ComboAddress>& primaries, const boost::opt
   bool skipRefreshDelay = isPreloaded;
 
   for (;;) {
+    // Don't hold on to oldZone, it well be re-assigned after sleep in the try block
+    oldZone = nullptr;
     DNSRecord dr;
     dr.setContent(sr);
 
@@ -462,6 +463,7 @@ void RPZIXFRTracker(const std::vector<ComboAddress>& primaries, const boost::opt
     else {
       sleep(refresh);
     }
+    auto luaconfsLocal = g_luaconfs.getLocal();
 
     if (luaconfsLocal->generation != configGeneration) {
       /* the configuration has been reloaded, meaning that a new thread
@@ -508,7 +510,7 @@ void RPZIXFRTracker(const std::vector<ComboAddress>& primaries, const boost::opt
 
       if (luaconfsLocal->generation != configGeneration) {
         SLOG(g_log << Logger::Info << "A more recent configuration has been found, stopping the existing RPZ update thread for " << zoneName << endl,
-             logger->info(Logr::Info, "A more recent configuration has been found, stopping the existing RPZ update thread"))
+             logger->info(Logr::Info, "A more recent configuration has been found, stopping the existing RPZ update thread"));
         return;
       }
       oldZone = luaconfsLocal->dfe.getZone(zoneIdx);
index 9b8761d4ab91fabbeef9f23503d40b1ef7430b9e..9c165cb82179ba16d0674cc6a88b194915b79310 100644 (file)
@@ -9,7 +9,7 @@
 #include "validate-recursor.hh"
 #include "secpoll.hh"
 
-#include <stdint.h>
+#include <cstdint>
 #ifndef PACKAGEVERSION
 #define PACKAGEVERSION getPDNSVersion()
 #endif
@@ -19,49 +19,54 @@ string g_security_message;
 
 void doSecPoll(time_t* last_secpoll, Logr::log_t log)
 {
-  if (::arg()["security-poll-suffix"].empty())
+  if (::arg()["security-poll-suffix"].empty()) {
     return;
+  }
 
   string pkgv(PACKAGEVERSION);
-  struct timeval now;
-  gettimeofday(&now, 0);
+  struct timeval now
+  {
+  };
+  Utility::gettimeofday(&now);
 
   /* update last_secpoll right now, even if it fails
      we don't want to retry right away and hammer the server */
   *last_secpoll = now.tv_sec;
 
-  SyncRes sr(now);
+  SyncRes resolver(now);
   if (g_dnssecmode != DNSSECMode::Off) {
-    sr.setDoDNSSEC(true);
-    sr.setDNSSECValidationRequested(true);
+    resolver.setDoDNSSEC(true);
+    resolver.setDNSSECValidationRequested(true);
   }
-  sr.setId("SecPoll");
+  resolver.setId("SecPoll");
 
   vector<DNSRecord> ret;
 
   string version = "recursor-" + pkgv;
   string qstring(version.substr(0, 63) + ".security-status." + ::arg()["security-poll-suffix"]);
 
-  if (*qstring.rbegin() != '.')
+  if (*qstring.rbegin() != '.') {
     qstring += '.';
+  }
 
   boost::replace_all(qstring, "+", "_");
   boost::replace_all(qstring, "~", "_");
 
   vState state = vState::Indeterminate;
   DNSName query(qstring);
-  int res = sr.beginResolve(query, QType(QType::TXT), 1, ret);
+  int res = resolver.beginResolve(query, QType(QType::TXT), 1, ret);
 
-  if (g_dnssecmode != DNSSECMode::Off && res) {
-    state = sr.getValidationState();
+  if (g_dnssecmode != DNSSECMode::Off && res != 0) {
+    state = resolver.getValidationState();
   }
 
   auto vlog = log->withValues("version", Logging::Loggable(pkgv), "query", Logging::Loggable(query));
   if (vStateIsBogus(state)) {
     SLOG(g_log << Logger::Error << "Failed to retrieve security status update for '" + pkgv + "' on '" << query << "', DNSSEC validation result was Bogus!" << endl,
          vlog->info(Logr::Error, "Failed to retrieve security status update", "validationResult", Logging::Loggable(vStateToString(state))));
-    if (g_security_status == 1) // If we were OK, go to unknown
+    if (g_security_status == 1) // If we were OK, go to unknown
       g_security_status = 0;
+    }
     return;
   }
 
@@ -72,7 +77,7 @@ void doSecPoll(time_t* last_secpoll, Logr::log_t log)
   }
 
   string security_message;
-  int security_status = g_security_status;
+  int security_status = static_cast<int>(g_security_status);
 
   try {
     processSecPoll(res, ret, security_status, security_message);
index 511305930a28bbc990203473a323109751dc57a7..2e58343bf4fd0ccc06c9772b36d4f6735576aab6 100644 (file)
@@ -200,7 +200,10 @@ static void possiblyConvertACLFile(const string& includeDir, const string& apiDi
   if (rename(tmpfilename.c_str(), yamlfilename.c_str()) != 0) {
     int err = errno;
     log->error(Logr::Error, err, "Rename failed", "file", Logging::Loggable(tmpfilename), "to", Logging::Loggable(yamlfilename));
-    rename((path + ".converted").c_str(), path.c_str());
+    if (rename((path + ".converted").c_str(), path.c_str()) != 0) {
+      err = errno;
+      log->error(Logr::Error, err, "Rename failed", "file", Logging::Loggable(path + ".converted"), "to", Logging::Loggable(path));
+    }
     throw runtime_error("YAML Conversion");
   }
   log->info(Logr::Notice, "Converted to YAML", "file", Logging::Loggable(path), "to", Logging::Loggable(yamlfilename));
@@ -515,7 +518,7 @@ static void processLine(const std::string& arg, FieldMap& map, bool mainFile)
   ::rust::String section;
   ::rust::String fieldname;
   ::rust::String type_name;
-  pdns::rust::settings::rec::Value rustvalue;
+  pdns::rust::settings::rec::Value rustvalue = {false, 0, 0.0, "", {}, {}, {}};
   if (pdns::settings::rec::oldKVToBridgeStruct(var, val, section, fieldname, type_name, rustvalue)) {
     auto overriding = !mainFile && !incremental && !simpleRustType(type_name);
     auto [existing, inserted] = map.emplace(std::pair{std::pair{section, fieldname}, pdns::rust::settings::rec::OldStyle{section, fieldname, var, type_name, rustvalue, overriding}});
@@ -615,8 +618,7 @@ std::string pdns::settings::rec::defaultsToYaml()
     ::rust::String section;
     ::rust::String fieldname;
     ::rust::String type_name;
-    pdns::rust::settings::rec::Value rustvalue;
-
+    pdns::rust::settings::rec::Value rustvalue{false, 0, 0.0, "", {}, {}, {}};
     string name = var;
     string val = arg().getDefault(var);
     if (pdns::settings::rec::oldKVToBridgeStruct(name, val, section, fieldname, type_name, rustvalue)) {
index e59cb5d1dba817c646b1abf4136edf366eb03f00..72cf42d4af99f8968ea099ce8a53707d49049950 100644 (file)
@@ -101,8 +101,7 @@ After processing ``extra.yml`` the value will be set to the empty sequence, as e
            - '::2'
 
    The result will *not* be a a single forward with two IP addresses, but two entries for ``example.net``.
-   It depends on the specific setting how the sequence is processed further.
-   In the future we might add a check for this case.
+   It depends on the specific setting how the sequence is processed and interpreted further.
 
 Socket Address
 ^^^^^^^^^^^^^^
index 14fb0fe35198f0e76d050d0e488d348b5c18318a..a4778bdb0897ba5c31895954403f78ff30871c80 100644 (file)
@@ -976,12 +976,13 @@ An entry called 'server1.home' will be stored as 'server1.home', regardless of t
         'name' : 'extended_resolution_errors',
         'section' : 'recursor',
         'type' : LType.Bool,
-        'default' : 'false',
+        'default' : 'true',
         'help' : 'If set, send an EDNS Extended Error extension on resolution failures, like DNSSEC validation errors',
         'doc' : '''
 If set, the recursor will add an EDNS Extended Error (:rfc:`8914`) to responses when resolution failed, like DNSSEC validation errors, explaining the reason it failed. This setting is not needed to allow setting custom error codes from Lua or from a RPZ hit.
  ''',
-    'versionadded': '4.5.0'
+        'versionadded': '4.5.0',
+        'versionchanged': ('5.0.0', 'Default changed to enabled, previously it was disabled.'),
     },
     {
         'name' : 'forward_zones',
@@ -1454,7 +1455,7 @@ Maximum number of Packet Cache entries. Sharded and shared by all threads since
     },
     {
         'name' : 'max_qperq',
-        'section' : 'recursor',
+        'section' : 'outgoing',
         'type' : LType.Uint64,
         'default' : '60',
         'help' : 'Maximum outgoing queries per query',
@@ -1467,7 +1468,7 @@ at a minimum to allow for the extra queries qname-minimization generates when th
     },
     {
         'name' : 'max_ns_address_qperq',
-        'section' : 'recursor',
+        'section' : 'outgoing',
         'type' : LType.Uint64,
         'default' : '10',
         'help' : 'Maximum outgoing NS address queries per query',
@@ -1485,7 +1486,7 @@ number lower than 5.
     },
     {
         'name' : 'max_ns_per_resolve',
-        'section' : 'recursor',
+        'section' : 'outgoing',
         'type' : LType.Uint64,
         'default' : '13',
         'help' : 'Maximum number of NS records to consider to resolve a name, 0 is no limit',
@@ -1755,7 +1756,7 @@ Number of milliseconds to wait for a remote authoritative server to respond.
     },
     {
         'name' : 'non_resolving_ns_max_fails',
-        'section' : 'recursor',
+        'section' : 'outgoing',
         'type' : LType.Uint64,
         'default' : '5',
         'help' : 'Number of failed address resolves of a nameserver to start throttling it, 0 is disabled',
@@ -1767,7 +1768,7 @@ Nameservers matching :ref:`setting-dont-throttle-names` will not be throttled.
     },
     {
         'name' : 'non_resolving_ns_throttle_time',
-        'section' : 'recursor',
+        'section' : 'outgoing',
         'type' : LType.Uint64,
         'default' : '60',
         'help' : 'Number of seconds to throttle a nameserver with a name failing to resolve',
@@ -1810,14 +1811,15 @@ without consulting authoritative servers.
         'name' : 'nsec3_max_iterations',
         'section' : 'dnssec',
         'type' : LType.Uint64,
-        'default' : '150',
+        'default' : '50',
         'help' : 'Maximum number of iterations allowed for an NSEC3 record',
         'doc' : '''
 Maximum number of iterations allowed for an NSEC3 record.
-If an answer containing an NSEC3 record with more iterations is received, its DNSSEC validation status is treated as Insecure.
+If an answer containing an NSEC3 record with more iterations is received, its DNSSEC validation status is treated as ``Insecure``.
  ''',
         'versionadded': '4.1.0',
-        'versionchanged': ('4.5.2', 'Default is now 150, was 2500 before.')
+        'versionchanged': [('4.5.2', 'Default is now 150, was 2500 before.'),
+                           ('5.0.0', 'Default is now 50, was 150 before.')]
     },
     {
         'name' : 'ttl',
@@ -2160,7 +2162,7 @@ See :ref:`serve-stale` for a description of the Serve Stale mechanism.
     },
     {
         'name' : 'server_down_max_fails',
-        'section' : 'recursor',
+        'section' : 'outgoing',
         'type' : LType.Uint64,
         'default' : '64',
         'help' : 'Maximum number of consecutive timeouts (and unreachables) to mark a server as down ( 0 => disabled )',
@@ -2172,7 +2174,7 @@ Even a single response packet will drop the block.
     },
     {
         'name' : 'server_down_throttle_time',
-        'section' : 'recursor',
+        'section' : 'outgoing',
         'type' : LType.Uint64,
         'default' : '60',
         'help' : 'Number of seconds to throttle all queries to a server after being marked as down',
@@ -2182,7 +2184,7 @@ Throttle a server that has failed to respond :ref:`setting-server-down-max-fails
     },
     {
         'name' : 'bypass_server_throttling_probability',
-        'section' : 'recursor',
+        'section' : 'outgoing',
         'type' : LType.Uint64,
         'default' : '25',
         'help' : 'Determines the probability of a server marked down to be used anyway',
@@ -2895,7 +2897,7 @@ Note that this option only applies to credentials stored in the configuration as
         'default' : 'normal',
         'help' : 'Amount of logging in the webserver (none, normal, detailed)',
         'doc' : '''
-One of ``one``, ``normal``, ``detailed``.
+One of ``none``, ``normal``, ``detailed``.
 The amount of logging the webserver must do. 'none' means no useful webserver information will be logged.
 When set to 'normal', the webserver will log a line per request that should be familiar::
 
index 8300e1c19eaed53b100e05fa2bfe1faa54ea1a93..9f2964fffb823b516a6def96b5c362a836d8210c 100644 (file)
@@ -879,7 +879,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.setContent(DNSRecordContent::mastermake(ans.first, qclass, ans.second));
+      dr.setContent(DNSRecordContent::make(ans.first, qclass, ans.second));
       ret.push_back(dr);
     }
   }
@@ -2327,7 +2327,7 @@ void SyncRes::getBestNSFromCache(const DNSName& qname, const QType qtype, vector
         auto insertionPair = beenthere.insert(std::move(answer));
         if (!insertionPair.second) {
           brokeloop = true;
-          LOG(prefix << qname << ": We have NS in cache for '" << subdomain << "' but part of LOOP (already seen " << answer.qname << ")! Trying less specific NS" << endl);
+          LOG(prefix << qname << ": We have NS in cache for '" << subdomain << "' but part of LOOP (already seen " << insertionPair.first->qname << ")! Trying less specific NS" << endl);
           ;
           if (doLog())
             for (set<GetBestNSAnswer>::const_iterator j = beenthere.begin(); j != beenthere.end(); ++j) {
index ac033238197ebdd1ce7859bdd77886d0f83e8794..dec12ad460e7374cedd88d13b475053530b63bba 100644 (file)
@@ -190,7 +190,7 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_basic)
     /* blocked A */
     DNSRecord dr;
     dr.d_type = QType::A;
-    dr.setContent(DNSRecordContent::mastermake(QType::A, QClass::IN, responseIP.toString()));
+    dr.setContent(DNSRecordContent::make(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.setContent(DNSRecordContent::mastermake(QType::A, QClass::IN, "192.0.2.142"));
+    dr.setContent(DNSRecordContent::make(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;
@@ -317,16 +317,16 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_local_data)
   const DNSName bad1("bad1.example.com.");
   const DNSName bad2("bad2.example.com.");
 
-  zone->addQNameTrigger(bad1, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::mastermake(QType::CNAME, QClass::IN, "garden.example.net.")}));
+  zone->addQNameTrigger(bad1, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::make(QType::CNAME, QClass::IN, "garden.example.net.")}));
   BOOST_CHECK_EQUAL(zone->size(), 1U);
 
-  zone->addQNameTrigger(bad2, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::mastermake(QType::A, QClass::IN, "192.0.2.1")}));
+  zone->addQNameTrigger(bad2, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::make(QType::A, QClass::IN, "192.0.2.1")}));
   BOOST_CHECK_EQUAL(zone->size(), 2U);
 
-  zone->addQNameTrigger(bad2, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::mastermake(QType::A, QClass::IN, "192.0.2.2")}));
+  zone->addQNameTrigger(bad2, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::make(QType::A, QClass::IN, "192.0.2.2")}));
   BOOST_CHECK_EQUAL(zone->size(), 2U);
 
-  zone->addQNameTrigger(bad2, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::mastermake(QType::MX, QClass::IN, "10 garden-mail.example.net.")}));
+  zone->addQNameTrigger(bad2, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::make(QType::MX, QClass::IN, "10 garden-mail.example.net.")}));
   BOOST_CHECK_EQUAL(zone->size(), 2U);
 
   dfe.addZone(zone);
@@ -392,7 +392,7 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_local_data)
   }
 
   /* remove only one entry, one of the A local records */
-  zone->rmQNameTrigger(bad2, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::mastermake(QType::A, QClass::IN, "192.0.2.1")}));
+  zone->rmQNameTrigger(bad2, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::make(QType::A, QClass::IN, "192.0.2.1")}));
   BOOST_CHECK_EQUAL(zone->size(), 2U);
 
   {
@@ -444,9 +444,9 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_local_data_netmask)
   const DNSName name("foo.example.com");
   const Netmask nm1("192.168.1.0/24");
 
-  zone->addClientTrigger(nm1, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::mastermake(QType::A, QClass::IN, "1.2.3.4")}));
-  zone->addClientTrigger(nm1, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::mastermake(QType::A, QClass::IN, "1.2.3.5")}));
-  zone->addClientTrigger(nm1, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::mastermake(QType::AAAA, QClass::IN, "::1234")}));
+  zone->addClientTrigger(nm1, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::make(QType::A, QClass::IN, "1.2.3.4")}));
+  zone->addClientTrigger(nm1, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::make(QType::A, QClass::IN, "1.2.3.5")}));
+  zone->addClientTrigger(nm1, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::make(QType::AAAA, QClass::IN, "::1234")}));
   BOOST_CHECK_EQUAL(zone->size(), 1U);
 
   dfe.addZone(zone);
@@ -487,16 +487,16 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_local_data_netmask)
   }
 
   // Try to zap 1 nonexisting record
-  zone->rmClientTrigger(nm1, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::mastermake(QType::A, QClass::IN, "1.1.1.1")}));
+  zone->rmClientTrigger(nm1, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::make(QType::A, QClass::IN, "1.1.1.1")}));
 
   // Zap a record using a wider netmask
-  zone->rmClientTrigger(Netmask("192.168.0.0/16"), DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::mastermake(QType::A, QClass::IN, "1.2.3.4")}));
+  zone->rmClientTrigger(Netmask("192.168.0.0/16"), DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::make(QType::A, QClass::IN, "1.2.3.4")}));
 
   // Zap a record using a narrow netmask
-  zone->rmClientTrigger(Netmask("192.168.1.1/32"), DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::mastermake(QType::A, QClass::IN, "1.2.3.4")}));
+  zone->rmClientTrigger(Netmask("192.168.1.1/32"), DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::make(QType::A, QClass::IN, "1.2.3.4")}));
 
   // Zap 1 existing record
-  zone->rmClientTrigger(nm1, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::mastermake(QType::A, QClass::IN, "1.2.3.5")}));
+  zone->rmClientTrigger(nm1, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::make(QType::A, QClass::IN, "1.2.3.5")}));
 
   { // A query should match one record now
     const auto matchingPolicy = dfe.getClientPolicy(ComboAddress("192.168.1.1"), std::unordered_map<std::string, bool>(), DNSFilterEngine::maximumPriority);
@@ -526,10 +526,10 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_local_data_netmask)
   }
 
   // Zap one more A record
-  zone->rmClientTrigger(nm1, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::mastermake(QType::A, QClass::IN, "1.2.3.4")}));
+  zone->rmClientTrigger(nm1, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::make(QType::A, QClass::IN, "1.2.3.4")}));
 
   // Zap now nonexisting record
-  zone->rmClientTrigger(nm1, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::mastermake(QType::A, QClass::IN, "1.2.3.4")}));
+  zone->rmClientTrigger(nm1, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::make(QType::A, QClass::IN, "1.2.3.4")}));
 
   { // AAAA query should still match one record
     const auto matchingPolicy = dfe.getClientPolicy(ComboAddress("192.168.1.1"), std::unordered_map<std::string, bool>(), DNSFilterEngine::maximumPriority);
@@ -546,7 +546,7 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_local_data_netmask)
   }
 
   // Zap AAAA record
-  zone->rmClientTrigger(nm1, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::mastermake(QType::AAAA, QClass::IN, "::1234")}));
+  zone->rmClientTrigger(nm1, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::make(QType::AAAA, QClass::IN, "::1234")}));
 
   { // there should be no match left
     const auto matchingPolicy = dfe.getClientPolicy(ComboAddress("192.168.1.1"), std::unordered_map<std::string, bool>(), DNSFilterEngine::maximumPriority);
@@ -569,10 +569,10 @@ BOOST_AUTO_TEST_CASE(test_multiple_filter_policies)
   const DNSName badWildcard("*.bad-wildcard.example.com.");
   const DNSName badUnderWildcard("sub.bad-wildcard.example.com.");
 
-  zone1->addQNameTrigger(bad, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::mastermake(QType::CNAME, QClass::IN, "garden1a.example.net.")}));
-  zone2->addQNameTrigger(bad, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::mastermake(QType::CNAME, QClass::IN, "garden2a.example.net.")}));
-  zone1->addQNameTrigger(badWildcard, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::mastermake(QType::CNAME, QClass::IN, "garden1b.example.net.")}));
-  zone2->addQNameTrigger(badUnderWildcard, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::mastermake(QType::CNAME, QClass::IN, "garden2b.example.net.")}));
+  zone1->addQNameTrigger(bad, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::make(QType::CNAME, QClass::IN, "garden1a.example.net.")}));
+  zone2->addQNameTrigger(bad, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::make(QType::CNAME, QClass::IN, "garden2a.example.net.")}));
+  zone1->addQNameTrigger(badWildcard, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::make(QType::CNAME, QClass::IN, "garden1b.example.net.")}));
+  zone2->addQNameTrigger(badUnderWildcard, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::make(QType::CNAME, QClass::IN, "garden2b.example.net.")}));
 
   dfe.addZone(zone1);
   dfe.addZone(zone2);
@@ -660,17 +660,17 @@ BOOST_AUTO_TEST_CASE(test_multiple_filter_policies_order)
   const DNSName nsName("ns.bad.wolf.");
   const ComboAddress responseIP("192.0.2.254");
 
-  zone1->addClientTrigger(Netmask(clientIP, 32), DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::mastermake(QType::CNAME, QClass::IN, "client1a.example.net.")}));
-  zone1->addQNameTrigger(bad, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::mastermake(QType::CNAME, QClass::IN, "garden1a.example.net.")}));
-  zone1->addNSIPTrigger(Netmask(nsIP, 32), DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::NSIP, 0, nullptr, {DNSRecordContent::mastermake(QType::CNAME, QClass::IN, "nsip1a.example.net.")}));
-  zone1->addNSTrigger(nsName, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::NSDName, 0, nullptr, {DNSRecordContent::mastermake(QType::CNAME, QClass::IN, "nsname1a.example.net.")}));
-  zone1->addResponseTrigger(Netmask(responseIP, 32), DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ResponseIP, 0, nullptr, {DNSRecordContent::mastermake(QType::CNAME, QClass::IN, "response1a.example.net.")}));
+  zone1->addClientTrigger(Netmask(clientIP, 32), DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::make(QType::CNAME, QClass::IN, "client1a.example.net.")}));
+  zone1->addQNameTrigger(bad, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::make(QType::CNAME, QClass::IN, "garden1a.example.net.")}));
+  zone1->addNSIPTrigger(Netmask(nsIP, 32), DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::NSIP, 0, nullptr, {DNSRecordContent::make(QType::CNAME, QClass::IN, "nsip1a.example.net.")}));
+  zone1->addNSTrigger(nsName, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::NSDName, 0, nullptr, {DNSRecordContent::make(QType::CNAME, QClass::IN, "nsname1a.example.net.")}));
+  zone1->addResponseTrigger(Netmask(responseIP, 32), DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ResponseIP, 0, nullptr, {DNSRecordContent::make(QType::CNAME, QClass::IN, "response1a.example.net.")}));
 
-  zone2->addClientTrigger(Netmask(clientIP, 32), DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::mastermake(QType::CNAME, QClass::IN, "client2a.example.net.")}));
-  zone2->addQNameTrigger(bad, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::mastermake(QType::CNAME, QClass::IN, "garden2a.example.net.")}));
-  zone2->addNSIPTrigger(Netmask(nsIP, 32), DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::NSIP, 0, nullptr, {DNSRecordContent::mastermake(QType::CNAME, QClass::IN, "nsip2a.example.net.")}));
-  zone2->addNSTrigger(nsName, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::NSDName, 0, nullptr, {DNSRecordContent::mastermake(QType::CNAME, QClass::IN, "nsname2a.example.net.")}));
-  zone2->addResponseTrigger(Netmask(responseIP, 32), DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ResponseIP, 0, nullptr, {DNSRecordContent::mastermake(QType::CNAME, QClass::IN, "response2a.example.net.")}));
+  zone2->addClientTrigger(Netmask(clientIP, 32), DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ClientIP, 0, nullptr, {DNSRecordContent::make(QType::CNAME, QClass::IN, "client2a.example.net.")}));
+  zone2->addQNameTrigger(bad, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::QName, 0, nullptr, {DNSRecordContent::make(QType::CNAME, QClass::IN, "garden2a.example.net.")}));
+  zone2->addNSIPTrigger(Netmask(nsIP, 32), DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::NSIP, 0, nullptr, {DNSRecordContent::make(QType::CNAME, QClass::IN, "nsip2a.example.net.")}));
+  zone2->addNSTrigger(nsName, DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::NSDName, 0, nullptr, {DNSRecordContent::make(QType::CNAME, QClass::IN, "nsname2a.example.net.")}));
+  zone2->addResponseTrigger(Netmask(responseIP, 32), DNSFilterEngine::Policy(DNSFilterEngine::PolicyKind::Custom, DNSFilterEngine::PolicyType::ResponseIP, 0, nullptr, {DNSRecordContent::make(QType::CNAME, QClass::IN, "response2a.example.net.")}));
 
   dfe.addZone(zone1);
   dfe.addZone(zone2);
@@ -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.setContent(DNSRecordContent::mastermake(QType::A, QClass::IN, responseIP.toString()));
+    dr.setContent(DNSRecordContent::make(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);
@@ -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.setContent(DNSRecordContent::mastermake(QType::A, QClass::IN, responseIP.toString()));
+    dr.setContent(DNSRecordContent::make(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 be31d1e7afeace01d3afbd44332549b28a9a28d4..dc01f55585a4670e34f2fe55ac003182d3af5591 100644 (file)
@@ -15,7 +15,7 @@ static recordsAndSignatures genRecsAndSigs(const DNSName& name, const uint16_t q
   rec.d_type = qtype;
   rec.d_ttl = 600;
   rec.d_place = DNSResourceRecord::AUTHORITY;
-  rec.setContent(DNSRecordContent::mastermake(qtype, QClass::IN, content));
+  rec.setContent(DNSRecordContent::make(qtype, QClass::IN, content));
 
   ret.records.push_back(rec);
 
index 921c7d1f11c4e016f2921d306362e4caa155df04..8693625a985b7886bdc66c4495779736432e4fe7 100644 (file)
@@ -25,17 +25,17 @@ struct Fixture
 {
   static std::shared_ptr<DNSRecordContent> makeLocalhostRootDRC()
   {
-    return DNSRecordContent::mastermake(QType::SOA, QClass::IN, "localhost. root 1 604800 86400 2419200 604800");
+    return DNSRecordContent::make(QType::SOA, QClass::IN, "localhost. root 1 604800 86400 2419200 604800");
   }
 
   static std::shared_ptr<DNSRecordContent> makeLocalhostDRC()
   {
-    return DNSRecordContent::mastermake(QType::NS, QClass::IN, "localhost.");
+    return DNSRecordContent::make(QType::NS, QClass::IN, "localhost.");
   }
 
   static std::shared_ptr<DNSRecordContent> makePtrDRC(const std::string& name)
   {
-    return DNSRecordContent::mastermake(QType::PTR, QClass::IN, name);
+    return DNSRecordContent::make(QType::PTR, QClass::IN, name);
   }
 
   static void addDomainMapFixtureEntry(SyncRes::domainmap_t& domainMap,
@@ -57,7 +57,7 @@ struct Fixture
   {
     domainMap[DNSName{name}] = SyncRes::AuthDomain{
       .d_records = {
-        DNSRecord(name, DNSRecordContent::mastermake(type, QClass::IN, address), type),
+        DNSRecord(name, DNSRecordContent::make(type, QClass::IN, address), type),
         DNSRecord(name, makeLocalhostDRC(), QType::NS),
         DNSRecord(name, makeLocalhostRootDRC(), QType::SOA),
       },
@@ -128,8 +128,8 @@ struct Fixture
       "localhost" + actualSearchSuffix,
       {DNSRecord("localhost" + actualSearchSuffix, makeLocalhostDRC(), QType::NS),
        DNSRecord("localhost" + actualSearchSuffix, makeLocalhostRootDRC(), QType::SOA),
-       DNSRecord("localhost" + actualSearchSuffix, DNSRecordContent::mastermake(QType::AAAA, QClass::IN, "::1"), QType::AAAA),
-       DNSRecord("localhost" + actualSearchSuffix, DNSRecordContent::mastermake(QType::A, QClass::IN, "127.0.0.1"), QType::A)});
+       DNSRecord("localhost" + actualSearchSuffix, DNSRecordContent::make(QType::AAAA, QClass::IN, "::1"), QType::AAAA),
+       DNSRecord("localhost" + actualSearchSuffix, DNSRecordContent::make(QType::A, QClass::IN, "127.0.0.1"), QType::A)});
     addDomainMapFixtureEntry(domainMap, "self" + actualSearchSuffix, QType::AAAA, "::1");
     addDomainMapFixtureEntry(
       domainMap,
index 2737f78ec02d8bdfbb52680b558f89742c6685fe..64c027da55bf006e99d6d4ba1f70b28742c2acc8 100644 (file)
@@ -1570,7 +1570,7 @@ void AsyncWebServer::serveConnection(const std::shared_ptr<Socket>& socket) cons
   }
   catch (...) {
     SLOG(g_log << Logger::Error << logprefix << "Unknown exception" << endl,
-         req.d_slog->error(Logr::Error, "Exception handing request"))
+         req.d_slog->error(Logr::Error, "Exception handing request"));
   }
 }
 
index 2f993bfa4a44109430ca990aa68d014e23f30675..0144456b29dcad592662422495c4bc295cbdf126 100644 (file)
@@ -410,7 +410,7 @@ uint PacketHandler::performUpdate(const string &msgPrefix, const DNSRecord *rr,
         auto repr = rec.getZoneRepresentation();
         if (rec.qtype == QType::TXT) {
           DLOG(g_log<<msgPrefix<<"Adjusting TXT content from ["<<repr<<"]"<<endl);
-          auto drc = DNSRecordContent::mastermake(rec.qtype.getCode(), QClass::IN, repr);
+          auto drc = DNSRecordContent::make(rec.qtype.getCode(), QClass::IN, repr);
           auto ser = drc->serialize(rec.qname, true, true);
           auto rc = DNSRecordContent::deserialize(rec.qname, rec.qtype.getCode(), ser);
           repr = rc->getZoneRepresentation(true);
@@ -545,12 +545,12 @@ int PacketHandler::forwardPacket(const string &msgPrefix, const DNSPacket& p, co
   B.getDomainMetadata(p.qdomain, "FORWARD-DNSUPDATE", forward);
 
   if (forward.size() == 0 && ! ::arg().mustDo("forward-dnsupdate")) {
-    g_log<<Logger::Notice<<msgPrefix<<"Not configured to forward to master, returning Refused."<<endl;
+    g_log << Logger::Notice << msgPrefix << "Not configured to forward to primary, returning Refused." << endl;
     return RCode::Refused;
   }
 
-  for(const auto& remote : di.masters) {
-    g_log<<Logger::Notice<<msgPrefix<<"Forwarding packet to master "<<remote<<endl;
+  for (const auto& remote : di.primaries) {
+    g_log << Logger::Notice << msgPrefix << "Forwarding packet to primary " << remote << endl;
 
     if (!pdns::isQueryLocalAddressFamilyEnabled(remote.sin4.sin_family)) {
       continue;
@@ -568,7 +568,7 @@ int PacketHandler::forwardPacket(const string &msgPrefix, const DNSPacket& p, co
         closesocket(sock);
       }
       catch(const PDNSException& e) {
-        g_log<<Logger::Error<<"Error closing master forwarding socket after connect() failed: "<<e.reason<<endl;
+        g_log << Logger::Error << "Error closing primary forwarding socket after connect() failed: " << e.reason << endl;
       }
       continue;
     }
@@ -585,29 +585,29 @@ int PacketHandler::forwardPacket(const string &msgPrefix, const DNSPacket& p, co
         closesocket(sock);
       }
       catch(const PDNSException& e) {
-        g_log<<Logger::Error<<"Error closing master forwarding socket after write() failed: "<<e.reason<<endl;
+        g_log << Logger::Error << "Error closing primary forwarding socket after write() failed: " << e.reason << endl;
       }
       continue;
     }
 
     int res = waitForData(sock, 10, 0);
     if (!res) {
-      g_log<<Logger::Error<<msgPrefix<<"Timeout waiting for reply from master at "<<remote.toStringWithPort()<<endl;
+      g_log << Logger::Error << msgPrefix << "Timeout waiting for reply from primary at " << remote.toStringWithPort() << endl;
       try {
         closesocket(sock);
       }
       catch(const PDNSException& e) {
-        g_log<<Logger::Error<<"Error closing master forwarding socket after a timeout occurred: "<<e.reason<<endl;
+        g_log << Logger::Error << "Error closing primary forwarding socket after a timeout occurred: " << e.reason << endl;
       }
       continue;
     }
     if (res < 0) {
-      g_log<<Logger::Error<<msgPrefix<<"Error waiting for answer from master at "<<remote.toStringWithPort()<<", error:"<<stringerror()<<endl;
+      g_log << Logger::Error << msgPrefix << "Error waiting for answer from primary at " << remote.toStringWithPort() << ", error:" << stringerror() << endl;
       try {
         closesocket(sock);
       }
       catch(const PDNSException& e) {
-        g_log<<Logger::Error<<"Error closing master forwarding socket after an error occurred: "<<e.reason<<endl;
+        g_log << Logger::Error << "Error closing primary forwarding socket after an error occurred: " << e.reason << endl;
       }
       continue;
     }
@@ -616,12 +616,12 @@ int PacketHandler::forwardPacket(const string &msgPrefix, const DNSPacket& p, co
     ssize_t recvRes;
     recvRes = recv(sock, &lenBuf, sizeof(lenBuf), 0);
     if (recvRes < 0 || static_cast<size_t>(recvRes) < sizeof(lenBuf)) {
-      g_log<<Logger::Error<<msgPrefix<<"Could not receive data (length) from master at "<<remote.toStringWithPort()<<", error:"<<stringerror()<<endl;
+      g_log << Logger::Error << msgPrefix << "Could not receive data (length) from primary at " << remote.toStringWithPort() << ", error:" << stringerror() << endl;
       try {
         closesocket(sock);
       }
       catch(const PDNSException& e) {
-        g_log<<Logger::Error<<"Error closing master forwarding socket after recv() failed: "<<e.reason<<endl;
+        g_log << Logger::Error << "Error closing primary forwarding socket after recv() failed: " << e.reason << endl;
       }
       continue;
     }
@@ -630,12 +630,12 @@ int PacketHandler::forwardPacket(const string &msgPrefix, const DNSPacket& p, co
     buffer.resize(packetLen);
     recvRes = recv(sock, &buffer.at(0), packetLen, 0);
     if (recvRes < 0) {
-      g_log<<Logger::Error<<msgPrefix<<"Could not receive data (dnspacket) from master at "<<remote.toStringWithPort()<<", error:"<<stringerror()<<endl;
+      g_log << Logger::Error << msgPrefix << "Could not receive data (dnspacket) from primary at " << remote.toStringWithPort() << ", error:" << stringerror() << endl;
       try {
         closesocket(sock);
       }
       catch(const PDNSException& e) {
-        g_log<<Logger::Error<<"Error closing master forwarding socket after recv() failed: "<<e.reason<<endl;
+        g_log << Logger::Error << "Error closing primary forwarding socket after recv() failed: " << e.reason << endl;
       }
       continue;
     }
@@ -643,7 +643,7 @@ int PacketHandler::forwardPacket(const string &msgPrefix, const DNSPacket& p, co
       closesocket(sock);
     }
     catch(const PDNSException& e) {
-      g_log<<Logger::Error<<"Error closing master forwarding socket: "<<e.reason<<endl;
+      g_log << Logger::Error << "Error closing primary forwarding socket: " << e.reason << endl;
     }
 
     try {
@@ -652,11 +652,11 @@ int PacketHandler::forwardPacket(const string &msgPrefix, const DNSPacket& p, co
       return mdp.d_header.rcode;
     }
     catch (...) {
-      g_log<<Logger::Error<<msgPrefix<<"Failed to parse response packet from master at "<<remote.toStringWithPort()<<endl;
+      g_log << Logger::Error << msgPrefix << "Failed to parse response packet from primary at " << remote.toStringWithPort() << endl;
       continue;
     }
   }
-  g_log<<Logger::Error<<msgPrefix<<"Failed to forward packet to master(s). Returning ServFail."<<endl;
+  g_log << Logger::Error << msgPrefix << "Failed to forward packet to primary(s). Returning ServFail." << endl;
   return RCode::ServFail;
 
 }
@@ -759,7 +759,7 @@ int PacketHandler::processUpdate(DNSPacket& p) {
     return RCode::NotAuth;
   }
 
-  if (di.kind == DomainInfo::Slave)
+  if (di.kind == DomainInfo::Secondary)
     return forwardPacket(msgPrefix, p, di);
 
   // Check if all the records provided are within the zone
@@ -989,8 +989,8 @@ int PacketHandler::processUpdate(DNSPacket& p) {
       zone.append("$");
       purgeAuthCaches(zone);
 
-      // Notify slaves
-      if (di.kind == DomainInfo::Master) {
+      // Notify secondaries
+      if (di.kind == DomainInfo::Primary) {
         vector<string> notify;
         B.getDomainMetadata(p.qdomain, "NOTIFY-DNSUPDATE", notify);
         if (!notify.empty() && notify.front() == "1") {
index 741bc701b975c691a5a6b165115610d2574a8887..f8188b0ab2aee6208c9c9c7028c16320020f81dc 100644 (file)
@@ -299,24 +299,24 @@ static vector<uint8_t> makeBigReferral()
   for(char c='a'; c<= 'm';++c) {
     pw.startRecord(DNSName("com"), QType::NS, 3600, 1, DNSResourceRecord::AUTHORITY);
     gtld[0]=c;
-    auto drc = DNSRecordContent::mastermake(QType::NS, 1, gtld);
+    auto drc = DNSRecordContent::make(QType::NS, 1, gtld);
     drc->toPacket(pw);
   }
 
   for(char c='a'; c<= 'k';++c) {
     gtld[0]=c;
     pw.startRecord(DNSName(gtld), QType::A, 3600, 1, DNSResourceRecord::ADDITIONAL);
-    auto drc = DNSRecordContent::mastermake(QType::A, 1, "1.2.3.4");
+    auto drc = DNSRecordContent::make(QType::A, 1, "1.2.3.4");
     drc->toPacket(pw);
   }
 
 
   pw.startRecord(DNSName("a.gtld-servers.net"), QType::AAAA, 3600, 1, DNSResourceRecord::ADDITIONAL);
-  auto aaaarc = DNSRecordContent::mastermake(QType::AAAA, 1, "2001:503:a83e::2:30");
+  auto aaaarc = DNSRecordContent::make(QType::AAAA, 1, "2001:503:a83e::2:30");
   aaaarc->toPacket(pw);
 
   pw.startRecord(DNSName("b.gtld-servers.net"), QType::AAAA, 3600, 1, DNSResourceRecord::ADDITIONAL);
-  aaaarc = DNSRecordContent::mastermake(QType::AAAA, 1, "2001:503:231d::2:30");
+  aaaarc = DNSRecordContent::make(QType::AAAA, 1, "2001:503:231d::2:30");
   aaaarc->toPacket(pw);
 
 
@@ -363,7 +363,7 @@ static vector<uint8_t> makeBigDNSPacketReferral()
   //  shuffle(records);
   for(const auto& rec : records) {
     pw.startRecord(rec.qname, rec.qtype.getCode(), rec.ttl, 1, DNSResourceRecord::ADDITIONAL);
-    auto drc = DNSRecordContent::mastermake(rec.qtype.getCode(), 1, rec.content);
+    auto drc = DNSRecordContent::make(rec.qtype.getCode(), 1, rec.content);
     drc->toPacket(pw);
   }
 
@@ -382,8 +382,8 @@ struct MakeARecordTestMM
 
   void operator()() const
   {
-      auto drc = DNSRecordContent::mastermake(QType::A, 1,
-                                              "1.2.3.4");
+    auto drc = DNSRecordContent::make(QType::A, 1,
+                                      "1.2.3.4");
   }
 };
 
@@ -455,8 +455,8 @@ struct GenericRecordTest
     DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), d_type);
     for(int records = 0; records < d_records; records++) {
       pw.startRecord(DNSName("outpost.ds9a.nl"), d_type);
-      auto drc = DNSRecordContent::mastermake(d_type, 1,
-                                              d_content);
+      auto drc = DNSRecordContent::make(d_type, 1,
+                                        d_content);
       drc->toPacket(pw);
     }
     pw.commit();
@@ -482,7 +482,7 @@ struct AAAARecordTest
     DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::AAAA);
     for(int records = 0; records < d_records; records++) {
       pw.startRecord(DNSName("outpost.ds9a.nl"), QType::AAAA);
-      auto drc = DNSRecordContent::mastermake(QType::AAAA, 1, "fe80::21d:92ff:fe6d:8441");
+      auto drc = DNSRecordContent::make(QType::AAAA, 1, "fe80::21d:92ff:fe6d:8441");
       drc->toPacket(pw);
     }
     pw.commit();
@@ -506,7 +506,7 @@ struct SOARecordTest
 
     for(int records = 0; records < d_records; records++) {
       pw.startRecord(DNSName("outpost.ds9a.nl"), QType::SOA);
-      auto drc = DNSRecordContent::mastermake(QType::SOA, 1, "a0.org.afilias-nst.info. noc.afilias-nst.info. 2008758137 1800 900 604800 86400");
+      auto drc = DNSRecordContent::make(QType::SOA, 1, "a0.org.afilias-nst.info. noc.afilias-nst.info. 2008758137 1800 900 604800 86400");
       drc->toPacket(pw);
     }
     pw.commit();
@@ -527,20 +527,20 @@ static vector<uint8_t> makeTypicalReferral()
   DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::A);
 
   pw.startRecord(DNSName("ds9a.nl"), QType::NS, 3600, 1, DNSResourceRecord::AUTHORITY);
-  auto drc = DNSRecordContent::mastermake(QType::NS, 1, "ns1.ds9a.nl");
+  auto drc = DNSRecordContent::make(QType::NS, 1, "ns1.ds9a.nl");
   drc->toPacket(pw);
 
   pw.startRecord(DNSName("ds9a.nl"), QType::NS, 3600, 1, DNSResourceRecord::AUTHORITY);
-  drc = DNSRecordContent::mastermake(QType::NS, 1, "ns2.ds9a.nl");
+  drc = DNSRecordContent::make(QType::NS, 1, "ns2.ds9a.nl");
   drc->toPacket(pw);
 
 
   pw.startRecord(DNSName("ns1.ds9a.nl"), QType::A, 3600, 1, DNSResourceRecord::ADDITIONAL);
-  drc = DNSRecordContent::mastermake(QType::A, 1, "1.2.3.4");
+  drc = DNSRecordContent::make(QType::A, 1, "1.2.3.4");
   drc->toPacket(pw);
 
   pw.startRecord(DNSName("ns2.ds9a.nl"), QType::A, 3600, 1, DNSResourceRecord::ADDITIONAL);
-  drc = DNSRecordContent::mastermake(QType::A, 1, "4.3.2.1");
+  drc = DNSRecordContent::make(QType::A, 1, "4.3.2.1");
   drc->toPacket(pw);
 
   pw.commit();
index a5d00ed73ba81333b8bde0ab59ea163e8959ce48..03468f8e367c450f1bd5d1727cae118e07840a42 100644 (file)
@@ -1129,9 +1129,9 @@ public:
 
   /* The callback prototype changed in 3.4.0. */
 #if GNUTLS_VERSION_NUMBER >= 0x030400
-  static int newTicketFromServerCb(gnutls_session_t session, unsigned int htype, unsigned post, unsigned int incoming, const gnutls_datum_t* msg)
+  static int newTicketFromServerCb(gnutls_session_t session, unsigned int htype, unsigned post, unsigned int /* incoming */, const gnutls_datum_t* /* msg */)
 #else
-  static int newTicketFromServerCb(gnutls_session_t session, unsigned int htype, unsigned post, unsigned int incoming)
+  static int newTicketFromServerCb(gnutls_session_t session, unsigned int htype, unsigned post, unsigned int /* incoming */)
 #endif /* GNUTLS_VERSION_NUMBER >= 0x030400 */
   {
     if (htype != GNUTLS_HANDSHAKE_NEW_SESSION_TICKET || post != GNUTLS_HOOK_POST || session == nullptr) {
@@ -1153,7 +1153,7 @@ public:
     return 0;
   }
 
-  IOState tryConnect(bool fastOpen, const ComboAddress& remote) override
+  IOState tryConnect(bool fastOpen, [[maybe_unused]] const ComboAddress& remote) override
   {
     int ret = 0;
 
index bff31f21fc51689c37652cb9842526cdaa61b118..9a918b36c7d5d1958f8aa343f9f4b01debf6fc71 100644 (file)
@@ -36,21 +36,21 @@ BOOST_AUTO_TEST_CASE(test_parser)
   vector<BindDomainInfo> domains = BP.getDomains();
   BOOST_CHECK_EQUAL(domains.size(), 11U);
 
-#define checkzone(i, dname, fname, ztype, nmasters)         \
-  {                                                         \
-    BOOST_CHECK(domains[i].name == DNSName(dname));         \
-    BOOST_CHECK_EQUAL(domains[i].filename, fname);          \
-    BOOST_CHECK_EQUAL(domains[i].type, #ztype);             \
-    BOOST_CHECK_EQUAL(domains[i].masters.size(), nmasters); \
+#define checkzone(i, dname, fname, ztype, nprimaries)           \
+  {                                                             \
+    BOOST_CHECK(domains[i].name == DNSName(dname));             \
+    BOOST_CHECK_EQUAL(domains[i].filename, fname);              \
+    BOOST_CHECK_EQUAL(domains[i].type, #ztype);                 \
+    BOOST_CHECK_EQUAL(domains[i].primaries.size(), nprimaries); \
   }
 
   checkzone(0, "example.com", "./zones/example.com", master, 0U);
   checkzone(1, "test.com", "./zones/test.com", slave, 1U);
-  BOOST_CHECK_EQUAL(domains[1].masters[0].toString(), ComboAddress("1.2.3.4", 5678).toString());
+  BOOST_CHECK_EQUAL(domains[1].primaries[0].toString(), ComboAddress("1.2.3.4", 5678).toString());
   checkzone(2, "test.dyndns", "./zones/test.dyndns", garblewarble, 0U);
   checkzone(3, "wtest.com", "./zones/wtest.com", primary, 0U);
   checkzone(4, "nztest.com", "./zones/nztest.com", secondary, 1U);
-  BOOST_CHECK_EQUAL(domains[1].masters[0].toString(), ComboAddress("1.2.3.4", 5678).toString());
+  BOOST_CHECK_EQUAL(domains[1].primaries[0].toString(), ComboAddress("1.2.3.4", 5678).toString());
   checkzone(5, "dnssec-parent.com", "./zones/dnssec-parent.com", primary, 0U);
   checkzone(6, "delegated.dnssec-parent.com", "./zones/delegated.dnssec-parent.com", primary, 0U);
   checkzone(7, "secure-delegated.dnssec-parent.com", "./zones/secure-delegated.dnssec-parent.com", primary, 0U);
index 8436fca4402959bc24268079fc9f137847ab44a8..9c0d75aec4e8466cdb6bdeb86fd352ecfe3d0d11 100644 (file)
@@ -22,7 +22,7 @@ static inline std::shared_ptr<DNSRecordContent> getRecordContent(uint16_t type,
     result = std::make_shared<OPTRecordContent>();
   }
   else {
-    result = DNSRecordContent::mastermake(type, QClass::IN, content);
+    result = DNSRecordContent::make(type, QClass::IN, content);
   }
 
   return result;
index 7c19d72ec82a9944e8c80a6a5aa24cb870fbc5cd..d41f0d4b0223c77d41a0b6dda6c025ac3d45a8d6 100644 (file)
@@ -7,10 +7,13 @@
 #include <boost/test/unit_test.hpp>
 #include <boost/assign/std/map.hpp>
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wextra"
 #include <boost/accumulators/statistics/median.hpp>
 #include <boost/accumulators/statistics/mean.hpp>
 #include <boost/accumulators/accumulators.hpp>
 #include <boost/accumulators/statistics.hpp>
+#pragma GCC diagnostic pop
 
 #include "arguments.hh"
 #include "dns_random.hh"
index 4bad3d0dbcf6ea46b04dc5d33e07f89ebc00a21b..63a86fef7694c1925e2621835e1a5e7791e5d071 100644 (file)
@@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheSimple) {
       BOOST_CHECK_EQUAL(found, false);
       BOOST_CHECK(!subnet);
 
-      PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, a, QType::A, QClass::IN, response, receivedOverUDP, 0, boost::none);
+      PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader().get())), dnssecOK, a, QType::A, QClass::IN, response, receivedOverUDP, 0, boost::none);
 
       found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
       if (found == true) {
@@ -168,7 +168,7 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheSharded) {
       BOOST_CHECK_EQUAL(found, false);
       BOOST_CHECK(!subnet);
 
-      PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, ids.qname, QType::AAAA, QClass::IN, response, receivedOverUDP, 0, boost::none);
+      PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader().get())), dnssecOK, ids.qname, QType::AAAA, QClass::IN, response, receivedOverUDP, 0, boost::none);
 
       found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
       if (found == true) {
@@ -265,7 +265,7 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheTCP) {
       BOOST_CHECK_EQUAL(found, false);
       BOOST_CHECK(!subnet);
 
-      PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, a, QType::A, QClass::IN, response, receivedOverUDP, RCode::NoError, boost::none);
+      PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader().get())), dnssecOK, a, QType::A, QClass::IN, response, receivedOverUDP, RCode::NoError, boost::none);
       found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
       BOOST_CHECK_EQUAL(found, true);
       BOOST_CHECK(!subnet);
@@ -281,7 +281,7 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheTCP) {
       BOOST_CHECK_EQUAL(found, false);
       BOOST_CHECK(!subnet);
 
-      PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, a, QType::A, QClass::IN, response, !receivedOverUDP, RCode::NoError, boost::none);
+      PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader().get())), dnssecOK, a, QType::A, QClass::IN, response, !receivedOverUDP, RCode::NoError, boost::none);
       found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, !receivedOverUDP, 0, true);
       BOOST_CHECK_EQUAL(found, true);
       BOOST_CHECK(!subnet);
@@ -328,13 +328,13 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheServFailTTL) {
     BOOST_CHECK(!subnet);
 
     // Insert with failure-TTL of 0 (-> should not enter cache).
-    PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, a, QType::A, QClass::IN, response, receivedOverUDP, RCode::ServFail, boost::optional<uint32_t>(0));
+    PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader().get())), dnssecOK, a, QType::A, QClass::IN, response, receivedOverUDP, RCode::ServFail, boost::optional<uint32_t>(0));
     found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
     BOOST_CHECK_EQUAL(found, false);
     BOOST_CHECK(!subnet);
 
     // Insert with failure-TTL non-zero (-> should enter cache).
-    PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, a, QType::A, QClass::IN, response, receivedOverUDP, RCode::ServFail, boost::optional<uint32_t>(300));
+    PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader().get())), dnssecOK, a, QType::A, QClass::IN, response, receivedOverUDP, RCode::ServFail, boost::optional<uint32_t>(300));
     found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
     BOOST_CHECK_EQUAL(found, true);
     BOOST_CHECK(!subnet);
@@ -383,7 +383,7 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheNoDataTTL) {
     BOOST_CHECK_EQUAL(found, false);
     BOOST_CHECK(!subnet);
 
-    PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, name, QType::A, QClass::IN, response, receivedOverUDP, RCode::NoError, boost::none);
+    PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader().get())), dnssecOK, name, QType::A, QClass::IN, response, receivedOverUDP, RCode::NoError, boost::none);
     found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
     BOOST_CHECK_EQUAL(found, true);
     BOOST_CHECK(!subnet);
@@ -438,7 +438,7 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheNXDomainTTL) {
     BOOST_CHECK_EQUAL(found, false);
     BOOST_CHECK(!subnet);
 
-    PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, name, QType::A, QClass::IN, response, receivedOverUDP, RCode::NXDomain, boost::none);
+    PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader().get())), dnssecOK, name, QType::A, QClass::IN, response, receivedOverUDP, RCode::NXDomain, boost::none);
     found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
     BOOST_CHECK_EQUAL(found, true);
     BOOST_CHECK(!subnet);
@@ -492,7 +492,7 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheTruncated) {
     BOOST_CHECK_EQUAL(found, false);
     BOOST_CHECK(!subnet);
 
-    PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, ids.qname, QType::A, QClass::IN, response, receivedOverUDP, RCode::NXDomain, boost::none);
+    PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader().get())), dnssecOK, ids.qname, QType::A, QClass::IN, response, receivedOverUDP, RCode::NXDomain, boost::none);
 
     bool allowTruncated = true;
     found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP, 0, true, allowTruncated);
@@ -542,7 +542,7 @@ static void threadMangler(unsigned int offset)
       DNSQuestion dq(ids, query);
       g_PC.get(dq, 0, &key, subnet, dnssecOK, receivedOverUDP);
 
-      g_PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, ids.qname, QType::A, QClass::IN, response, receivedOverUDP, 0, boost::none);
+      g_PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader().get())), dnssecOK, ids.qname, QType::A, QClass::IN, response, receivedOverUDP, 0, boost::none);
     }
   }
   catch(PDNSException& e) {
@@ -1074,7 +1074,7 @@ BOOST_AUTO_TEST_CASE(test_PacketCacheXFR) {
     BOOST_CHECK_EQUAL(found, false);
     BOOST_CHECK(!subnet);
 
-    PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader())), dnssecOK, ids.qname, ids.qtype, ids.qclass, response, receivedOverUDP, 0, boost::none);
+    PC.insert(key, subnet, *(getFlagsFromDNSHeader(dq.getHeader().get())), dnssecOK, ids.qname, ids.qtype, ids.qclass, response, receivedOverUDP, 0, boost::none);
     found = PC.get(dq, pwR.getHeader()->id, &key, subnet, dnssecOK, receivedOverUDP, 0, true);
     BOOST_CHECK_EQUAL(found, false);
   }
index 527b49b8dd9471f6bc6c73d8a21b9135d4f4214e..b5811dafa4fed59c21028fed409ecfed5e72855e 100644 (file)
@@ -19,13 +19,12 @@ BOOST_AUTO_TEST_CASE(test_equality) {
 
   BOOST_CHECK(aaaa == aaaa1);
 
-
-  auto rec1=DNSRecordContent::mastermake(QType::A, 1, "192.168.0.1");
-  auto rec2=DNSRecordContent::mastermake(QType::A, 1, "192.168.222.222");
-  auto rec3=DNSRecordContent::mastermake(QType::AAAA, 1, "::1");
-  auto recMX=DNSRecordContent::mastermake(QType::MX, 1, "25 smtp.powerdns.com");
-  auto recMX2=DNSRecordContent::mastermake(QType::MX, 1, "26 smtp.powerdns.com");
-  auto recMX3=DNSRecordContent::mastermake(QType::MX, 1, "26 SMTP.powerdns.com");
+  auto rec1 = DNSRecordContent::make(QType::A, 1, "192.168.0.1");
+  auto rec2 = DNSRecordContent::make(QType::A, 1, "192.168.222.222");
+  auto rec3 = DNSRecordContent::make(QType::AAAA, 1, "::1");
+  auto recMX = DNSRecordContent::make(QType::MX, 1, "25 smtp.powerdns.com");
+  auto recMX2 = DNSRecordContent::make(QType::MX, 1, "26 smtp.powerdns.com");
+  auto recMX3 = DNSRecordContent::make(QType::MX, 1, "26 SMTP.powerdns.com");
   BOOST_CHECK(!(*rec1==*rec2));
   BOOST_CHECK(*rec1==*rec1);
   BOOST_CHECK(*rec3==*rec3);
index 141cfc3f9eed67451e004d899b66824a20895b65..e3c5fe1e33053e37752025249ec4a92dda1a369b 100644 (file)
@@ -295,8 +295,8 @@ BOOST_AUTO_TEST_CASE(test_record_types) {
    BOOST_TEST_MESSAGE("Checking record type " << q.toString() << " test #" << n);
    try {
       std::string recData;
-      auto rec = DNSRecordContent::mastermake(q.getCode(), 1, inval);
-      BOOST_CHECK_MESSAGE(rec != NULL, "mastermake( " << q.getCode() << ", 1, " << inval << ") should not return NULL");
+      auto rec = DNSRecordContent::make(q.getCode(), 1, inval);
+      BOOST_CHECK_MESSAGE(rec != NULL, "make( " << q.getCode() << ", 1, " << inval << ") should not return NULL");
       if (rec == NULL) continue;
       // now verify the record (note that this will be same as *zone* value (except for certain QTypes)
 
@@ -399,23 +399,21 @@ BOOST_AUTO_TEST_CASE(test_record_types_bad_values) {
       bool success=true;
       BOOST_WARN_EXCEPTION(
         {
-          auto drc = DNSRecordContent::mastermake(q.getCode(), 1, input);
+          auto drc = DNSRecordContent::make(q.getCode(), 1, input);
           pw.startRecord(DNSName("unit.test"), q.getCode());
           drc->toPacket(pw);
           success=false;
         },
-        std::exception, test_dnsrecords_cc_predicate
-      );
+        std::exception, test_dnsrecords_cc_predicate);
       if (success) REC_FAIL_XSUCCESS(q.toString() << " test #" << n << " has unexpectedly passed"); // a bad record was detected when it was supposed not to be detected
     } else {
       BOOST_CHECK_EXCEPTION(
         {
-          auto drc = DNSRecordContent::mastermake(q.getCode(), 1, input);
+          auto drc = DNSRecordContent::make(q.getCode(), 1, input);
           pw.startRecord(DNSName("unit.test"), q.getCode());
           drc->toPacket(pw);
         },
-        std::exception, test_dnsrecords_cc_predicate
-      );
+        std::exception, test_dnsrecords_cc_predicate);
     }
   };
 }
@@ -463,27 +461,27 @@ BOOST_AUTO_TEST_CASE(test_opt_record_out) {
 // special record test, because Unknown record types are the worst
 BOOST_AUTO_TEST_CASE(test_unknown_records_in) {
 
-  auto validUnknown = DNSRecordContent::mastermake(static_cast<QType::typeenum>(65534), QClass::IN, "\\# 1 42");
+  auto validUnknown = DNSRecordContent::make(static_cast<QType::typeenum>(65534), QClass::IN, "\\# 1 42");
 
   // we need at least two parts
-  BOOST_CHECK_THROW(auto notEnoughPartsUnknown = DNSRecordContent::mastermake(static_cast<QType::typeenum>(65534), QClass::IN, "\\#"), MOADNSException);
+  BOOST_CHECK_THROW(auto notEnoughPartsUnknown = DNSRecordContent::make(static_cast<QType::typeenum>(65534), QClass::IN, "\\#"), MOADNSException);
 
   // two parts are OK when the RDATA size is 0, not OK otherwise
-  auto validEmptyUnknown = DNSRecordContent::mastermake(static_cast<QType::typeenum>(65534), QClass::IN, "\\# 0");
-  BOOST_CHECK_THROW(auto twoPartsNotZeroUnknown = DNSRecordContent::mastermake(static_cast<QType::typeenum>(65534), QClass::IN, "\\# 1"), MOADNSException);
+  auto validEmptyUnknown = DNSRecordContent::make(static_cast<QType::typeenum>(65534), QClass::IN, "\\# 0");
+  BOOST_CHECK_THROW(auto twoPartsNotZeroUnknown = DNSRecordContent::make(static_cast<QType::typeenum>(65534), QClass::IN, "\\# 1"), MOADNSException);
 
   // the first part has to be "\#"
-  BOOST_CHECK_THROW(auto invalidFirstPartUnknown = DNSRecordContent::mastermake(static_cast<QType::typeenum>(65534), QClass::IN, "\\$ 0"), MOADNSException);
+  BOOST_CHECK_THROW(auto invalidFirstPartUnknown = DNSRecordContent::make(static_cast<QType::typeenum>(65534), QClass::IN, "\\$ 0"), MOADNSException);
 
   // RDATA length is not even
-  BOOST_CHECK_THROW(auto unevenUnknown = DNSRecordContent::mastermake(static_cast<QType::typeenum>(65534), QClass::IN, "\\# 1 A"), MOADNSException);
+  BOOST_CHECK_THROW(auto unevenUnknown = DNSRecordContent::make(static_cast<QType::typeenum>(65534), QClass::IN, "\\# 1 A"), MOADNSException);
 
   // RDATA length is not equal to the expected size
-  BOOST_CHECK_THROW(auto wrongRDATASizeUnknown = DNSRecordContent::mastermake(static_cast<QType::typeenum>(65534), QClass::IN, "\\# 2 AA"), MOADNSException);
+  BOOST_CHECK_THROW(auto wrongRDATASizeUnknown = DNSRecordContent::make(static_cast<QType::typeenum>(65534), QClass::IN, "\\# 2 AA"), MOADNSException);
 
   // RDATA is invalid (invalid hex value)
   try {
-    auto invalidRDATAUnknown = DNSRecordContent::mastermake(static_cast<QType::typeenum>(65534), QClass::IN, "\\# 1 JJ");
+    auto invalidRDATAUnknown = DNSRecordContent::make(static_cast<QType::typeenum>(65534), QClass::IN, "\\# 1 JJ");
     // we should not reach that code
     BOOST_CHECK(false);
     // but if we do let's see what we got (likely what was left over on the stack)
@@ -498,28 +496,27 @@ BOOST_AUTO_TEST_CASE(test_unknown_records_in) {
 // test that we reject invalid SVCB escaping
 BOOST_AUTO_TEST_CASE(test_svcb_records_in) {
 
-  BOOST_CHECK_THROW(auto invalidSVCB1=DNSRecordContent::mastermake(QType::SVCB, QClass::IN, R"FOO(1 . alpn=foo\\)FOO"), std::runtime_error);
-
+  BOOST_CHECK_THROW(auto invalidSVCB1 = DNSRecordContent::make(QType::SVCB, QClass::IN, R"FOO(1 . alpn=foo\\)FOO"), std::runtime_error);
 }
 
 // special record test, because EUI are odd
 BOOST_AUTO_TEST_CASE(test_eui_records_in) {
 
-  auto validEUI48=DNSRecordContent::mastermake(QType::EUI48, QClass::IN, "00-00-5e-00-53-2a");
+  auto validEUI48 = DNSRecordContent::make(QType::EUI48, QClass::IN, "00-00-5e-00-53-2a");
 
-  BOOST_CHECK_THROW(auto invalidEUI48=DNSRecordContent::mastermake(QType::EUI48, QClass::IN, "00-00-5e-00-53-"), MOADNSException);
+  BOOST_CHECK_THROW(auto invalidEUI48 = DNSRecordContent::make(QType::EUI48, QClass::IN, "00-00-5e-00-53-"), MOADNSException);
 
-  auto validEUI64=DNSRecordContent::mastermake(QType::EUI64, QClass::IN, "00-00-5e-ef-10-00-00-2a");
+  auto validEUI64 = DNSRecordContent::make(QType::EUI64, QClass::IN, "00-00-5e-ef-10-00-00-2a");
 
-  BOOST_CHECK_THROW(auto invalidEUI64=DNSRecordContent::mastermake(QType::EUI64, QClass::IN, "00-00-5e-ef-10-00-00-"), MOADNSException);
+  BOOST_CHECK_THROW(auto invalidEUI64 = DNSRecordContent::make(QType::EUI64, QClass::IN, "00-00-5e-ef-10-00-00-"), MOADNSException);
 }
 
 // special record test, because LOC is weird
 BOOST_AUTO_TEST_CASE(test_loc_records_in) {
 
-  auto validLOC=DNSRecordContent::mastermake(QType::LOC, QClass::IN, "52 22 23.000 N 4 53 32.000 E -2.00m 0.00m 10000m 10m");
+  auto validLOC = DNSRecordContent::make(QType::LOC, QClass::IN, "52 22 23.000 N 4 53 32.000 E -2.00m 0.00m 10000m 10m");
 
-  BOOST_CHECK_THROW(auto invalidLOC=DNSRecordContent::mastermake(QType::LOC, QClass::IN, "52 22 23.000 N"), MOADNSException);
+  BOOST_CHECK_THROW(auto invalidLOC = DNSRecordContent::make(QType::LOC, QClass::IN, "52 22 23.000 N"), MOADNSException);
 
   vector<uint8_t> packet;
   DNSPacketWriter writer(packet, DNSName("powerdns.com."), QType::LOC, QClass::IN, 0);
@@ -537,7 +534,7 @@ BOOST_AUTO_TEST_CASE(test_loc_records_in) {
 BOOST_AUTO_TEST_CASE(test_nsec_records_in) {
 
   {
-    auto validNSEC=DNSRecordContent::mastermake(QType::NSEC, QClass::IN, "host.example.com. A MX RRSIG NSEC TYPE1234");
+    auto validNSEC = DNSRecordContent::make(QType::NSEC, QClass::IN, "host.example.com. A MX RRSIG NSEC TYPE1234");
 
     vector<uint8_t> packet;
     DNSPacketWriter writer(packet, DNSName("powerdns.com."), QType::NSEC, QClass::IN, 0);
@@ -552,7 +549,7 @@ BOOST_AUTO_TEST_CASE(test_nsec_records_in) {
   }
 
   {
-    auto validNSEC3=DNSRecordContent::mastermake(QType::NSEC3, QClass::IN, "1 1 12 aabbccdd 2vptu5timamqttgl4luu9kg21e0aor3s A RRSIG");
+    auto validNSEC3 = DNSRecordContent::make(QType::NSEC3, QClass::IN, "1 1 12 aabbccdd 2vptu5timamqttgl4luu9kg21e0aor3s A RRSIG");
 
     vector<uint8_t> packet;
     DNSPacketWriter writer(packet, DNSName("powerdns.com."), QType::NSEC3, QClass::IN, 0);
@@ -567,7 +564,7 @@ BOOST_AUTO_TEST_CASE(test_nsec_records_in) {
   }
 
   {
-    auto validNSEC3PARAM=DNSRecordContent::mastermake(QType::NSEC3PARAM, QClass::IN, "1 0 12 aabbccdd");
+    auto validNSEC3PARAM = DNSRecordContent::make(QType::NSEC3PARAM, QClass::IN, "1 0 12 aabbccdd");
 
     vector<uint8_t> packet;
     DNSPacketWriter writer(packet, DNSName("powerdns.com."), QType::NSEC3PARAM, QClass::IN, 0);
@@ -585,7 +582,7 @@ BOOST_AUTO_TEST_CASE(test_nsec_records_in) {
 BOOST_AUTO_TEST_CASE(test_nsec_records_types) {
 
   {
-    auto validNSEC = DNSRecordContent::mastermake(QType::NSEC, QClass::IN, "host.example.com. A MX RRSIG NSEC TYPE1234");
+    auto validNSEC = DNSRecordContent::make(QType::NSEC, QClass::IN, "host.example.com. A MX RRSIG NSEC TYPE1234");
     auto nsecContent = std::dynamic_pointer_cast<NSECRecordContent>(validNSEC);
     BOOST_REQUIRE(nsecContent);
 
@@ -613,7 +610,7 @@ BOOST_AUTO_TEST_CASE(test_nsec_records_types) {
 }
 
 BOOST_AUTO_TEST_CASE(test_nsec_invalid_bitmap_len) {
-  auto validNSEC = DNSRecordContent::mastermake(QType::NSEC, QClass::IN, "host.example.com. A MX RRSIG NSEC AAAA NSEC3 TYPE1234 TYPE65535");
+  auto validNSEC = DNSRecordContent::make(QType::NSEC, QClass::IN, "host.example.com. A MX RRSIG NSEC AAAA NSEC3 TYPE1234 TYPE65535");
   const DNSName powerdnsName("powerdns.com.");
 
   vector<uint8_t> packet;
@@ -637,7 +634,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_records_types) {
 
   {
     const std::string str = "1 1 12 aabbccdd 2vptu5timamqttgl4luu9kg21e0aor3s a mx rrsig nsec3 type1234 type65535";
-    auto validNSEC3 = DNSRecordContent::mastermake(QType::NSEC3, QClass::IN, str);
+    auto validNSEC3 = DNSRecordContent::make(QType::NSEC3, QClass::IN, str);
     auto nsec3Content = std::dynamic_pointer_cast<NSEC3RecordContent>(validNSEC3);
     BOOST_REQUIRE(nsec3Content);
 
@@ -677,7 +674,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_records_types) {
     const std::string salt = "aabbccdd";
     const std::string hash =  "2vptu5timamqttgl4luu9kg21e0aor3s";
     const std::string str = "1 1 12 " + salt + " " + hash;
-    auto validNSEC3=DNSRecordContent::mastermake(QType::NSEC3, QClass::IN, str);
+    auto validNSEC3 = DNSRecordContent::make(QType::NSEC3, QClass::IN, str);
 
     vector<uint8_t> packet;
     DNSPacketWriter writer(packet, qname, QType::NSEC3, QClass::IN, 0);
index 63d78ea17856dddb5f68d2651225ca711d6f3229..48127d3cd6534f6fc59c5a4b554bef049a34ab09 100644 (file)
 BOOST_AUTO_TEST_SUITE(test_ixfr_cc)
 
 BOOST_AUTO_TEST_CASE(test_ixfr_rfc1995_axfr) {
-  const ComboAddress master("[2001:DB8::1]:53");
+  const ComboAddress primary("[2001:DB8::1]:53");
   const DNSName zone("JAIN.AD.JP.");
 
-  auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
+  auto primarySOA = DNSRecordContent::make(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   vector<DNSRecord> records;
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::NS, "NS.JAIN.AD.JP.");
@@ -25,7 +25,7 @@ BOOST_AUTO_TEST_CASE(test_ixfr_rfc1995_axfr) {
   addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "192.41.197.2");
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
 
-  auto ret = processIXFRRecords(master, zone, records, std::dynamic_pointer_cast<SOARecordContent>(masterSOA));
+  auto ret = processIXFRRecords(primary, zone, records, std::dynamic_pointer_cast<SOARecordContent>(primarySOA));
   BOOST_CHECK_EQUAL(ret.size(), 1U);
   BOOST_CHECK_EQUAL(ret.at(0).first.size(), 0U);
   BOOST_REQUIRE_EQUAL(ret.at(0).second.size(), records.size());
@@ -35,10 +35,10 @@ BOOST_AUTO_TEST_CASE(test_ixfr_rfc1995_axfr) {
 }
 
 BOOST_AUTO_TEST_CASE(test_ixfr_rfc1995_incremental) {
-  const ComboAddress master("[2001:DB8::1]:53");
+  const ComboAddress primary("[2001:DB8::1]:53");
   const DNSName zone("JAIN.AD.JP.");
 
-  auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
+  auto primarySOA = DNSRecordContent::make(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   vector<DNSRecord> records;
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 1 600 600 3600000 604800");
@@ -52,7 +52,7 @@ BOOST_AUTO_TEST_CASE(test_ixfr_rfc1995_incremental) {
   addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.3");
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
 
-  auto ret = processIXFRRecords(master, zone, records, std::dynamic_pointer_cast<SOARecordContent>(masterSOA));
+  auto ret = processIXFRRecords(primary, zone, records, std::dynamic_pointer_cast<SOARecordContent>(primarySOA));
   // two sequences
   BOOST_CHECK_EQUAL(ret.size(), 2U);
   // the first one has one removal, two additions (plus the corresponding SOA removal/addition)
@@ -82,10 +82,10 @@ BOOST_AUTO_TEST_CASE(test_ixfr_rfc1995_incremental) {
 }
 
 BOOST_AUTO_TEST_CASE(test_ixfr_rfc1995_condensed_incremental) {
-  const ComboAddress master("[2001:DB8::1]:53");
+  const ComboAddress primary("[2001:DB8::1]:53");
   const DNSName zone("JAIN.AD.JP.");
 
-  auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
+  auto primarySOA = DNSRecordContent::make(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   vector<DNSRecord> records;
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 1 600 600 3600000 604800");
@@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE(test_ixfr_rfc1995_condensed_incremental) {
   addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "192.41.197.2");
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
 
-  auto ret = processIXFRRecords(master, zone, records, std::dynamic_pointer_cast<SOARecordContent>(masterSOA));
+  auto ret = processIXFRRecords(primary, zone, records, std::dynamic_pointer_cast<SOARecordContent>(primarySOA));
   // one sequence
   BOOST_CHECK_EQUAL(ret.size(), 1U);
   // it has one removal, two additions (plus the corresponding SOA removal/addition)
@@ -113,10 +113,10 @@ BOOST_AUTO_TEST_CASE(test_ixfr_rfc1995_condensed_incremental) {
 }
 
 BOOST_AUTO_TEST_CASE(test_ixfr_no_additions_in_first_sequence) {
-  const ComboAddress master("[2001:DB8::1]:53");
+  const ComboAddress primary("[2001:DB8::1]:53");
   const DNSName zone("JAIN.AD.JP.");
 
-  auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
+  auto primarySOA = DNSRecordContent::make(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   vector<DNSRecord> records;
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 1 600 600 3600000 604800");
@@ -128,7 +128,7 @@ BOOST_AUTO_TEST_CASE(test_ixfr_no_additions_in_first_sequence) {
   addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.3");
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
 
-  auto ret = processIXFRRecords(master, zone, records, std::dynamic_pointer_cast<SOARecordContent>(masterSOA));
+  auto ret = processIXFRRecords(primary, zone, records, std::dynamic_pointer_cast<SOARecordContent>(primarySOA));
   // two sequences
   BOOST_CHECK_EQUAL(ret.size(), 2U);
   // the first one has one removal, no additions (plus the corresponding SOA removal/addition)
@@ -156,10 +156,10 @@ BOOST_AUTO_TEST_CASE(test_ixfr_no_additions_in_first_sequence) {
 }
 
 BOOST_AUTO_TEST_CASE(test_ixfr_no_removals_in_first_sequence) {
-  const ComboAddress master("[2001:DB8::1]:53");
+  const ComboAddress primary("[2001:DB8::1]:53");
   const DNSName zone("JAIN.AD.JP.");
 
-  auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
+  auto primarySOA = DNSRecordContent::make(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   vector<DNSRecord> records;
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 1 600 600 3600000 604800");
@@ -172,7 +172,7 @@ BOOST_AUTO_TEST_CASE(test_ixfr_no_removals_in_first_sequence) {
   addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.3");
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
 
-  auto ret = processIXFRRecords(master, zone, records, std::dynamic_pointer_cast<SOARecordContent>(masterSOA));
+  auto ret = processIXFRRecords(primary, zone, records, std::dynamic_pointer_cast<SOARecordContent>(primarySOA));
   // two sequences
   BOOST_CHECK_EQUAL(ret.size(), 2U);
   // the first one has no removal, two additions (plus the corresponding SOA removal/addition)
@@ -201,15 +201,15 @@ BOOST_AUTO_TEST_CASE(test_ixfr_no_removals_in_first_sequence) {
 }
 
 BOOST_AUTO_TEST_CASE(test_ixfr_same_serial) {
-  const ComboAddress master("[2001:DB8::1]:53");
+  const ComboAddress primary("[2001:DB8::1]:53");
   const DNSName zone("JAIN.AD.JP.");
 
-  auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
+  auto primarySOA = DNSRecordContent::make(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   vector<DNSRecord> records;
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
 
-  auto ret = processIXFRRecords(master, zone, records, std::dynamic_pointer_cast<SOARecordContent>(masterSOA));
+  auto ret = processIXFRRecords(primary, zone, records, std::dynamic_pointer_cast<SOARecordContent>(primarySOA));
 
   // this is actually an empty AXFR
   BOOST_CHECK_EQUAL(ret.size(), 1U);
@@ -222,32 +222,33 @@ BOOST_AUTO_TEST_CASE(test_ixfr_same_serial) {
 }
 
 BOOST_AUTO_TEST_CASE(test_ixfr_invalid_no_records) {
-  const ComboAddress master("[2001:DB8::1]:53");
+  const ComboAddress primary("[2001:DB8::1]:53");
   const DNSName zone("JAIN.AD.JP.");
 
-  auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
+  auto primarySOA = DNSRecordContent::make(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   vector<DNSRecord> records;
 
-  auto ret = processIXFRRecords(master, zone, records, std::dynamic_pointer_cast<SOARecordContent>(masterSOA));
+  auto ret = processIXFRRecords(primary, zone, records, std::dynamic_pointer_cast<SOARecordContent>(primarySOA));
   BOOST_CHECK_EQUAL(ret.size(), 0U);
 }
 
-BOOST_AUTO_TEST_CASE(test_ixfr_invalid_no_master_soa) {
-  const ComboAddress master("[2001:DB8::1]:53");
+BOOST_AUTO_TEST_CASE(test_ixfr_invalid_no_primary_soa)
+{
+  const ComboAddress primary("[2001:DB8::1]:53");
   const DNSName zone("JAIN.AD.JP.");
 ;
   vector<DNSRecord> records;
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
 
-  auto ret = processIXFRRecords(master, zone, records, nullptr);
+  auto ret = processIXFRRecords(primary, zone, records, nullptr);
   BOOST_CHECK_EQUAL(ret.size(), 0U);
 }
 
 BOOST_AUTO_TEST_CASE(test_ixfr_invalid_no_trailing_soa) {
-  const ComboAddress master("[2001:DB8::1]:53");
+  const ComboAddress primary("[2001:DB8::1]:53");
   const DNSName zone("JAIN.AD.JP.");
 
-  auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
+  auto primarySOA = DNSRecordContent::make(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   vector<DNSRecord> records;
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 1 600 600 3600000 604800");
@@ -256,27 +257,27 @@ BOOST_AUTO_TEST_CASE(test_ixfr_invalid_no_trailing_soa) {
   addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.3");
   addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "192.41.197.2");
 
-  BOOST_CHECK_THROW(processIXFRRecords(master, zone, records, std::dynamic_pointer_cast<SOARecordContent>(masterSOA)), std::runtime_error);
+  BOOST_CHECK_THROW(processIXFRRecords(primary, zone, records, std::dynamic_pointer_cast<SOARecordContent>(primarySOA)), std::runtime_error);
 }
 
 BOOST_AUTO_TEST_CASE(test_ixfr_invalid_no_soa_after_removals) {
-  const ComboAddress master("[2001:DB8::1]:53");
+  const ComboAddress primary("[2001:DB8::1]:53");
   const DNSName zone("JAIN.AD.JP.");
 
-  auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
+  auto primarySOA = DNSRecordContent::make(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   vector<DNSRecord> records;
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 1 600 600 3600000 604800");
   addRecordToList(records, DNSName("NEZU.JAIN.AD.JP."), QType::A, "133.69.136.5");
 
-  BOOST_CHECK_THROW(processIXFRRecords(master, zone, records, std::dynamic_pointer_cast<SOARecordContent>(masterSOA)), std::runtime_error);
+  BOOST_CHECK_THROW(processIXFRRecords(primary, zone, records, std::dynamic_pointer_cast<SOARecordContent>(primarySOA)), std::runtime_error);
 }
 
 BOOST_AUTO_TEST_CASE(test_ixfr_mismatching_serial_before_and_after_additions) {
-  const ComboAddress master("[2001:DB8::1]:53");
+  const ComboAddress primary("[2001:DB8::1]:53");
   const DNSName zone("JAIN.AD.JP.");
 
-  auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
+  auto primarySOA = DNSRecordContent::make(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   vector<DNSRecord> records;
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 1 600 600 3600000 604800");
@@ -286,14 +287,14 @@ BOOST_AUTO_TEST_CASE(test_ixfr_mismatching_serial_before_and_after_additions) {
   addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "192.41.197.2");
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
 
-  BOOST_CHECK_THROW(processIXFRRecords(master, zone, records, std::dynamic_pointer_cast<SOARecordContent>(masterSOA)), std::runtime_error);
+  BOOST_CHECK_THROW(processIXFRRecords(primary, zone, records, std::dynamic_pointer_cast<SOARecordContent>(primarySOA)), std::runtime_error);
 }
 
 BOOST_AUTO_TEST_CASE(test_ixfr_trailing_record_after_end) {
-  const ComboAddress master("[2001:DB8::1]:53");
+  const ComboAddress primary("[2001:DB8::1]:53");
   const DNSName zone("JAIN.AD.JP.");
 
-  auto masterSOA = DNSRecordContent::mastermake(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
+  auto primarySOA = DNSRecordContent::make(QType::SOA, QClass::IN, "NS.JAIN.AD.JP. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   vector<DNSRecord> records;
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 1 600 600 3600000 604800");
@@ -304,7 +305,7 @@ BOOST_AUTO_TEST_CASE(test_ixfr_trailing_record_after_end) {
   addRecordToList(records, DNSName("JAIN.AD.JP."), QType::SOA, "ns.jain.ad.jp. mohta.jain.ad.jp. 3 600 600 3600000 604800");
   addRecordToList(records, DNSName("JAIN-BB.JAIN.AD.JP."), QType::A, "133.69.136.3");
 
-  BOOST_CHECK_THROW(processIXFRRecords(master, zone, records, std::dynamic_pointer_cast<SOARecordContent>(masterSOA)), std::runtime_error);
+  BOOST_CHECK_THROW(processIXFRRecords(primary, zone, records, std::dynamic_pointer_cast<SOARecordContent>(primarySOA)), std::runtime_error);
 }
 
 BOOST_AUTO_TEST_SUITE_END();
index 0a1dbd8e7c15c3ab6018bb937f0567102d9e509a..f92fedb1748729c3b279f7229b0accedd55675a2 100644 (file)
@@ -350,11 +350,11 @@ static void checkRR(const SignerParams& signer)
     rrc.d_signer = DNSName("example.net.");
     inception = 946684800;
     expire = 1893456000;
-    rrs.insert(DNSRecordContent::mastermake(QType::A, QClass::IN, "192.0.2.1"));
+    rrs.insert(DNSRecordContent::make(QType::A, QClass::IN, "192.0.2.1"));
   }
   else {
     rrc.d_signer = qname;
-    rrs.insert(DNSRecordContent::mastermake(QType::MX, QClass::IN, "10 mail.example.com."));
+    rrs.insert(DNSRecordContent::make(QType::MX, QClass::IN, "10 mail.example.com."));
   }
 
   rrc.d_originalttl = 3600;
index 4a13aafad05004df111b5ea42c6b41fb43d5a5c2..1bde35389a100eb20573dc6fd93f9aba9283e222 100644 (file)
@@ -1053,8 +1053,10 @@ BOOST_AUTO_TEST_CASE(test_multi_backends_best_soa) {
 
     auto testFunction = [](UeberBackend& ub) -> void {
     {
-      auto sbba = dynamic_cast<SimpleBackendBestAuth*>(ub.backends.at(0));
+      auto* sbba = dynamic_cast<SimpleBackendBestAuth*>(ub.backends.at(0).get());
       BOOST_REQUIRE(sbba != nullptr);
+
+      // NOLINTNEXTLINE (clang-analyzer-core.NullDereference): Not sure.
       sbba->d_authLookupCount = 0;
 
       // test getAuth()
index 6392adb25d49bb7a13bfdad04930177688fc2f63..a5981a7e7b6d4781302f88d49d0161b152b733d8 100644 (file)
@@ -19,6 +19,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
+#include <memory>
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 #include "auth-zonecache.hh"
 #include "utility.hh"
 
-
-#include <dlfcn.h>
-#include <string>
-#include <map>
-#include <sys/types.h>
-#include <sstream>
 #include <cerrno>
+#include <dlfcn.h>
+#include <functional>
 #include <iostream>
+#include <map>
 #include <sstream>
-#include <functional>
+#include <string>
+#include <sys/types.h>
 
 #include "dns.hh"
 #include "arguments.hh"
 
 extern StatBag S;
 
-LockGuarded<vector<UeberBackend *>> UeberBackend::d_instances;
+LockGuarded<vector<UeberBackend*>> UeberBackend::d_instances;
 
 // initially we are blocked
-bool UeberBackend::d_go=false;
-bool UeberBackend::s_doANYLookupsOnly=false;
+bool UeberBackend::d_go = false;
+bool UeberBackend::s_doANYLookupsOnly = false;
 std::mutex UeberBackend::d_mut;
 std::condition_variable UeberBackend::d_cond;
 AtomicCounter* UeberBackend::s_backendQueries = nullptr;
 
 //! Loads a module and reports it to all UeberBackend threads
-bool UeberBackend::loadmodule(const string &name)
+bool UeberBackend::loadmodule(const stringname)
 {
-  g_log<<Logger::Warning <<"Loading '"<<name<<"'" << endl;
+  g_log << Logger::Warning << "Loading '" << name << "'" << endl;
 
-  void *dlib=dlopen(name.c_str(), RTLD_NOW);
+  void* dlib = dlopen(name.c_str(), RTLD_NOW);
 
-  if(dlib == nullptr) {
-    g_log<<Logger::Error <<"Unable to load module '"<<name<<"': "<<dlerror() << endl;
+  if (dlib == nullptr) {
+    // NOLINTNEXTLINE(concurrency-mt-unsafe): There's no thread-safe alternative to dlerror().
+    g_log << Logger::Error << "Unable to load module '" << name << "': " << dlerror() << endl;
     return false;
   }
 
@@ -76,18 +76,28 @@ bool UeberBackend::loadmodule(const string &name)
 
 bool UeberBackend::loadModules(const vector<string>& modules, const string& path)
 {
-  for (const auto& module: modules) {
-    bool res;
-    if (module.find('.')==string::npos) {
-      res = UeberBackend::loadmodule(path+"/lib"+module+"backend.so");
-    } else if (module[0]=='/' || (module[0]=='.' && module[1]=='/') || (module[0]=='.' && module[1]=='.')) {
+  for (const auto& module : modules) {
+    bool res = false;
+
+    if (module.find('.') == string::npos) {
+      auto fullPath = path;
+      fullPath += "/lib";
+      fullPath += module;
+      fullPath += "backend.so";
+      res = UeberBackend::loadmodule(fullPath);
+    }
+    else if (module[0] == '/' || (module[0] == '.' && module[1] == '/') || (module[0] == '.' && module[1] == '.')) {
       // absolute or current path
       res = UeberBackend::loadmodule(module);
-    } else {
-      res = UeberBackend::loadmodule(path+"/"+module);
+    }
+    else {
+      auto fullPath = path;
+      fullPath += "/";
+      fullPath += module;
+      res = UeberBackend::loadmodule(fullPath);
     }
 
-    if (res == false) {
+    if (!res) {
       return false;
     }
   }
@@ -110,18 +120,20 @@ void UeberBackend::go()
   d_cond.notify_all();
 }
 
-bool UeberBackend::getDomainInfo(const DNSName &domain, DomainInfo &di, bool getSerial)
+bool UeberBackend::getDomainInfo(const DNSName& domain, DomainInfo& domainInfo, bool getSerial)
 {
-  for(auto backend : backends)
-    if(backend->getDomainInfo(domain, di, getSerial))
+  for (auto& backend : backends) {
+    if (backend->getDomainInfo(domain, domainInfo, getSerial)) {
       return true;
+    }
+  }
   return false;
 }
 
-bool UeberBackend::createDomain(const DNSName &domain, const DomainInfo::DomainKind kind, const vector<ComboAddress> &masters, const string &account)
+bool UeberBackend::createDomain(const DNSName& domain, const DomainInfo::DomainKind kind, const vector<ComboAddress>& primaries, const string& account)
 {
-  for(DNSBackend* mydb :  backends) {
-    if (mydb->createDomain(domain, kind, masters, account)) {
+  for (auto& backend : backends) {
+    if (backend->createDomain(domain, kind, primaries, account)) {
       return true;
     }
   }
@@ -130,55 +142,60 @@ bool UeberBackend::createDomain(const DNSName &domain, const DomainInfo::DomainK
 
 bool UeberBackend::doesDNSSEC()
 {
-  for(auto* db :  backends) {
-    if(db->doesDNSSEC())
+  for (auto& backend : backends) {
+    if (backend->doesDNSSEC()) {
       return true;
+    }
   }
   return false;
 }
 
-bool UeberBackend::addDomainKey(const DNSName& name, const DNSBackend::KeyData& key, int64_t& id)
+bool UeberBackend::addDomainKey(const DNSName& name, const DNSBackend::KeyData& key, int64_t& keyID)
 {
-  id = -1;
-  for(DNSBackend* db :  backends) {
-    if(db->addDomainKey(name, key, id))
+  keyID = -1;
+  for (auto& backend : backends) {
+    if (backend->addDomainKey(name, key, keyID)) {
       return true;
+    }
   }
   return false;
 }
 bool UeberBackend::getDomainKeys(const DNSName& name, std::vector<DNSBackend::KeyData>& keys)
 {
-  for(DNSBackend* db :  backends) {
-    if(db->getDomainKeys(name, keys))
+  for (auto& backend : backends) {
+    if (backend->getDomainKeys(name, keys)) {
       return true;
+    }
   }
   return false;
 }
 
-bool UeberBackend::getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string> >& meta)
+bool UeberBackend::getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string>>& meta)
 {
-  for(DNSBackend* db :  backends) {
-    if(db->getAllDomainMetadata(name, meta))
+  for (auto& backend : backends) {
+    if (backend->getAllDomainMetadata(name, meta)) {
       return true;
+    }
   }
   return false;
 }
 
 bool UeberBackend::getDomainMetadata(const DNSName& name, const std::string& kind, std::vector<std::string>& meta)
 {
-  for(DNSBackend* db :  backends) {
-    if(db->getDomainMetadata(name, kind, meta))
+  for (auto& backend : backends) {
+    if (backend->getDomainMetadata(name, kind, meta)) {
       return true;
+    }
   }
   return false;
 }
 
 bool UeberBackend::getDomainMetadata(const DNSName& name, const std::string& kind, std::string& meta)
 {
-  bool ret;
   meta.clear();
   std::vector<string> tmp;
-  if ((ret = getDomainMetadata(name, kind, tmp)) && !tmp.empty()) {
+  const bool ret = getDomainMetadata(name, kind, tmp);
+  if (ret && !tmp.empty()) {
     meta = *tmp.begin();
   }
   return ret;
@@ -186,9 +203,10 @@ bool UeberBackend::getDomainMetadata(const DNSName& name, const std::string& kin
 
 bool UeberBackend::setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector<std::string>& meta)
 {
-  for(DNSBackend* db :  backends) {
-    if(db->setDomainMetadata(name, kind, meta))
+  for (auto& backend : backends) {
+    if (backend->setDomainMetadata(name, kind, meta)) {
       return true;
+    }
   }
   return false;
 }
@@ -202,63 +220,65 @@ bool UeberBackend::setDomainMetadata(const DNSName& name, const std::string& kin
   return setDomainMetadata(name, kind, tmp);
 }
 
-bool UeberBackend::activateDomainKey(const DNSName& name, unsigned int id)
+bool UeberBackend::activateDomainKey(const DNSName& name, unsigned int keyID)
 {
-  for(DNSBackend* db :  backends) {
-    if(db->activateDomainKey(name, id))
+  for (auto& backend : backends) {
+    if (backend->activateDomainKey(name, keyID)) {
       return true;
+    }
   }
   return false;
 }
 
-bool UeberBackend::deactivateDomainKey(const DNSName& name, unsigned int id)
+bool UeberBackend::deactivateDomainKey(const DNSName& name, unsigned int keyID)
 {
-  for(DNSBackend* db :  backends) {
-    if(db->deactivateDomainKey(name, id))
+  for (auto& backend : backends) {
+    if (backend->deactivateDomainKey(name, keyID)) {
       return true;
+    }
   }
   return false;
 }
 
-bool UeberBackend::publishDomainKey(const DNSName& name, unsigned int id)
+bool UeberBackend::publishDomainKey(const DNSName& name, unsigned int keyID)
 {
-  for(DNSBackend* db :  backends) {
-    if(db->publishDomainKey(name, id))
+  for (auto& backend : backends) {
+    if (backend->publishDomainKey(name, keyID)) {
       return true;
+    }
   }
   return false;
 }
 
-bool UeberBackend::unpublishDomainKey(const DNSName& name, unsigned int id)
+bool UeberBackend::unpublishDomainKey(const DNSName& name, unsigned int keyID)
 {
-  for(DNSBackend* db :  backends) {
-    if(db->unpublishDomainKey(name, id))
+  for (auto& backend : backends) {
+    if (backend->unpublishDomainKey(name, keyID)) {
       return true;
+    }
   }
   return false;
 }
 
-
-bool UeberBackend::removeDomainKey(const DNSName& name, unsigned int id)
+bool UeberBackend::removeDomainKey(const DNSName& name, unsigned int keyID)
 {
-  for(DNSBackend* db :  backends) {
-    if(db->removeDomainKey(name, id))
+  for (auto& backend : backends) {
+    if (backend->removeDomainKey(name, keyID)) {
       return true;
+    }
   }
   return false;
 }
 
-
-
 void UeberBackend::reload()
 {
-  for (auto & backend : backends)
-  {
+  for (auto& backend : backends) {
     backend->reload();
   }
 }
 
-void UeberBackend::updateZoneCache() {
+void UeberBackend::updateZoneCache()
+{
   if (!g_zoneCache.isEnabled()) {
     return;
   }
@@ -266,58 +286,166 @@ void UeberBackend::updateZoneCache() {
   vector<std::tuple<DNSName, int>> zone_indices;
   g_zoneCache.setReplacePending();
 
-  for (vector<DNSBackend*>::iterator i = backends.begin(); i != backends.end(); ++i )
-  {
+  for (auto& backend : backends) {
     vector<DomainInfo> zones;
-    (*i)->getAllDomains(&zones, false, true);
-    for(auto& di: zones) {
-      zone_indices.emplace_back(std::move(di.zone), (int)di.id); // this cast should not be necessary
+    backend->getAllDomains(&zones, false, true);
+    for (auto& domainInfo : zones) {
+      zone_indices.emplace_back(std::move(domainInfo.zone), (int)domainInfo.id); // this cast should not be necessary
     }
   }
   g_zoneCache.replace(zone_indices);
 }
 
-void UeberBackend::rediscover(string *status)
+void UeberBackend::rediscover(stringstatus)
 {
-  for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
-  {
+  for (auto backend = backends.begin(); backend != backends.end(); ++backend) {
     string tmpstr;
-    ( *i )->rediscover(&tmpstr);
-    if(status) 
-      *status+=tmpstr + (i!=backends.begin() ? "\n" : "");
+    (*backend)->rediscover(&tmpstr);
+    if (status != nullptr) {
+      *status += tmpstr + (backend != backends.begin() ? "\n" : "");
+    }
   }
 
   updateZoneCache();
 }
 
-
-void UeberBackend::getUnfreshSlaveInfos(vector<DomainInfo>* domains)
+void UeberBackend::getUnfreshSecondaryInfos(vector<DomainInfo>* domains)
 {
-  for (auto & backend : backends)
-  {
-    backend->getUnfreshSlaveInfos( domains );
-  }  
+  for (auto& backend : backends) {
+    backend->getUnfreshSecondaryInfos(domains);
+  }
 }
 
-void UeberBackend::getUpdatedMasters(vector<DomainInfo>& domains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes)
+void UeberBackend::getUpdatedPrimaries(vector<DomainInfo>& domains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes)
 {
-  for (auto & backend : backends)
-  {
-    backend->getUpdatedMasters(domains, catalogs, catalogHashes);
+  for (auto& backend : backends) {
+    backend->getUpdatedPrimaries(domains, catalogs, catalogHashes);
   }
 }
 
 bool UeberBackend::inTransaction()
 {
-  for (auto* b : backends )
-  {
-    if(b->inTransaction())
+  for (auto& backend : backends) {
+    if (backend->inTransaction()) {
       return true;
+    }
   }
   return false;
 }
 
-bool UeberBackend::getAuth(const DNSName &target, const QType& qtype, SOAData* sd, bool cachedOk)
+bool UeberBackend::fillSOAFromZoneRecord(DNSName& shorter, const int zoneId, SOAData* const soaData)
+{
+  // Zone exists in zone cache, directly look up SOA.
+  lookup(QType(QType::SOA), shorter, zoneId, nullptr);
+
+  DNSZoneRecord zoneRecord;
+  if (!get(zoneRecord)) {
+    DLOG(g_log << Logger::Info << "Backend returned no SOA for zone '" << shorter.toLogString() << "', which it reported as existing " << endl);
+    return false;
+  }
+
+  if (zoneRecord.dr.d_name != shorter) {
+    throw PDNSException("getAuth() returned an SOA for the wrong zone. Zone '" + zoneRecord.dr.d_name.toLogString() + "' is not equal to looked up zone '" + shorter.toLogString() + "'");
+  }
+
+  // Fill soaData.
+  soaData->qname = zoneRecord.dr.d_name;
+
+  try {
+    fillSOAData(zoneRecord, *soaData);
+  }
+  catch (...) {
+    g_log << Logger::Warning << "Backend returned a broken SOA for zone '" << shorter.toLogString() << "'" << endl;
+
+    while (get(zoneRecord)) {
+      ;
+    }
+
+    return false;
+  }
+
+  soaData->db = backends.size() == 1 ? backends.begin()->get() : nullptr;
+
+  // Leave database handle in a consistent state.
+  while (get(zoneRecord)) {
+    ;
+  }
+
+  return true;
+}
+
+UeberBackend::CacheResult UeberBackend::fillSOAFromCache(SOAData* soaData, DNSName& shorter)
+{
+  auto cacheResult = cacheHas(d_question, d_answers);
+
+  if (cacheResult == CacheResult::Hit && !d_answers.empty() && d_cache_ttl != 0U) {
+    DLOG(g_log << Logger::Error << "has pos cache entry: " << shorter << endl);
+    fillSOAData(d_answers[0], *soaData);
+
+    soaData->db = backends.size() == 1 ? backends.begin()->get() : nullptr;
+    soaData->qname = shorter;
+  }
+  else if (cacheResult == CacheResult::NegativeMatch && d_negcache_ttl != 0U) {
+    DLOG(g_log << Logger::Error << "has neg cache entry: " << shorter << endl);
+  }
+
+  return cacheResult;
+}
+
+static std::vector<std::unique_ptr<DNSBackend>>::iterator findBestMatchingBackend(std::vector<std::unique_ptr<DNSBackend>>& backends, std::vector<std::pair<std::size_t, SOAData>>& bestMatches, const DNSName& shorter, SOAData* soaData)
+{
+  auto backend = backends.begin();
+  for (auto bestMatch = bestMatches.begin(); backend != backends.end() && bestMatch != bestMatches.end(); ++backend, ++bestMatch) {
+
+    DLOG(g_log << Logger::Error << "backend: " << backend - backends.begin() << ", qname: " << shorter << endl);
+
+    if (bestMatch->first < shorter.wirelength()) {
+      DLOG(g_log << Logger::Error << "skipped, we already found a shorter best match in this backend: " << bestMatch->second.qname << endl);
+      continue;
+    }
+
+    if (bestMatch->first == shorter.wirelength()) {
+      DLOG(g_log << Logger::Error << "use shorter best match: " << bestMatch->second.qname << endl);
+      *soaData = bestMatch->second;
+      break;
+    }
+
+    DLOG(g_log << Logger::Error << "lookup: " << shorter << endl);
+
+    if ((*backend)->getAuth(shorter, soaData)) {
+      DLOG(g_log << Logger::Error << "got: " << soaData->qname << endl);
+
+      if (!soaData->qname.empty() && !shorter.isPartOf(soaData->qname)) {
+        throw PDNSException("getAuth() returned an SOA for the wrong zone. Zone '" + soaData->qname.toLogString() + "' is not part of '" + shorter.toLogString() + "'");
+      }
+
+      bestMatch->first = soaData->qname.wirelength();
+      bestMatch->second = *soaData;
+
+      if (soaData->qname == shorter) {
+        break;
+      }
+    }
+    else {
+      DLOG(g_log << Logger::Error << "no match for: " << shorter << endl);
+    }
+  }
+
+  return backend;
+}
+
+static bool foundTarget(const DNSName& target, const DNSName& shorter, const QType& qtype, [[maybe_unused]] SOAData* soaData, const bool found)
+{
+  if (found == (qtype == QType::DS) || target != shorter) {
+    DLOG(g_log << Logger::Error << "found: " << soaData->qname << endl);
+    return true;
+  }
+
+  DLOG(g_log << Logger::Error << "chasing next: " << soaData->qname << endl);
+  return false;
+}
+
+bool UeberBackend::getAuth(const DNSName& target, const QType& qtype, SOAData* soaData, bool cachedOk)
 {
   // A backend can respond to our authority request with the 'best' match it
   // has. For example, when asked for a.b.c.example.com. it might respond with
@@ -325,47 +453,31 @@ bool UeberBackend::getAuth(const DNSName &target, const QType& qtype, SOAData* s
   // of them has a more specific zone but don't bother asking this specific
   // backend again for b.c.example.com., c.example.com. and example.com.
   // If a backend has no match it may respond with an empty qname.
+
   bool found = false;
-  int cstat;
   DNSName shorter(target);
-  vector<pair<size_t, SOAData> > bestmatch (backends.size(), pair(target.wirelength()+1, SOAData()));
-  do {
+  vector<pair<size_t, SOAData>> bestMatches(backends.size(), pair(target.wirelength() + 1, SOAData()));
+
+  bool first = true;
+  while (first || shorter.chopOff()) {
+    first = false;
+
     int zoneId{-1};
-    if(cachedOk && g_zoneCache.isEnabled()) {
+
+    if (cachedOk && g_zoneCache.isEnabled()) {
       if (g_zoneCache.getEntry(shorter, zoneId)) {
-        // Zone exists in zone cache, directly look up SOA.
-        DNSZoneRecord zr;
-        lookup(QType(QType::SOA), shorter, zoneId, nullptr);
-        if (!get(zr)) {
-          DLOG(g_log << Logger::Info << "Backend returned no SOA for zone '" << shorter.toLogString() << "', which it reported as existing " << endl);
-          continue;
-        }
-        if (zr.dr.d_name != shorter) {
-          throw PDNSException("getAuth() returned an SOA for the wrong zone. Zone '"+zr.dr.d_name.toLogString()+"' is not equal to looked up zone '"+shorter.toLogString()+"'");
-        }
-        // fill sd
-        sd->qname = zr.dr.d_name;
-        try {
-          fillSOAData(zr, *sd);
-        }
-        catch (...) {
-          g_log << Logger::Warning << "Backend returned a broken SOA for zone '" << shorter.toLogString() << "'" << endl;
-          while (get(zr))
-            ;
-          continue;
-        }
-        if (backends.size() == 1) {
-          sd->db = *backends.begin();
-        }
-        else {
-          sd->db = nullptr;
+        if (fillSOAFromZoneRecord(shorter, zoneId, soaData)) {
+          if (foundTarget(target, shorter, qtype, soaData, found)) {
+            return true;
+          }
+
+          found = true;
         }
-        // leave database handle in a consistent state
-        while (get(zr))
-          ;
-        goto found;
+
+        continue;
       }
-      // zone does not exist, try again with shorter name
+
+      // Zone does not exist, try again with a shorter name.
       continue;
     }
 
@@ -373,344 +485,311 @@ bool UeberBackend::getAuth(const DNSName &target, const QType& qtype, SOAData* s
     d_question.qname = shorter;
     d_question.zoneId = zoneId;
 
-    // Check cache
-    if(cachedOk && (d_cache_ttl || d_negcache_ttl)) {
-      cstat = cacheHas(d_question,d_answers);
+    // Check cache.
+    if (cachedOk && (d_cache_ttl != 0 || d_negcache_ttl != 0)) {
+      auto cacheResult = fillSOAFromCache(soaData, shorter);
+      if (cacheResult == CacheResult::Hit) {
+        if (foundTarget(target, shorter, qtype, soaData, found)) {
+          return true;
+        }
 
-      if(cstat == 1 && !d_answers.empty() && d_cache_ttl) {
-        DLOG(g_log<<Logger::Error<<"has pos cache entry: "<<shorter<<endl);
-        fillSOAData(d_answers[0], *sd);
+        found = true;
+        continue;
+      }
 
-        if (backends.size() == 1) {
-          sd->db = *backends.begin();
-        } else {
-          sd->db = nullptr;
-        }
-        sd->qname = shorter;
-        goto found;
-      } else if(cstat == 0 && d_negcache_ttl) {
-        DLOG(g_log<<Logger::Error<<"has neg cache entry: "<<shorter<<endl);
+      if (cacheResult == CacheResult::NegativeMatch) {
         continue;
       }
     }
 
-    // Check backends
+    // Check backends.
     {
-      vector<DNSBackend *>::const_iterator i = backends.begin();
-      vector<pair<size_t, SOAData> >::iterator j = bestmatch.begin();
-      for(; i != backends.end() && j != bestmatch.end(); ++i, ++j) {
-
-        DLOG(g_log<<Logger::Error<<"backend: "<<i-backends.begin()<<", qname: "<<shorter<<endl);
-
-        if(j->first < shorter.wirelength()) {
-          DLOG(g_log<<Logger::Error<<"skipped, we already found a shorter best match in this backend: "<<j->second.qname<<endl);
-          continue;
-        } else if(j->first == shorter.wirelength()) {
-          DLOG(g_log<<Logger::Error<<"use shorter best match: "<<j->second.qname<<endl);
-          *sd = j->second;
-          break;
-        } else {
-          DLOG(g_log<<Logger::Error<<"lookup: "<<shorter<<endl);
-          if((*i)->getAuth(shorter, sd)) {
-            DLOG(g_log<<Logger::Error<<"got: "<<sd->qname<<endl);
-            if(!sd->qname.empty() && !shorter.isPartOf(sd->qname)) {
-              throw PDNSException("getAuth() returned an SOA for the wrong zone. Zone '"+sd->qname.toLogString()+"' is not part of '"+shorter.toLogString()+"'");
-            }
-            j->first = sd->qname.wirelength();
-            j->second = *sd;
-            if(sd->qname == shorter) {
-              break;
-            }
-          } else {
-            DLOG(g_log<<Logger::Error<<"no match for: "<<shorter<<endl);
-          }
-        }
-      }
+      auto backend = findBestMatchingBackend(backends, bestMatches, shorter, soaData);
 
       // Add to cache
-      if(i == backends.end()) {
-        if(d_negcache_ttl) {
-          DLOG(g_log<<Logger::Error<<"add neg cache entry:"<<shorter<<endl);
-          d_question.qname=shorter;
+      if (backend == backends.end()) {
+        if (d_negcache_ttl != 0U) {
+          DLOG(g_log << Logger::Error << "add neg cache entry:" << shorter << endl);
+          d_question.qname = shorter;
           addNegCache(d_question);
         }
+
         continue;
-      } else if(d_cache_ttl) {
-        DLOG(g_log<<Logger::Error<<"add pos cache entry: "<<sd->qname<<endl);
+      }
+
+      if (d_cache_ttl != 0) {
+        DLOG(g_log << Logger::Error << "add pos cache entry: " << soaData->qname << endl);
+
         d_question.qtype = QType::SOA;
-        d_question.qname = sd->qname;
+        d_question.qname = soaData->qname;
         d_question.zoneId = zoneId;
 
-        DNSZoneRecord rr;
-        rr.dr.d_name = sd->qname;
-        rr.dr.d_type = QType::SOA;
-        rr.dr.setContent(makeSOAContent(*sd));
-        rr.dr.d_ttl = sd->ttl;
-        rr.domain_id = sd->domain_id;
+        DNSZoneRecord resourceRecord;
+        resourceRecord.dr.d_name = soaData->qname;
+        resourceRecord.dr.d_type = QType::SOA;
+        resourceRecord.dr.setContent(makeSOAContent(*soaData));
+        resourceRecord.dr.d_ttl = soaData->ttl;
+        resourceRecord.domain_id = soaData->domain_id;
 
-        addCache(d_question, {rr});
+        addCache(d_question, {resourceRecord});
       }
     }
 
-found:
-    if(found == (qtype == QType::DS) || target != shorter) {
-      DLOG(g_log<<Logger::Error<<"found: "<<sd->qname<<endl);
+    if (foundTarget(target, shorter, qtype, soaData, found)) {
       return true;
-    } else {
-      DLOG(g_log<<Logger::Error<<"chasing next: "<<sd->qname<<endl);
-      found = true;
     }
 
-  } while(shorter.chopOff());
+    found = true;
+  }
+
   return found;
 }
 
-bool UeberBackend::getSOAUncached(const DNSName &domain, SOAData &sd)
+bool UeberBackend::getSOAUncached(const DNSName& domain, SOAData& soaData)
 {
-  d_question.qtype=QType::SOA;
-  d_question.qname=domain;
-  d_question.zoneId=-1;
+  d_question.qtype = QType::SOA;
+  d_question.qname = domain;
+  d_question.zoneId = -1;
 
-  for(auto backend : backends)
-    if(backend->getSOA(domain, sd)) {
-      if(domain != sd.qname) {
-        throw PDNSException("getSOA() returned an SOA for the wrong zone. Question: '"+domain.toLogString()+"', answer: '"+sd.qname.toLogString()+"'");
+  for (auto& backend : backends) {
+    if (backend->getSOA(domain, soaData)) {
+      if (domain != soaData.qname) {
+        throw PDNSException("getSOA() returned an SOA for the wrong zone. Question: '" + domain.toLogString() + "', answer: '" + soaData.qname.toLogString() + "'");
       }
-      if(d_cache_ttl) {
-        DNSZoneRecord rr;
-        rr.dr.d_name = sd.qname;
-        rr.dr.d_type = QType::SOA;
-        rr.dr.setContent(makeSOAContent(sd));
-        rr.dr.d_ttl = sd.ttl;
-        rr.domain_id = sd.domain_id;
-
-        addCache(d_question, {rr});
-
+      if (d_cache_ttl != 0U) {
+        DNSZoneRecord zoneRecord;
+        zoneRecord.dr.d_name = soaData.qname;
+        zoneRecord.dr.d_type = QType::SOA;
+        zoneRecord.dr.setContent(makeSOAContent(soaData));
+        zoneRecord.dr.d_ttl = soaData.ttl;
+        zoneRecord.domain_id = soaData.domain_id;
+
+        addCache(d_question, {zoneRecord});
       }
       return true;
     }
+  }
 
-  if(d_negcache_ttl)
+  if (d_negcache_ttl != 0U) {
     addNegCache(d_question);
+  }
   return false;
 }
 
-bool UeberBackend::superMasterAdd(const AutoPrimary &primary)
+bool UeberBackend::autoPrimaryAdd(const AutoPrimary& primary)
 {
-  for(auto backend : backends)
-    if(backend->superMasterAdd(primary))
+  for (auto& backend : backends) {
+    if (backend->autoPrimaryAdd(primary)) {
       return true;
+    }
+  }
   return false;
 }
 
-bool UeberBackend::autoPrimaryRemove(const AutoPrimary &primary)
+bool UeberBackend::autoPrimaryRemove(const AutoPrimaryprimary)
 {
-  for(auto backend : backends)
-    if(backend->autoPrimaryRemove(primary))
+  for (auto& backend : backends) {
+    if (backend->autoPrimaryRemove(primary)) {
       return true;
+    }
+  }
   return false;
 }
 
 bool UeberBackend::autoPrimariesList(std::vector<AutoPrimary>& primaries)
 {
-   for(auto backend : backends)
-     if(backend->autoPrimariesList(primaries))
-       return true;
-   return false;
+  for (auto& backend : backends) {
+    if (backend->autoPrimariesList(primaries)) {
+      return true;
+    }
+  }
+  return false;
 }
 
-bool UeberBackend::superMasterBackend(const string &ip, const DNSName &domain, const vector<DNSResourceRecord>&nsset, string *nameserver, string *account, DNSBackend **db)
+bool UeberBackend::autoPrimaryBackend(const string& ip, const DNSName& domain, const vector<DNSResourceRecord>& nsset, string* nameserver, string* account, DNSBackend** dnsBackend)
 {
-  for(auto backend : backends)
-    if(backend->superMasterBackend(ip, domain, nsset, nameserver, account, db))
+  for (auto& backend : backends) {
+    if (backend->autoPrimaryBackend(ip, domain, nsset, nameserver, account, dnsBackend)) {
       return true;
+    }
+  }
   return false;
 }
 
-UeberBackend::UeberBackend(const string &pname)
+UeberBackend::UeberBackend(const stringpname)
 {
   {
     d_instances.lock()->push_back(this); // report to the static list of ourself
   }
 
-  d_negcached=false;
-  d_cached=false;
   d_cache_ttl = ::arg().asNum("query-cache-ttl");
   d_negcache_ttl = ::arg().asNum("negquery-cache-ttl");
-  d_qtype = 0;
-  d_stale = false;
-
-  backends=BackendMakers().all(pname=="key-only");
-}
 
-static void del(DNSBackend* d)
-{
-  delete d;
-}
-
-void UeberBackend::cleanup()
-{
-  {
-    auto instances = d_instances.lock();
-    remove(instances->begin(), instances->end(), this);
-    instances->resize(instances->size()-1);
-  }
-
-  for_each(backends.begin(),backends.end(),del);
+  backends = BackendMakers().all(pname == "key-only");
 }
 
 // returns -1 for miss, 0 for negative match, 1 for hit
-int UeberBackend::cacheHas(const Question &q, vector<DNSZoneRecord> &rrs)
+enum UeberBackend::CacheResult UeberBackend::cacheHas(const Question& question, vector<DNSZoneRecord>& resourceRecords) const
 {
   extern AuthQueryCache QC;
 
-  if(!d_cache_ttl && ! d_negcache_ttl) {
-    return -1;
+  if (d_cache_ttl == 0 && d_negcache_ttl == 0) {
+    return CacheResult::Miss;
   }
 
-  rrs.clear();
+  resourceRecords.clear();
   //  g_log<<Logger::Warning<<"looking up: '"<<q.qname+"'|N|"+q.qtype.getName()+"|"+itoa(q.zoneId)<<endl;
 
-  bool ret=QC.getEntry(q.qname, q.qtype, rrs, q.zoneId);   // think about lowercasing here
-  if(!ret) {
-    return -1;
+  bool ret = QC.getEntry(question.qname, question.qtype, resourceRecords, question.zoneId); // think about lowercasing here
+  if (!ret) {
+    return CacheResult::Miss;
   }
-  if(rrs.empty()) // negatively cached
-    return 0;
-  
-  return 1;
+  if (resourceRecords.empty()) { // negatively cached
+    return CacheResult::NegativeMatch;
+  }
+
+  return CacheResult::Hit;
 }
 
-void UeberBackend::addNegCache(const Question &q)
+void UeberBackend::addNegCache(const Question& question) const
 {
   extern AuthQueryCache QC;
-  if(!d_negcache_ttl)
+  if (d_negcache_ttl == 0) {
     return;
+  }
   // we should also not be storing negative answers if a pipebackend does scopeMask, but we can't pass a negative scopeMask in an empty set!
-  QC.insert(q.qname, q.qtype, vector<DNSZoneRecord>(), d_negcache_ttl, q.zoneId);
+  QC.insert(question.qname, question.qtype, vector<DNSZoneRecord>(), d_negcache_ttl, question.zoneId);
 }
 
-void UeberBackend::addCache(const Question &q, vector<DNSZoneRecord> &&rrs)
+void UeberBackend::addCache(const Question& question, vector<DNSZoneRecord>&& rrs) const
 {
   extern AuthQueryCache QC;
 
-  if(!d_cache_ttl)
+  if (d_cache_ttl == 0) {
     return;
+  }
 
-  for(const auto& rr : rrs) {
-   if (rr.scopeMask)
-     return;
+  for (const auto& resourceRecord : rrs) {
+    if (resourceRecord.scopeMask != 0) {
+      return;
+    }
   }
 
-  QC.insert(q.qname, q.qtype, std::move(rrs), d_cache_ttl, q.zoneId);
+  QC.insert(question.qname, question.qtype, std::move(rrs), d_cache_ttl, question.zoneId);
 }
 
-void UeberBackend::alsoNotifies(const DNSName &domain, set<string> *ips)
+void UeberBackend::alsoNotifies(const DNSName& domain, set<string>* ips)
 {
-  for (auto & backend : backends)
-    backend->alsoNotifies(domain,ips);
+  for (auto& backend : backends) {
+    backend->alsoNotifies(domain, ips);
+  }
 }
 
 UeberBackend::~UeberBackend()
 {
-  DLOG(g_log<<Logger::Error<<"UeberBackend destructor called, removing ourselves from instances, and deleting our backends"<<endl);
-  cleanup();
+  DLOG(g_log << Logger::Error << "UeberBackend destructor called, removing ourselves from instances, and deleting our backends" << endl);
+
+  {
+    auto instances = d_instances.lock();
+    [[maybe_unused]] auto end = remove(instances->begin(), instances->end(), this);
+    instances->resize(instances->size() - 1);
+  }
+
+  backends.clear();
 }
 
 // this handle is more magic than most
-void UeberBackend::lookup(const QType &qtype,const DNSName &qname, int zoneId, DNSPacket *pkt_p)
+void UeberBackend::lookup(const QType& qtype, const DNSName& qname, int zoneId, DNSPacket* pkt_p)
 {
-  if(d_stale) {
-    g_log<<Logger::Error<<"Stale ueberbackend received question, signalling that we want to be recycled"<<endl;
+  if (d_stale) {
+    g_log << Logger::Error << "Stale ueberbackend received question, signalling that we want to be recycled" << endl;
     throw PDNSException("We are stale, please recycle");
   }
 
-  DLOG(g_log<<"UeberBackend received question for "<<qtype<<" of "<<qname<<endl);
+  DLOG(g_log << "UeberBackend received question for " << qtype << " of " << qname << endl);
   if (!d_go) {
-    g_log<<Logger::Error<<"UeberBackend is blocked, waiting for 'go'"<<endl;
+    g_log << Logger::Error << "UeberBackend is blocked, waiting for 'go'" << endl;
     std::unique_lock<std::mutex> l(d_mut);
-    d_cond.wait(l, []{ return d_go == true; });
-    g_log<<Logger::Error<<"Broadcast received, unblocked"<<endl;
+    d_cond.wait(l, [] { return d_go; });
+    g_log << Logger::Error << "Broadcast received, unblocked" << endl;
   }
 
-  d_qtype=qtype.getCode();
+  d_qtype = qtype.getCode();
 
-  d_handle.i=0;
-  d_handle.qtype=s_doANYLookupsOnly ? QType::ANY : qtype;
-  d_handle.qname=qname;
-  d_handle.zoneId=zoneId;
-  d_handle.pkt_p=pkt_p;
+  d_handle.i = 0;
+  d_handle.qtype = s_doANYLookupsOnly ? QType::ANY : qtype;
+  d_handle.qname = qname;
+  d_handle.zoneId = zoneId;
+  d_handle.pkt_p = pkt_p;
 
-  if(!backends.size()) {
-    g_log<<Logger::Error<<"No database backends available - unable to answer questions."<<endl;
-    d_stale=true; // please recycle us!
+  if (backends.empty()) {
+    g_log << Logger::Error << "No database backends available - unable to answer questions." << endl;
+    d_stale = true; // please recycle us!
     throw PDNSException("We are stale, please recycle");
   }
+
+  d_question.qtype = d_handle.qtype;
+  d_question.qname = qname;
+  d_question.zoneId = d_handle.zoneId;
+
+  auto cacheResult = cacheHas(d_question, d_answers);
+  if (cacheResult == CacheResult::Miss) { // nothing
+    //      cout<<"UeberBackend::lookup("<<qname<<"|"<<DNSRecordContent::NumberToType(qtype.getCode())<<"): uncached"<<endl;
+    d_negcached = d_cached = false;
+    d_answers.clear();
+    (d_handle.d_hinterBackend = backends[d_handle.i++].get())->lookup(d_handle.qtype, d_handle.qname, d_handle.zoneId, d_handle.pkt_p);
+    ++(*s_backendQueries);
+  }
+  else if (cacheResult == CacheResult::NegativeMatch) {
+    //      cout<<"UeberBackend::lookup("<<qname<<"|"<<DNSRecordContent::NumberToType(qtype.getCode())<<"): NEGcached"<<endl;
+    d_negcached = true;
+    d_cached = false;
+    d_answers.clear();
+  }
   else {
-    d_question.qtype=d_handle.qtype;
-    d_question.qname=qname;
-    d_question.zoneId=d_handle.zoneId;
-
-    int cstat=cacheHas(d_question, d_answers);
-    if(cstat<0) { // nothing
-      //      cout<<"UeberBackend::lookup("<<qname<<"|"<<DNSRecordContent::NumberToType(qtype.getCode())<<"): uncached"<<endl;
-      d_negcached=d_cached=false;
-      d_answers.clear(); 
-      (d_handle.d_hinterBackend=backends[d_handle.i++])->lookup(d_handle.qtype, d_handle.qname, d_handle.zoneId, d_handle.pkt_p);
-      ++(*s_backendQueries);
-    } 
-    else if(cstat==0) {
-      //      cout<<"UeberBackend::lookup("<<qname<<"|"<<DNSRecordContent::NumberToType(qtype.getCode())<<"): NEGcached"<<endl;
-      d_negcached=true;
-      d_cached=false;
-      d_answers.clear();
-    }
-    else {
-      // cout<<"UeberBackend::lookup("<<qname<<"|"<<DNSRecordContent::NumberToType(qtype.getCode())<<"): CACHED"<<endl;
-      d_negcached=false;
-      d_cached=true;
-      d_cachehandleiter = d_answers.begin();
-    }
+    // cout<<"UeberBackend::lookup("<<qname<<"|"<<DNSRecordContent::NumberToType(qtype.getCode())<<"): CACHED"<<endl;
+    d_negcached = false;
+    d_cached = true;
+    d_cachehandleiter = d_answers.begin();
   }
 
-  d_handle.parent=this;
+  d_handle.parent = this;
 }
 
 void UeberBackend::getAllDomains(vector<DomainInfo>* domains, bool getSerial, bool include_disabled)
 {
-  for (auto & backend : backends)
-  {
+  for (auto& backend : backends) {
     backend->getAllDomains(domains, getSerial, include_disabled);
   }
 }
 
-bool UeberBackend::get(DNSZoneRecord &rr)
+bool UeberBackend::get(DNSZoneRecord& resourceRecord)
 {
   // cout<<"UeberBackend::get(DNSZoneRecord) called"<<endl;
-  if(d_negcached) {
-    return false; 
+  if (d_negcached) {
+    return false;
   }
 
-  if(d_cached) {
-    while(d_cachehandleiter != d_answers.end()) {
-      rr=*d_cachehandleiter++;;
-      if((d_qtype == QType::ANY || rr.dr.d_type == d_qtype)) {
+  if (d_cached) {
+    while (d_cachehandleiter != d_answers.end()) {
+      resourceRecord = *d_cachehandleiter++;
+      if ((d_qtype == QType::ANY || resourceRecord.dr.d_type == d_qtype)) {
         return true;
       }
     }
     return false;
   }
 
-  while(d_handle.get(rr)) {
-    rr.dr.d_place=DNSResourceRecord::ANSWER;
-    d_answers.push_back(rr);
-    if((d_qtype == QType::ANY || rr.dr.d_type == d_qtype)) {
+  while (d_handle.get(resourceRecord)) {
+    resourceRecord.dr.d_place = DNSResourceRecord::ANSWER;
+    d_answers.push_back(resourceRecord);
+    if ((d_qtype == QType::ANY || resourceRecord.dr.d_type == d_qtype)) {
       return true;
     }
   }
 
   // cout<<"end of ueberbackend get, seeing if we should cache"<<endl;
-  if(d_answers.empty()) {
+  if (d_answers.empty()) {
     // cout<<"adding negcache"<<endl;
     addNegCache(d_question);
   }
@@ -726,8 +805,8 @@ bool UeberBackend::get(DNSZoneRecord &rr)
 //
 bool UeberBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content)
 {
-  for (auto* b : backends) {
-    if (b->setTSIGKey(name, algorithm, content)) {
+  for (auto& backend : backends) {
+    if (backend->setTSIGKey(name, algorithm, content)) {
       return true;
     }
   }
@@ -739,8 +818,8 @@ bool UeberBackend::getTSIGKey(const DNSName& name, DNSName& algorithm, string& c
   algorithm.clear();
   content.clear();
 
-  for (auto* b : backends) {
-    if (b->getTSIGKey(name, algorithm, content)) {
+  for (auto& backend : backends) {
+    if (backend->getTSIGKey(name, algorithm, content)) {
       break;
     }
   }
@@ -751,8 +830,8 @@ bool UeberBackend::getTSIGKeys(std::vector<struct TSIGKey>& keys)
 {
   keys.clear();
 
-  for (auto* b : backends) {
-    if (b->getTSIGKeys(keys)) {
+  for (auto& backend : backends) {
+    if (backend->getTSIGKeys(keys)) {
       return true;
     }
   }
@@ -761,8 +840,8 @@ bool UeberBackend::getTSIGKeys(std::vector<struct TSIGKey>& keys)
 
 bool UeberBackend::deleteTSIGKey(const DNSName& name)
 {
-  for (auto* b : backends) {
-    if (b->deleteTSIGKey(name)) {
+  for (auto& backend : backends) {
+    if (backend->deleteTSIGKey(name)) {
       return true;
     }
   }
@@ -771,20 +850,26 @@ bool UeberBackend::deleteTSIGKey(const DNSName& name)
 
 // API Search
 //
-bool UeberBackend::searchRecords(const string& pattern, int maxResults, vector<DNSResourceRecord>& result)
+bool UeberBackend::searchRecords(const string& pattern, size_t maxResults, vector<DNSResourceRecord>& result)
 {
-  bool rc = false;
-  for ( vector< DNSBackend * >::iterator i = backends.begin(); result.size() < static_cast<vector<DNSResourceRecord>::size_type>(maxResults) && i != backends.end(); ++i )
-    if ((*i)->searchRecords(pattern, maxResults - result.size(), result)) rc = true;
-  return rc;
+  bool ret = false;
+  for (auto backend = backends.begin(); result.size() < maxResults && backend != backends.end(); ++backend) {
+    if ((*backend)->searchRecords(pattern, maxResults - result.size(), result)) {
+      ret = true;
+    }
+  }
+  return ret;
 }
 
-bool UeberBackend::searchComments(const string& pattern, int maxResults, vector<Comment>& result)
+bool UeberBackend::searchComments(const string& pattern, size_t maxResults, vector<Comment>& result)
 {
-  bool rc = false;
-  for ( vector< DNSBackend * >::iterator i = backends.begin(); result.size() < static_cast<vector<Comment>::size_type>(maxResults) && i != backends.end(); ++i )
-    if ((*i)->searchComments(pattern, maxResults - result.size(), result)) rc = true;
-  return rc;
+  bool ret = false;
+  for (auto backend = backends.begin(); result.size() < maxResults && backend != backends.end(); ++backend) {
+    if ((*backend)->searchComments(pattern, maxResults - result.size(), result)) {
+      ret = true;
+    }
+  }
+  return ret;
 }
 
 AtomicCounter UeberBackend::handle::instances(0);
@@ -793,11 +878,6 @@ UeberBackend::handle::handle()
 {
   //  g_log<<Logger::Warning<<"Handle instances: "<<instances<<endl;
   ++instances;
-  parent=nullptr;
-  d_hinterBackend=nullptr;
-  pkt_p=nullptr;
-  i=0;
-  zoneId = -1;
 }
 
 UeberBackend::handle::~handle()
@@ -805,31 +885,32 @@ UeberBackend::handle::~handle()
   --instances;
 }
 
-bool UeberBackend::handle::get(DNSZoneRecord &r)
+bool UeberBackend::handle::get(DNSZoneRecord& record)
 {
-  DLOG(g_log << "Ueber get() was called for a "<<qtype<<" record" << endl);
-  bool isMore=false;
-  while(d_hinterBackend && !(isMore=d_hinterBackend->get(r))) { // this backend out of answers
-    if(i<parent->backends.size()) {
-      DLOG(g_log<<"Backend #"<<i<<" of "<<parent->backends.size()
-           <<" out of answers, taking next"<<endl);
-      
-      d_hinterBackend=parent->backends[i++];
-      d_hinterBackend->lookup(qtype,qname,zoneId,pkt_p);
+  DLOG(g_log << "Ueber get() was called for a " << qtype << " record" << endl);
+  bool isMore = false;
+  while (d_hinterBackend != nullptr && !(isMore = d_hinterBackend->get(record))) { // this backend out of answers
+    if (i < parent->backends.size()) {
+      DLOG(g_log << "Backend #" << i << " of " << parent->backends.size()
+                 << " out of answers, taking next" << endl);
+
+      d_hinterBackend = parent->backends[i++].get();
+      d_hinterBackend->lookup(qtype, qname, zoneId, pkt_p);
       ++(*s_backendQueries);
     }
-    else 
+    else {
       break;
+    }
 
-    DLOG(g_log<<"Now asking backend #"<<i<<endl);
+    DLOG(g_log << "Now asking backend #" << i << endl);
   }
 
-  if(!isMore && i==parent->backends.size()) {
-    DLOG(g_log<<"UeberBackend reached end of backends"<<endl);
+  if (!isMore && i == parent->backends.size()) {
+    DLOG(g_log << "UeberBackend reached end of backends" << endl);
     return false;
   }
 
-  DLOG(g_log<<"Found an answering backend - will not try another one"<<endl);
-  i=parent->backends.size(); // don't go on to the next backend
+  DLOG(g_log << "Found an answering backend - will not try another one" << endl);
+  i = parent->backends.size(); // don't go on to the next backend
   return true;
 }
index 93feea5b0fd76ebebabc09d577fa9507103f0aef..be5859c9d47f2aafb26324fa03deaddb7fdde2af 100644 (file)
@@ -36,7 +36,7 @@
 
 /** This is a very magic backend that allows us to load modules dynamically,
     and query them in order. This is persistent over all UeberBackend instantiations
-    across multiple threads. 
+    across multiple threads.
 
     The UeberBackend is transparent for exceptions, which should fall straight through.
 */
 class UeberBackend : public boost::noncopyable
 {
 public:
-  UeberBackend(const string &pname="default");
+  UeberBackend(const string& pname = "default");
   ~UeberBackend();
 
-  bool superMasterBackend(const string &ip, const DNSName &domain, const vector<DNSResourceRecord>&nsset, string *nameserver, string *account, DNSBackend **db);
+  bool autoPrimaryBackend(const string& ip, const DNSName& domain, const vector<DNSResourceRecord>& nsset, string* nameserver, string* account, DNSBackend** dnsBackend);
 
-  bool superMasterAdd(const AutoPrimary &primary);
+  bool autoPrimaryAdd(const AutoPrimary& primary);
   bool autoPrimaryRemove(const struct AutoPrimary& primary);
   bool autoPrimariesList(std::vector<AutoPrimary>& primaries);
 
   /** Tracks all created UeberBackend instances for us. We use this vector to notify
-      existing threads of new modules 
+      existing threads of new modules
   */
-  static LockGuarded<vector<UeberBackend *>> d_instances;
+  static LockGuarded<vector<UeberBackend*>> d_instances;
 
-  static bool loadmodule(const string &name);
+  static bool loadmodule(const stringname);
   static bool loadModules(const vector<string>& modules, const string& path);
 
-  static void go(void);
+  static void go();
 
   /** This contains all registered backends. The DynListener modifies this list for us when
       new modules are loaded */
-  vector<DNSBackend*> backends; 
-
-  void cleanup();
+  vector<std::unique_ptr<DNSBackend>> backends;
 
   //! the very magic handle for UeberBackend questions
   class handle
   {
   public:
-    bool get(DNSZoneRecord &dr);
+    bool get(DNSZoneRecord& record);
     handle();
     ~handle();
 
     //! The UeberBackend class where this handle belongs to
-    UeberBackend *parent;
+    UeberBackend* parent{nullptr};
     //! The current real backend, which is answering questions
-    DNSBackend *d_hinterBackend;
+    DNSBackend* d_hinterBackend{nullptr};
 
     //! DNSPacket who asked this question
-    DNSPacket* pkt_p;
+    DNSPacket* pkt_p{nullptr};
     DNSName qname;
 
     //! Index of the current backend within the backends vector
-    unsigned int i;
+    unsigned int i{0};
     QType qtype;
-    int zoneId;
+    int zoneId{-1};
 
   private:
-
     static AtomicCounter instances;
   };
 
-  void lookup(const QType &, const DNSName &qdomain, int zoneId, DNSPacket *pkt_p=nullptr);
+  void lookup(const QType& qtype, const DNSName& qname, int zoneId, DNSPacket* pkt_p = nullptr);
 
   /** Determines if we are authoritative for a zone, and at what level */
-  bool getAuth(const DNSName &target, const QType &qtype, SOAData* sd, bool cachedOk=true);
+  bool getAuth(const DNSName& target, const QType& qtype, SOAData* soaData, bool cachedOk = true);
   /** Load SOA info from backends, ignoring the cache.*/
-  bool getSOAUncached(const DNSName &domain, SOAData &sd);
-  bool get(DNSZoneRecord &r);
+  bool getSOAUncached(const DNSName& domain, SOAData& soaData);
+  bool get(DNSZoneRecord& resourceRecord);
   void getAllDomains(vector<DomainInfo>* domains, bool getSerial, bool include_disabled);
 
-  void getUnfreshSlaveInfos(vector<DomainInfo>* domains);
-  void getUpdatedMasters(vector<DomainInfo>& domains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes);
-  bool getDomainInfo(const DNSName &domain, DomainInfo &di, bool getSerial=true);
-  bool createDomain(const DNSName &domain, const DomainInfo::DomainKind kind, const vector<ComboAddress> &masters, const string &account);
-  
+  void getUnfreshSecondaryInfos(vector<DomainInfo>* domains);
+  void getUpdatedPrimaries(vector<DomainInfo>& domains, std::unordered_set<DNSName>& catalogs, CatalogHashMap& catalogHashes);
+  bool getDomainInfo(const DNSName& domain, DomainInfo& domainInfo, bool getSerial = true);
+  bool createDomain(const DNSName& domain, DomainInfo::DomainKind kind, const vector<ComboAddress>& primaries, const string& account);
+
   bool doesDNSSEC();
-  bool addDomainKey(const DNSName& name, const DNSBackend::KeyData& key, int64_t& id);
+  bool addDomainKey(const DNSName& name, const DNSBackend::KeyData& key, int64_t& keyID);
   bool getDomainKeys(const DNSName& name, std::vector<DNSBackend::KeyData>& keys);
-  bool getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string> >& meta);
+  bool getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string>>& meta);
   bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector<std::string>& meta);
   bool getDomainMetadata(const DNSName& name, const std::string& kind, std::string& meta);
   bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector<std::string>& meta);
   bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::string& meta);
 
-  bool removeDomainKey(const DNSName& name, unsigned int id);
-  bool activateDomainKey(const DNSName& name, unsigned int id);
-  bool deactivateDomainKey(const DNSName& name, unsigned int id);
-  bool publishDomainKey(const DNSName& name, unsigned int id);
-  bool unpublishDomainKey(const DNSName& name, unsigned int id);
+  bool removeDomainKey(const DNSName& name, unsigned int keyID);
+  bool activateDomainKey(const DNSName& name, unsigned int keyID);
+  bool deactivateDomainKey(const DNSName& name, unsigned int keyID);
+  bool publishDomainKey(const DNSName& name, unsigned int keyID);
+  bool unpublishDomainKey(const DNSName& name, unsigned int keyID);
 
-  void alsoNotifies(const DNSName &domain, set<string> *ips); 
-  void rediscover(string* status=0);
+  void alsoNotifies(const DNSName& domain, set<string>* ips);
+  void rediscover(string* status = nullptr);
   void reload();
 
   bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content);
@@ -134,8 +131,8 @@ public:
   bool getTSIGKeys(std::vector<struct TSIGKey>& keys);
   bool deleteTSIGKey(const DNSName& name);
 
-  bool searchRecords(const string &pattern, int maxResults, vector<DNSResourceRecord>& result);
-  bool searchComments(const string &pattern, int maxResults, vector<Comment>& result);
+  bool searchRecords(const string& pattern, vector<DNSResourceRecord>::size_type maxResults, vector<DNSResourceRecord>& result);
+  bool searchComments(const string& pattern, size_t maxResults, vector<Comment>& result);
 
   void updateZoneCache();
 
@@ -154,19 +151,29 @@ private:
     DNSName qname;
     int zoneId;
     QType qtype;
-  }d_question;
+  } d_question;
 
   unsigned int d_cache_ttl, d_negcache_ttl;
-  uint16_t d_qtype;
+  uint16_t d_qtype{0};
 
-  bool d_negcached;
-  bool d_cached;
+  bool d_negcached{false};
+  bool d_cached{false};
   static AtomicCounter* s_backendQueries;
   static bool d_go;
-  bool d_stale;
+  bool d_stale{false};
   static bool s_doANYLookupsOnly;
 
-  int cacheHas(const Question &q, vector<DNSZoneRecord> &rrs);
-  void addNegCache(const Question &q);
-  void addCache(const Question &q, vector<DNSZoneRecord>&& rrs);
+  enum CacheResult
+  {
+    Miss = -1,
+    NegativeMatch = 0,
+    Hit = 1,
+  };
+
+  CacheResult cacheHas(const Question& question, vector<DNSZoneRecord>& resourceRecords) const;
+  void addNegCache(const Question& question) const;
+  void addCache(const Question& question, vector<DNSZoneRecord>&& rrs) const;
+
+  bool fillSOAFromZoneRecord(DNSName& shorter, int zoneId, SOAData* soaData);
+  CacheResult fillSOAFromCache(SOAData* soaData, DNSName& shorter);
 };
index 20bac3e3498076c0c60baff452747c16b2cc9c2e..9612f75362b692df98b34a1614f616afd71e0d52 100644 (file)
@@ -297,7 +297,7 @@ void AuthWebServer::indexfunction(HttpRequest* req, HttpResponse* resp)
 /** Helper to build a record content as needed. */
 static inline string makeRecordContent(const QType& qtype, const string& content, bool noDot) {
   // noDot: for backend storage, pass true. for API users, pass false.
-  auto drc = DNSRecordContent::mastermake(qtype.getCode(), QClass::IN, content);
+  auto drc = DNSRecordContent::make(qtype.getCode(), QClass::IN, content);
   return drc->getZoneRepresentation(noDot);
 }
 
@@ -313,10 +313,10 @@ static inline string makeBackendRecordContent(const QType& qtype, const string&
 
 static Json::object getZoneInfo(const DomainInfo& di, DNSSECKeeper* dk) {
   string zoneId = apiZoneNameToId(di.zone);
-  vector<string> masters;
-  masters.reserve(di.masters.size());
-  for(const auto& m : di.masters) {
-    masters.push_back(m.toStringWithPortExcept(53));
+  vector<string> primaries;
+  primaries.reserve(di.primaries.size());
+  for (const auto& m : di.primaries) {
+    primaries.push_back(m.toStringWithPortExcept(53));
   }
 
   auto obj = Json::object{
@@ -327,7 +327,7 @@ static Json::object getZoneInfo(const DomainInfo& di, DNSSECKeeper* dk) {
     {"kind", di.getKindString()},
     {"catalog", (!di.catalog.empty() ? di.catalog.toString() : "")},
     {"account", di.account},
-    {"masters", std::move(masters)},
+    {"masters", std::move(primaries)},
     {"serial", (double)di.serial},
     {"notified_serial", (double)di.notified_serial},
     {"last_check", (double)di.last_check}};
@@ -384,21 +384,21 @@ static void fillZone(UeberBackend& B, const DNSName& zonename, HttpResponse* res
   doc["api_rectify"] = (api_rectify == "1");
 
   // TSIG
-  vector<string> tsig_master, tsig_slave;
-  di.backend->getDomainMetadata(zonename, "TSIG-ALLOW-AXFR", tsig_master);
-  di.backend->getDomainMetadata(zonename, "AXFR-MASTER-TSIG", tsig_slave);
+  vector<string> tsig_primary, tsig_secondary;
+  di.backend->getDomainMetadata(zonename, "TSIG-ALLOW-AXFR", tsig_primary);
+  di.backend->getDomainMetadata(zonename, "AXFR-MASTER-TSIG", tsig_secondary);
 
-  Json::array tsig_master_keys;
-  for (const auto& keyname : tsig_master) {
-    tsig_master_keys.push_back(apiZoneNameToId(DNSName(keyname)));
+  Json::array tsig_primary_keys;
+  for (const auto& keyname : tsig_primary) {
+    tsig_primary_keys.push_back(apiZoneNameToId(DNSName(keyname)));
   }
-  doc["master_tsig_key_ids"] = tsig_master_keys;
+  doc["master_tsig_key_ids"] = tsig_primary_keys;
 
-  Json::array tsig_slave_keys;
-  for (const auto& keyname : tsig_slave) {
-    tsig_slave_keys.push_back(apiZoneNameToId(DNSName(keyname)));
+  Json::array tsig_secondary_keys;
+  for (const auto& keyname : tsig_secondary) {
+    tsig_secondary_keys.push_back(apiZoneNameToId(DNSName(keyname)));
   }
-  doc["slave_tsig_key_ids"] = tsig_slave_keys;
+  doc["slave_tsig_key_ids"] = tsig_secondary_keys;
 
   if (shouldDoRRSets(req)) {
     vector<DNSResourceRecord> records;
@@ -652,7 +652,7 @@ static bool isZoneApiRectifyEnabled(const DomainInfo& di) {
   return api_rectify == "1";
 }
 
-static void extractDomainInfoFromDocument(const Json& document, boost::optional<DomainInfo::DomainKind>& kind, boost::optional<vector<ComboAddress>>& masters, boost::optional<DNSName>& catalog, boost::optional<string>& account)
+static void extractDomainInfoFromDocument(const Json& document, boost::optional<DomainInfo::DomainKind>& kind, boost::optional<vector<ComboAddress>>& primaries, boost::optional<DNSName>& catalog, boost::optional<string>& account)
 {
   if (document["kind"].is_string()) {
     kind = DomainInfo::stringToKind(stringFromJson(document, "kind"));
@@ -661,19 +661,19 @@ static void extractDomainInfoFromDocument(const Json& document, boost::optional<
   }
 
   if (document["masters"].is_array()) {
-    masters = vector<ComboAddress>();
+    primaries = vector<ComboAddress>();
     for(const auto& value : document["masters"].array_items()) {
-      string master = value.string_value();
-      if (master.empty())
-        throw ApiException("Master can not be an empty string");
+      string primary = value.string_value();
+      if (primary.empty())
+        throw ApiException("Primary can not be an empty string");
       try {
-        masters->emplace_back(master, 53);
+        primaries->emplace_back(primary, 53);
       } catch (const PDNSException &e) {
-        throw ApiException("Master (" + master + ") is not an IP address: " + e.reason);
+        throw ApiException("Primary (" + primary + ") is not an IP address: " + e.reason);
       }
     }
   } else {
-    masters = boost::none;
+    primaries = boost::none;
   }
 
   if (document["catalog"].is_string()) {
@@ -711,18 +711,18 @@ static void extractJsonTSIGKeyIds(UeberBackend& B, const Json& jsonArray, vector
 // Must be called within backend transaction.
 static void updateDomainSettingsFromDocument(UeberBackend& B, DomainInfo& di, const DNSName& zonename, const Json& document, bool zoneWasModified) {
   boost::optional<DomainInfo::DomainKind> kind;
-  boost::optional<vector<ComboAddress>> masters;
+  boost::optional<vector<ComboAddress>> primaries;
   boost::optional<DNSName> catalog;
   boost::optional<string> account;
 
-  extractDomainInfoFromDocument(document, kind, masters, catalog, account);
+  extractDomainInfoFromDocument(document, kind, primaries, catalog, account);
 
   if (kind) {
     di.backend->setKind(zonename, *kind);
     di.kind = *kind;
   }
-  if (masters) {
-    di.backend->setMasters(zonename, *masters);
+  if (primaries) {
+    di.backend->setPrimaries(zonename, *primaries);
   }
   if (catalog) {
     di.backend->setCatalog(zonename, *catalog);
@@ -860,14 +860,14 @@ static void updateDomainSettingsFromDocument(UeberBackend& B, DomainInfo& di, co
     vector<string> metadata;
     extractJsonTSIGKeyIds(B, document["master_tsig_key_ids"], metadata);
     if (!di.backend->setDomainMetadata(zonename, "TSIG-ALLOW-AXFR", metadata)) {
-      throw HttpInternalServerErrorException("Unable to set new TSIG master keys for zone '" + zonename.toLogString() + "'");
+      throw HttpInternalServerErrorException("Unable to set new TSIG primary keys for zone '" + zonename.toLogString() + "'");
     }
   }
   if (!document["slave_tsig_key_ids"].is_null()) {
     vector<string> metadata;
     extractJsonTSIGKeyIds(B, document["slave_tsig_key_ids"], metadata);
     if (!di.backend->setDomainMetadata(zonename, "AXFR-MASTER-TSIG", metadata)) {
-      throw HttpInternalServerErrorException("Unable to set new TSIG slave keys for zone '" + zonename.toLogString() + "'");
+      throw HttpInternalServerErrorException("Unable to set new TSIG secondary keys for zone '" + zonename.toLogString() + "'");
     }
   }
 }
@@ -1688,7 +1688,7 @@ static void apiServerAutoprimaries(HttpRequest* req, HttpResponse* resp) {
     if (primary.ip=="" or primary.nameserver=="") {
       throw ApiException("ip and nameserver fields must be filled");
     }
-    if (!B.superMasterAdd(primary))
+    if (!B.autoPrimaryAdd(primary))
       throw HttpInternalServerErrorException("Cannot find backend with autoprimary feature");
     resp->body = "";
     resp->status = 201;
@@ -1713,10 +1713,10 @@ static void apiServerZonesPost(HttpRequest* req, HttpResponse* resp) {
   }
 
   boost::optional<DomainInfo::DomainKind> kind;
-  boost::optional<vector<ComboAddress>> masters;
+  boost::optional<vector<ComboAddress>> primaries;
   boost::optional<DNSName> catalog;
   boost::optional<string> account;
-  extractDomainInfoFromDocument(document, kind, masters, catalog, account);
+  extractDomainInfoFromDocument(document, kind, primaries, catalog, account);
 
   // validate 'kind' is set
   if (!kind) {
@@ -1731,7 +1731,7 @@ static void apiServerZonesPost(HttpRequest* req, HttpResponse* resp) {
   }
 
   auto nameservers = document["nameservers"];
-  if (!nameservers.is_null() && !nameservers.is_array() && zonekind != DomainInfo::Slave && zonekind != DomainInfo::Consumer) {
+  if (!nameservers.is_null() && !nameservers.is_array() && zonekind != DomainInfo::Secondary && zonekind != DomainInfo::Consumer) {
     throw ApiException("Nameservers is not a list");
   }
 
@@ -1793,7 +1793,7 @@ static void apiServerZonesPost(HttpRequest* req, HttpResponse* resp) {
   autorr.auth = true;
   autorr.ttl = ::arg().asNum("default-ttl");
 
-  if (!have_soa && zonekind != DomainInfo::Slave && zonekind != DomainInfo::Consumer) {
+  if (!have_soa && zonekind != DomainInfo::Secondary && zonekind != DomainInfo::Consumer) {
     // synthesize a SOA record so the zone "really" exists
     string soa = ::arg()["default-soa-content"];
     boost::replace_all(soa, "@", zonename.toStringNoDot());
@@ -1846,7 +1846,7 @@ static void apiServerZonesPost(HttpRequest* req, HttpResponse* resp) {
   }
 
   // no going back after this
-  if(!B.createDomain(zonename, kind.get_value_or(DomainInfo::Native), masters.get_value_or(vector<ComboAddress>()), account.get_value_or(""))) {
+  if (!B.createDomain(zonename, kind.get_value_or(DomainInfo::Native), primaries.get_value_or(vector<ComboAddress>()), account.get_value_or(""))) {
     throw ApiException("Creating domain '"+zonename.toString()+"' failed: backend refused");
   }
 
@@ -1872,7 +1872,7 @@ static void apiServerZonesPost(HttpRequest* req, HttpResponse* resp) {
 
   updateDomainSettingsFromDocument(B, di, zonename, document, !new_records.empty());
 
-  if (!catalog && kind == DomainInfo::Master) {
+  if (!catalog && kind == DomainInfo::Primary) {
     auto defaultCatalog = ::arg()["default-catalog-zone"];
     if (!defaultCatalog.empty()) {
       di.backend->setCatalog(zonename, DNSName(defaultCatalog));
@@ -2011,7 +2011,7 @@ static void apiServerZoneDetail(HttpRequest* req, HttpResponse* resp) {
         }
       }
 
-      if (!haveSoa && newKind != DomainInfo::Slave && newKind != DomainInfo::Consumer) {
+      if (!haveSoa && newKind != DomainInfo::Secondary && newKind != DomainInfo::Consumer) {
         // Require SOA if this is a primary zone.
         throw ApiException("Must give SOA record for zone when replacing all RR sets");
       }
@@ -2032,7 +2032,7 @@ static void apiServerZoneDetail(HttpRequest* req, HttpResponse* resp) {
         di.backend->feedComment(c);
       }
 
-      if (!haveSoa && (newKind == DomainInfo::Slave || newKind == DomainInfo::Consumer)) {
+      if (!haveSoa && (newKind == DomainInfo::Secondary || newKind == DomainInfo::Consumer)) {
         di.backend->setStale(di.id);
       }
     } else {
@@ -2134,12 +2134,12 @@ static void apiServerZoneAxfrRetrieve(HttpRequest* req, HttpResponse* resp) {
     throw HttpNotFoundException();
   }
 
-  if(di.masters.empty())
-    throw ApiException("Domain '"+zonename.toString()+"' is not a slave domain (or has no master defined)");
+  if (di.primaries.empty())
+    throw ApiException("Domain '" + zonename.toString() + "' is not a secondary domain (or has no primary defined)");
 
-  shuffle(di.masters.begin(), di.masters.end(), pdns::dns_random_engine());
-  Communicator.addSuckRequest(zonename, di.masters.front(), SuckRequest::Api);
-  resp->setSuccessResult("Added retrieval request for '"+zonename.toString()+"' from master "+di.masters.front().toLogString());
+  shuffle(di.primaries.begin(), di.primaries.end(), pdns::dns_random_engine());
+  Communicator.addSuckRequest(zonename, di.primaries.front(), SuckRequest::Api);
+  resp->setSuccessResult("Added retrieval request for '" + zonename.toString() + "' from primary " + di.primaries.front().toLogString());
 }
 
 static void apiServerZoneNotify(HttpRequest* req, HttpResponse* resp) {
@@ -2384,8 +2384,8 @@ static void apiServerSearchData(HttpRequest* req, HttpResponse* resp) {
   string sMax = req->getvars["max"];
   string sObjectType = req->getvars["object_type"];
 
-  int maxEnts = 100;
-  int ents = 0;
+  size_t maxEnts = 100;
+  size_t ents = 0;
 
   // the following types of data can be searched for using the api
   enum class ObjectType
index c309533f6fb704005c16703540e20d01ec7fbf03..4dfa32ed8464e29e6450d7863db9d48e30dd6021 100644 (file)
@@ -111,16 +111,17 @@ static void startNewTransaction()
     cout<<"BEGIN TRANSACTION;"<<endl;
 }
 
-static void emitDomain(const DNSName& domain, const vector<ComboAddress> *masters = nullptr) {
+static void emitDomain(const DNSName& domain, const vector<ComboAddress>* primaries = nullptr)
+{
   string iDomain = domain.toStringRootDot();
-  if(!::arg().mustDo("slave")) {
+  if (!::arg().mustDo("secondary")) {
     cout<<"insert into domains (name,type) values ("<<toLower(sqlstr(iDomain))<<",'NATIVE');"<<endl;
   }
   else
   {
     string mstrs;
-    if (masters != nullptr && ! masters->empty()) {
-      for(const auto& mstr :  *masters) {
+    if (primaries != nullptr && !primaries->empty()) {
+      for (const auto& mstr : *primaries) {
         mstrs.append(mstr.toStringWithPortExcept(53));
         mstrs.append(1, ' ');
       }
@@ -203,7 +204,7 @@ try
     ::arg().setSwitch("gmysql","Output in format suitable for default gmysqlbackend")="no";
     ::arg().setSwitch("gsqlite","Output in format suitable for default gsqlitebackend")="no";
     ::arg().setSwitch("verbose","Verbose comments on operation")="no";
-    ::arg().setSwitch("slave","Keep BIND slaves as slaves. Only works with named-conf.")="no";
+    ::arg().setSwitch("secondary", "Keep BIND secondaries as secondaries. Only works with named-conf.") = "no";
     ::arg().setSwitch("json-comments","Parse json={} field for disabled & comments")="no";
     ::arg().setSwitch("transactions","If target SQL supports it, use transactions")="no";
     ::arg().setSwitch("on-error-resume-next","Continue after errors")="no";
@@ -292,7 +293,7 @@ try
           try {
             startNewTransaction();
 
-            emitDomain(domain.name, &(domain.masters));
+            emitDomain(domain.name, &(domain.primaries));
 
             ZoneParserTNG zpt(domain.filename, domain.name, BP.getDirectory());
             zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
index dc1ee7af252456484bce85f175dfddb7d45619b1..c3274f4f22fc8a23c9ceefdb9b2d1a9c813a29cb 100644 (file)
@@ -13,7 +13,7 @@ void pdns::ZoneMD::readRecords(ZoneParserTNG& zpt)
   while (zpt.get(dnsResourceRecord)) {
     std::shared_ptr<DNSRecordContent> drc;
     try {
-      drc = DNSRecordContent::mastermake(dnsResourceRecord.qtype, QClass::IN, dnsResourceRecord.content);
+      drc = DNSRecordContent::make(dnsResourceRecord.qtype, QClass::IN, dnsResourceRecord.content);
     }
     catch (const PDNSException& pe) {
       std::string err = "Bad record content in record for '" + dnsResourceRecord.qname.toStringNoDot() + "'|" + dnsResourceRecord.qtype.toString() + ": " + pe.reason;
index 8193070a6053fdf2959cd503fafb15009bf13f72..6bd02bfc872a4043467165c495da88496aef9675 100644 (file)
@@ -836,7 +836,7 @@ class AuthZones(ApiTestCase, AuthZonesHelperMixin):
         data = r.json()
         print("status for axfr-retrieve:", data)
         self.assertEqual(data['result'], u'Added retrieval request for \'' + payload['name'] +
-                         '\' from master 127.0.0.2')
+                         '\' from primary 127.0.0.2')
 
     def test_notify_master_zone(self):
         name, payload, data = self.create_zone(kind='Master')
index ee1ae3f24b658f01104f7cec0919b7120133b1d2..f1236ed89f9bb8b8c99bf6863ca3ceb5d434853e 100644 (file)
@@ -1,5 +1,5 @@
 dnspython==2.1.0
-nose>=1.3.7
+pytest
 Twisted>0.15.0
 requests>=2.18.4
 git+https://github.com/PowerDNS/xfrserver.git@0.3
index 45c6d62f27ffc7d76cef5fa597b65c42ddebdf9b..22f0b14639c339f9f5e01ed1dc98a027f9644c7b 100755 (executable)
@@ -31,13 +31,13 @@ if [ "${PDNS_DEBUG}" = "YES" ]; then
   set -x
 fi
 
-ignore="-test_GSSTSIG.py"
+ignore="--ignore=test_GSSTSIG.py"
 if [ "${WITHKERBEROS}" = "YES" ]; then
     ignore=""
     (cd kerberos-server && sudo docker compose up --detach --build)
 fi
 
-nosetests --with-xunit $ignore $@
+pytest --junitxml=pytest.xml $ignore $@
 ret=$?
 
 if [ "${WITHKERBEROS}" = "YES" ]; then
index 755ae125044e07878d1b55b816a86f1bc96048ce..6247dc04b72eae1c30aa6d43e687b640c1267efe 100644 (file)
@@ -63,8 +63,8 @@ class TestIXFR(AuthTest):
 launch=gsqlite3 bind
 gsqlite3-database=configs/auth/powerdns.sqlite
 gsqlite3-dnssec
-slave
-slave-cycle-interval=1
+secondary
+xfr-cycle-interval=1
 query-cache-ttl=20
 negquery-cache-ttl=60
 """
@@ -76,7 +76,7 @@ negquery-cache-ttl=60
     @classmethod
     def setUpClass(cls):
         super(TestIXFR, cls).setUpClass()
-        os.system("$PDNSUTIL --config-dir=configs/auth create-slave-zone example. 127.0.0.1:%s" % (xfrServerPort,))
+        os.system("$PDNSUTIL --config-dir=configs/auth create-secondary-zone example. 127.0.0.1:%s" % (xfrServerPort,))
         os.system("$PDNSUTIL --config-dir=configs/auth set-meta example. IXFR 1")
 
     def waitUntilCorrectSerialIsLoaded(self, serial, timeout=10):
index 6061d3123f5162abe93286272e77d7487b96c037..3db145e293f155a460a6b25bf8cbbec8f624b707 100644 (file)
@@ -144,12 +144,12 @@ class XFRIncompleteAuthTest(AuthTest):
 launch=gsqlite3 bind
 gsqlite3-database=configs/auth/powerdns.sqlite
 gsqlite3-dnssec
-slave
+secondary
 cache-ttl=0
 query-cache-ttl=0
 domain-metadata-cache-ttl=0
 negquery-cache-ttl=0
-slave-cycle-interval=1
+xfr-cycle-interval=1
 #loglevel=9
 #axfr-fetch-timeout=20
 """
@@ -157,7 +157,7 @@ slave-cycle-interval=1
     @classmethod
     def setUpClass(cls):
         super(XFRIncompleteAuthTest, cls).setUpClass()
-        os.system("$PDNSUTIL --config-dir=configs/auth create-slave-zone zone.rpz. 127.0.0.1:%s" % (badxfrServerPort,))
+        os.system("$PDNSUTIL --config-dir=configs/auth create-secondary-zone zone.rpz. 127.0.0.1:%s" % (badxfrServerPort,))
         os.system("$PDNSUTIL --config-dir=configs/auth set-meta zone.rpz. IXFR 1")
     
     def waitUntilCorrectSerialIsLoaded(self, serial, timeout=20):
index d36da2e76e4609ac6d84db2f64a3175bfe98e610..2e704550877f3fc908e5b5ffa751838b8a2c88fd 100644 (file)
@@ -2,6 +2,7 @@
 import os.path
 
 import base64
+import dns
 import json
 import requests
 import socket
@@ -32,7 +33,8 @@ class APITestsBase(DNSDistTest):
                         'latency-avg10000', 'latency-avg1000000', 'latency-tcp-avg100', 'latency-tcp-avg1000',
                         'latency-tcp-avg10000', 'latency-tcp-avg1000000', 'latency-dot-avg100', 'latency-dot-avg1000',
                         'latency-dot-avg10000', 'latency-dot-avg1000000', 'latency-doh-avg100', 'latency-doh-avg1000',
-                        'latency-doh-avg10000', 'latency-doh-avg1000000', 'uptime', 'real-memory-usage', 'noncompliant-queries',
+                        'latency-doh-avg10000', 'latency-doh-avg1000000', 'latency-doq-avg100', 'latency-doq-avg1000',
+                        'latency-doq-avg10000', 'latency-doq-avg1000000','uptime', 'real-memory-usage', 'noncompliant-queries',
                         'noncompliant-responses', 'rdqueries', 'empty-queries', 'cache-hits',
                         'cache-misses', 'cpu-iowait', 'cpu-steal', 'cpu-sys-msec', 'cpu-user-msec', 'fd-usage', 'dyn-blocked',
                         'dyn-block-nmg-size', 'rule-servfail', 'rule-truncated', 'security-status',
@@ -350,6 +352,59 @@ class TestAPIBasics(APITestsBase):
             for key in ['blocks']:
                 self.assertTrue(content[key] >= 0)
 
+    def testServersLocalhostRings(self):
+        """
+        API: /api/v1/servers/localhost/rings
+        """
+        headers = {'x-api-key': self._webServerAPIKey}
+        url = 'http://127.0.0.1:' + str(self._webServerPort) + '/api/v1/servers/localhost/rings'
+        expectedValues = ['age', 'id', 'name', 'requestor', 'size', 'qtype', 'protocol', 'rd']
+        expectedResponseValues = expectedValues + ['latency', 'rcode', 'tc', 'aa', 'answers', 'backend']
+        r = requests.get(url, headers=headers, timeout=self._webTimeout)
+        self.assertTrue(r)
+        self.assertEqual(r.status_code, 200)
+        self.assertTrue(r.json())
+        content = r.json()
+        self.assertIn('queries', content)
+        self.assertIn('responses', content)
+        self.assertEqual(len(content['queries']), 0)
+        self.assertEqual(len(content['responses']), 0)
+
+        name = 'simple.api.tests.powerdns.com.'
+        query = dns.message.make_query(name, 'A', 'IN')
+        response = dns.message.make_response(query)
+        rrset = dns.rrset.from_text(name,
+                                    3600,
+                                    dns.rdataclass.IN,
+                                    dns.rdatatype.A,
+                                    '127.0.0.1')
+        response.answer.append(rrset)
+
+        for method in ("sendUDPQuery", "sendTCPQuery"):
+            sender = getattr(self, method)
+            (receivedQuery, receivedResponse) = sender(query, response)
+            self.assertTrue(receivedQuery)
+            self.assertTrue(receivedResponse)
+            receivedQuery.id = query.id
+            self.assertEqual(query, receivedQuery)
+            self.assertEqual(response, receivedResponse)
+
+        r = requests.get(url, headers=headers, timeout=self._webTimeout)
+        self.assertTrue(r)
+        self.assertEqual(r.status_code, 200)
+        self.assertTrue(r.json())
+        content = r.json()
+        self.assertIn('queries', content)
+        self.assertIn('responses', content)
+        self.assertEqual(len(content['queries']), 2)
+        self.assertEqual(len(content['responses']), 2)
+        for entry in content['queries']:
+            for value in expectedValues:
+                self.assertIn(value, entry)
+        for entry in content['responses']:
+            for value in expectedResponseValues:
+                self.assertIn(value, entry)
+
 class TestAPIServerDown(APITestsBase):
     __test__ = True
     _config_template = """
diff --git a/regression-tests.dnsdist/test_EDE.py b/regression-tests.dnsdist/test_EDE.py
new file mode 100644 (file)
index 0000000..e45ded5
--- /dev/null
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+import extendederrors
+import dns
+from dnsdisttests import DNSDistTest, pickAvailablePort
+
+class TestBasics(DNSDistTest):
+
+    _config_template = """
+    newServer{address="127.0.0.1:%s"}
+    pc = newPacketCache(100, {maxTTL=86400, minTTL=1})
+    getPool(""):setCache(pc)
+
+    local ffi = require("ffi")
+    function ffiAction(dq)
+      local extraText = 'Synthesized from Lua'
+      ffi.C.dnsdist_ffi_dnsquestion_set_extended_dns_error(dq, 29, extraText, #extraText)
+      local str = "192.0.2.2"
+      local buf = ffi.new("char[?]", #str + 1)
+      ffi.copy(buf, str)
+      ffi.C.dnsdist_ffi_dnsquestion_set_result(dq, buf, #str)
+      return DNSAction.Spoof
+    end
+
+    addAction("self-answered.ede.tests.powerdns.com.", SpoofAction("192.0.2.1"))
+    addAction("self-answered-ffi.ede.tests.powerdns.com.", LuaFFIAction(ffiAction))
+    addSelfAnsweredResponseAction("self-answered.ede.tests.powerdns.com.", SetExtendedDNSErrorResponseAction(42, "my self-answered extended error status"))
+    addAction(AllRule(), SetExtendedDNSErrorAction(16, "my extended error status"))
+
+    """
+
+    def testExtendedErrorNoEDNS(self):
+        """
+        EDE: No EDNS
+        """
+        name = 'no-edns.ede.tests.powerdns.com.'
+        # no EDNS
+        query = dns.message.make_query(name, 'A', 'IN', use_edns=False)
+        response = dns.message.make_response(query)
+        rrset = dns.rrset.from_text(name,
+                                    60,
+                                    dns.rdataclass.IN,
+                                    dns.rdatatype.A,
+                                    '127.0.0.1')
+
+        response.answer.append(rrset)
+
+        for method in ("sendUDPQuery", "sendTCPQuery"):
+            sender = getattr(self, method)
+            (receivedQuery, receivedResponse) = sender(query, response)
+            receivedQuery.id = query.id
+            self.assertEqual(query, receivedQuery)
+            self.checkResponseNoEDNS(response, receivedResponse)
+
+    def testExtendedErrorBackendResponse(self):
+        """
+        EDE: Backend response
+        """
+        name = 'backend-response.ede.tests.powerdns.com.'
+        ede = extendederrors.ExtendedErrorOption(16, b'my extended error status')
+        query = dns.message.make_query(name, 'A', 'IN', use_edns=True)
+
+        backendResponse = dns.message.make_response(query)
+        backendResponse.use_edns(edns=True, payload=4096, options=[])
+        rrset = dns.rrset.from_text(name,
+                                    60,
+                                    dns.rdataclass.IN,
+                                    dns.rdatatype.A,
+                                    '127.0.0.1')
+
+        backendResponse.answer.append(rrset)
+        expectedResponse = dns.message.make_response(query)
+        expectedResponse.use_edns(edns=True, payload=4096, options=[ede])
+        rrset = dns.rrset.from_text(name,
+                                    60,
+                                    dns.rdataclass.IN,
+                                    dns.rdatatype.A,
+                                    '127.0.0.1')
+        expectedResponse.answer.append(rrset)
+
+        for method in ("sendUDPQuery", "sendTCPQuery"):
+            sender = getattr(self, method)
+            (receivedQuery, receivedResponse) = sender(query, backendResponse)
+            receivedQuery.id = query.id
+            self.assertEqual(query, receivedQuery)
+            self.checkMessageEDNS(expectedResponse, receivedResponse)
+
+        # testing the cache
+        for method in ("sendUDPQuery", "sendTCPQuery"):
+            sender = getattr(self, method)
+            (_, receivedResponse) = sender(query, response=None, useQueue=False)
+            self.checkMessageEDNS(expectedResponse, receivedResponse)
+
+    def testExtendedErrorBackendResponseWithExistingEDE(self):
+        """
+        EDE: Backend response with existing EDE
+        """
+        name = 'backend-response-existing-ede.ede.tests.powerdns.com.'
+        ede = extendederrors.ExtendedErrorOption(16, b'my extended error status')
+        query = dns.message.make_query(name, 'A', 'IN', use_edns=True)
+
+        backendResponse = dns.message.make_response(query)
+        backendEDE = extendederrors.ExtendedErrorOption(3, b'Stale answer')
+        backendResponse.use_edns(edns=True, payload=4096, options=[backendEDE])
+        rrset = dns.rrset.from_text(name,
+                                    60,
+                                    dns.rdataclass.IN,
+                                    dns.rdatatype.A,
+                                    '127.0.0.1')
+
+        backendResponse.answer.append(rrset)
+        expectedResponse = dns.message.make_response(query)
+        expectedResponse.use_edns(edns=True, payload=4096, options=[ede])
+        rrset = dns.rrset.from_text(name,
+                                    60,
+                                    dns.rdataclass.IN,
+                                    dns.rdatatype.A,
+                                    '127.0.0.1')
+        expectedResponse.answer.append(rrset)
+
+        for method in ("sendUDPQuery", "sendTCPQuery"):
+            sender = getattr(self, method)
+            (receivedQuery, receivedResponse) = sender(query, backendResponse)
+            receivedQuery.id = query.id
+            self.assertEqual(query, receivedQuery)
+            self.checkMessageEDNS(expectedResponse, receivedResponse)
+
+        # testing the cache
+        for method in ("sendUDPQuery", "sendTCPQuery"):
+            sender = getattr(self, method)
+            (_, receivedResponse) = sender(query, response=None, useQueue=False)
+            self.checkMessageEDNS(expectedResponse, receivedResponse)
+
+    def testExtendedErrorSelfAnswered(self):
+        """
+        EDE: Self-answered
+        """
+        name = 'self-answered.ede.tests.powerdns.com.'
+        ede = extendederrors.ExtendedErrorOption(42, b'my self-answered extended error status')
+        query = dns.message.make_query(name, 'A', 'IN', use_edns=True)
+        # dnsdist sets RA = RD for self-generated responses
+        query.flags &= ~dns.flags.RD
+
+        expectedResponse = dns.message.make_response(query)
+        expectedResponse.use_edns(edns=True, payload=1232, options=[ede])
+        rrset = dns.rrset.from_text(name,
+                                    60,
+                                    dns.rdataclass.IN,
+                                    dns.rdatatype.A,
+                                    '192.0.2.1')
+        expectedResponse.answer.append(rrset)
+
+        for method in ("sendUDPQuery", "sendTCPQuery"):
+            sender = getattr(self, method)
+            (_, receivedResponse) = sender(query, response=None, useQueue=False)
+            self.checkMessageEDNS(expectedResponse, receivedResponse)
+
+    def testExtendedErrorLuaFFI(self):
+        """
+        EDE: Self-answered via Lua FFI
+        """
+        name = 'self-answered-ffi.ede.tests.powerdns.com.'
+        ede = extendederrors.ExtendedErrorOption(29, b'Synthesized from Lua')
+        query = dns.message.make_query(name, 'A', 'IN', use_edns=True)
+        # dnsdist sets RA = RD for self-generated responses
+        query.flags &= ~dns.flags.RD
+
+        expectedResponse = dns.message.make_response(query)
+        expectedResponse.use_edns(edns=True, payload=1232, options=[ede])
+        rrset = dns.rrset.from_text(name,
+                                    60,
+                                    dns.rdataclass.IN,
+                                    dns.rdatatype.A,
+                                    '192.0.2.2')
+        expectedResponse.answer.append(rrset)
+
+        for method in ("sendUDPQuery", "sendTCPQuery"):
+            sender = getattr(self, method)
+            (_, receivedResponse) = sender(query, response=None, useQueue=False)
+            self.checkMessageEDNS(expectedResponse, receivedResponse)
index d3f0ebb9d381e861fd541621e924d6d58efdf17c..4ce1178649e82e6e22e86dd527b1a6278fc64e24 100644 (file)
@@ -1313,6 +1313,46 @@ class TestSetRules(DNSDistTest):
             self.assertTrue(receivedResponse)
             self.assertEqual(expectedResponse, receivedResponse)
 
+class TestRmRules(DNSDistTest):
+    _consoleKey = DNSDistTest.generateConsoleKey()
+    _consoleKeyB64 = base64.b64encode(_consoleKey).decode('ascii')
+    _config_params = ['_consoleKeyB64', '_consolePort', '_testServerPort']
+    _config_template = """
+    setKey("%s")
+    controlSocket("127.0.0.1:%s")
+    newServer{address="127.0.0.1:%s"}
+    addAction(AllRule(), SpoofAction("192.0.2.1"), {name='myFirstRule', uuid='090736ca-2fb6-41e7-a836-58efaca3d71e'})
+    addAction(AllRule(), SpoofAction("192.0.2.1"), {name='mySecondRule'})
+    addResponseAction(AllRule(), AllowResponseAction(), {name='myFirstResponseRule', uuid='745a03b5-89e0-4eee-a6bf-c9700b0d31f0'})
+    addResponseAction(AllRule(), AllowResponseAction(), {name='mySecondResponseRule'})
+    """
+
+    def testRmRules(self):
+        """
+        Advanced: Remove rules
+        """
+        lines = self.sendConsoleCommand("showRules({showUUIDs=true})").splitlines()
+        self.assertEqual(len(lines), 3)
+        self.assertIn('myFirstRule', lines[1])
+        self.assertIn('mySecondRule', lines[2])
+        self.assertIn('090736ca-2fb6-41e7-a836-58efaca3d71e', lines[1])
+
+        lines = self.sendConsoleCommand("showResponseRules({showUUIDs=true})").splitlines()
+        self.assertEqual(len(lines), 3)
+        self.assertIn('myFirstResponseRule', lines[1])
+        self.assertIn('mySecondResponseRule', lines[2])
+        self.assertIn('745a03b5-89e0-4eee-a6bf-c9700b0d31f0', lines[1])
+
+        self.sendConsoleCommand("rmRule('090736ca-2fb6-41e7-a836-58efaca3d71e')")
+        self.sendConsoleCommand("rmRule('mySecondRule')")
+        lines = self.sendConsoleCommand("showRules({showUUIDs=true})").splitlines()
+        self.assertEqual(len(lines), 1)
+
+        self.sendConsoleCommand("rmResponseRule('745a03b5-89e0-4eee-a6bf-c9700b0d31f0')")
+        self.sendConsoleCommand("rmResponseRule('mySecondResponseRule')")
+        lines = self.sendConsoleCommand("showResponseRules({showUUIDs=true})").splitlines()
+        self.assertEqual(len(lines), 1)
+
 class TestAdvancedContinueAction(DNSDistTest):
 
     _config_template = """
index c0788f874a2a6aca55305c238ded7dbc3827beae..159d85d4fba18c6a3484fbc54b30e3d21bf7459b 100644 (file)
@@ -26,7 +26,7 @@ newrecord.example.        8484    A       192.0.2.42
 """,
     3: """
 $ORIGIN example.
-@        86400   SOA    foo bar 3 2 3 4 5
+@        86400   SOA    foo bar 3 1500 3 4 5
 @        4242    NS     ns1.example.
 @        4242    NS     ns2.example.
 ns1.example.    4242    A       192.0.2.1
@@ -72,11 +72,17 @@ class IXFRDistBasicTest(IXFRDistTest):
     def tearDownClass(cls):
         cls.tearDownIXFRDist()
 
-    def waitUntilCorrectSerialIsLoaded(self, serial, timeout=10):
+    def waitUntilCorrectSerialIsLoaded(self, serial, timeout=10, notify=False):
         global xfrServer
 
         xfrServer.moveToSerial(serial)
 
+        if notify:
+            notif = dns.message.make_query('example.', 'SOA')
+            notif.set_opcode(dns.opcode.NOTIFY)
+            notify_response = self.sendUDPQuery(notif)
+            assert notify_response.rcode() == dns.rcode.NOERROR
+
         def get_current_serial():
             query = dns.message.make_query('example.', 'SOA')
             response_message = self.sendUDPQuery(query)
@@ -227,7 +233,7 @@ class IXFRDistBasicTest(IXFRDistTest):
         self.checkIXFR(2,3)
         self.checkIXFR(1,3)
 
-        self.waitUntilCorrectSerialIsLoaded(4)
+        self.waitUntilCorrectSerialIsLoaded(serial=4, timeout=10, notify=True)
         self.checkFullZone(4)
         self.checkIXFR(3,4)
         self.checkIXFR(2,4)
index d9c8c8c35b980b6e623dc9b4c71c3e551fe8f8f1..e3f6e7a8483580f28ceda313cde33aad64154c86 100644 (file)
@@ -33,7 +33,8 @@ webserver-address: %s
                          "ixfrdist_unknown_domain_inqueries_total",
                          "ixfrdist_sys_msec", "ixfrdist_user_msec",
                          "ixfrdist_real_memory_usage",
-                         "ixfrdist_fd_usage"]
+                         "ixfrdist_fd_usage",
+                         "ixfrdist_notimp"]
     metric_domain_stats = ["ixfrdist_soa_serial", "ixfrdist_soa_checks_total",
                            "ixfrdist_soa_checks_failed_total",
                            "ixfrdist_soa_inqueries_total",
index 9829dbc8cf99c43c0006f8510198990536aad897..16d771b7f39373f3269f88bb75d840b8b9b29e7b 100755 (executable)
@@ -84,7 +84,7 @@ start_master()
 {
         $RUNWRAPPER $PDNS --daemon=no --local-port=$port --config-dir=. --module-dir=../regression-tests/modules \
                 --config-name=gsqlite3-master --socket-dir=./ --no-shuffle \
-                --master=yes --local-address=127.0.0.1 \
+                --primary=yes --local-address=127.0.0.1 \
                 --query-local-address=127.0.0.1 --cache-ttl=$cachettl --dname-processing --allow-axfr-ips= &
 }
 
@@ -94,8 +94,8 @@ start_slave()
 
         $RUNWRAPPER $PDNS --daemon=no --local-port=$slaveport --config-dir=. --module-dir=../regression-tests/modules \
                 --config-name=gsqlite3-slave --socket-dir=./ --no-shuffle --local-address=127.0.0.2 \
-                --slave --retrieval-threads=4 --slave=yes --superslave=yes --query-local-address=127.0.0.2 \
-                --slave-cycle-interval=300 --allow-unsigned-notify=no --allow-unsigned-supermaster=no &
+                --secondary --retrieval-threads=4 --autosecondary=yes --query-local-address=127.0.0.2 \
+                --xfr-cycle-interval=300 --allow-unsigned-notify=no --allow-unsigned-autoprimary=no &
 }
 
 check_process ()
index 53b6881c07b03100cd57ce3f5be6b7c0416663c6..ae75429c122ec6b32c6bb92e3b7889455a9674e2 100755 (executable)
@@ -76,7 +76,7 @@ start_master()
 {
         $RUNWRAPPER $PDNS --daemon=no --local-port=$port --config-dir=. --module-dir=../regression-tests/modules \
                 --config-name=gsqlite3-master --socket-dir=./ --no-shuffle \
-                --master=yes --local-address=127.0.0.1 \
+                --primary=yes --local-address=127.0.0.1 \
                 --query-local-address=127.0.0.1 --cache-ttl=$cachettl --dname-processing --allow-axfr-ips= &
 }
 
@@ -86,8 +86,8 @@ start_slave()
 
         $RUNWRAPPER $PDNS --daemon=no --local-port=$slaveport --config-dir=. --module-dir=../regression-tests/modules \
                 --config-name=gsqlite3-slave --socket-dir=./ --no-shuffle --local-address=127.0.0.2 \
-                --slave --retrieval-threads=4 --slave=yes --superslave=yes --query-local-address=127.0.0.2 \
-                --slave-cycle-interval=300 --dname-processing &
+                --secondary --retrieval-threads=4 --autosecondary=yes --query-local-address=127.0.0.2 \
+                --xfr-cycle-interval=300 --dname-processing &
 }
 
 check_process ()
index 2ff833efcd58efff054d0686a5e6daecb08c3559..1e149af6acdd404f64e4f805c7046e4dd67a5831 100644 (file)
@@ -16,6 +16,7 @@ class AggressiveNSECCacheBase(RecursorTest):
     _config_template = """
     dnssec=validate
     aggressive-nsec-cache-size=10000
+    nsec3-max-iterations=150
     webserver=yes
     webserver-port=%d
     webserver-address=127.0.0.1
index 75aef9db303c9c736da86f6d86e9c7ccd3a21bfd..34ef04f93392230467aa754a936c541da7dfa3bc 100644 (file)
@@ -34,10 +34,10 @@ class basicNSEC3(BasicDNSSEC):
         except subprocess.CalledProcessError as e:
             raise AssertionError('%s failed (%d): %s' % (pdnsutilCmd, e.returncode, e.output))
 
-        params = "1 0 100 AABBCCDDEEFF112233"
+        params = "1 0 50 AABBCCDDEEFF112233"
 
         if zone == "optout.example":
-            params = "1 1 100 AABBCCDDEEFF112233"
+            params = "1 1 50 AABBCCDDEEFF112233"
 
         pdnsutilCmd = [os.environ['PDNSUTIL'],
                        '--config-dir=%s' % confdir,
index add98b0fac4af2bdce44fdb069cecb8fe5b1d34a..2ba32c523187987dabf19406ae383de9f93e4458 100644 (file)
@@ -1,10 +1,10 @@
 Reply to question for qname='www3.example.net.', qtype=A
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
-0      www3.example.net.       IN      CNAME   [ttl]   www2.example.net.
-0      www2.example.net.       IN      A       [ttl]   192.0.2.2
+0      www3.example.net.       [ttl]   IN      CNAME   www2.example.net.
+0      www2.example.net.       [ttl]   IN      A       192.0.2.2
 Reply to question for qname='android.marvin.example.net.', qtype=A
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
-0      android.marvin.example.net.     IN      A       [ttl]   192.0.2.5
+0      android.marvin.example.net.     [ttl]   IN      A       192.0.2.5
 Reply to question for qname='www5.example.net.', qtype=A
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
-0      www5.example.net.       IN      A       [ttl]   192.0.2.25
+0      www5.example.net.       [ttl]   IN      A       192.0.2.25
index 2d54e2bcc7d13b77ba214fc62fdb08388c4f649f..a776c7dad1721d15fb45f8ea123cc52fd4a915b2 100755 (executable)
@@ -21,11 +21,11 @@ $SDIG $nameserver 5301 capped-ttl.example.net a recurse 2>&1
 echo "==> defpol-with-ttl.example.net should use the default policy's TTL and not the zone one"
 $SDIG $nameserver 5301 defpol-with-ttl.example.net a recurse 2>&1
 echo "==> defpol-with-ttl-capped.example.net should use the default policy's TTL, but capped to maxTTL"
-$SDIG $nameserver 5301 defpol-with-ttl-capped.example.net a recurse 2>&1 | sed 's/\(0\tdefault.example.net.\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\115/'
+$SDIG $nameserver 5301 defpol-with-ttl-capped.example.net a recurse 2>&1 | sed 's/\(0\tdefault.example.net.\t\)\([0-9]\+\)/\115/'
 echo "==> defpol-without-ttl.example.net should use the zone's TTL"
-$SDIG $nameserver 5301 defpol-without-ttl.example.net a recurse 2>&1 | sed 's/\(0\tdefault.example.net.\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\115/'
+$SDIG $nameserver 5301 defpol-without-ttl.example.net a recurse 2>&1 | sed 's/\(0\tdefault.example.net.\t\)\([0-9]\+\)/\115/'
 echo "==> defpol-without-ttl-capped.example.net should use the zone's TTL but capped to maxTTL"
-$SDIG $nameserver 5301 defpol-without-ttl-capped.example.net a recurse 2>&1 | sed 's/\(0\tdefault.example.net.\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\115/'
+$SDIG $nameserver 5301 defpol-without-ttl-capped.example.net a recurse 2>&1 | sed 's/\(0\tdefault.example.net.\t\)\([0-9]\+\)/\115/'
 echo "==> unsupported.example.net has an unsupported target, should be ignored from the RPZ zone"
 $SDIG $nameserver 5301 unsupported.example.net a recurse 2>&1
 echo "==> unsupported2.example.net has an unsupported target, should be ignored from the RPZ zone"
index c8a866e80fe7f7c2a84192dd981266df60d03056..29514fa92972c3a5dab52d8ac5eac77b845bb9bb 100644 (file)
@@ -7,12 +7,12 @@ Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 ==> srv.arthur.example.net RPZ passthru
 Reply to question for qname='srv.arthur.example.net.', qtype=SRV
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
-0      srv.arthur.example.net. IN      SRV     15      0 100 389 server2.example.net.
+0      srv.arthur.example.net. 15      IN      SRV     0 100 389 server2.example.net.
 ==> www.example.net RPZ local data to www2.example.net
 Reply to question for qname='www.example.net.', qtype=A
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
-0      www.example.net.        IN      CNAME   7200    www2.example.net.
-0      www2.example.net.       IN      A       15      192.0.2.2
+0      www.example.net.        7200    IN      CNAME   www2.example.net.
+0      www2.example.net.       15      IN      A       192.0.2.2
 ==> www4.example.net RPZ IP trigger action, dropped
 ==> trillian.example.net NXDOMAIN
 Reply to question for qname='trillian.example.net.', qtype=A
@@ -20,8 +20,8 @@ Rcode: 3 (Non-Existent domain), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 ==> www.trillian.example.net has no RPZ policy attached, so lookup should succeed
 Reply to question for qname='www.trillian.example.net.', qtype=A
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
-0      www.trillian.example.net.       IN      CNAME   15      www3.arthur.example.net.
-0      www3.arthur.example.net.        IN      A       15      192.0.2.6
+0      www.trillian.example.net.       15      IN      CNAME   www3.arthur.example.net.
+0      www3.arthur.example.net.        15      IN      A       192.0.2.6
 ==> www.hijackme.example.net is served on ns.hijackme.example.net, which should be NXDOMAIN
 Reply to question for qname='www.hijackme.example.net.', qtype=A
 Rcode: 3 (Non-Existent domain), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
@@ -31,42 +31,42 @@ Rcode: 3 (Non-Existent domain), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 ==> capped-ttl.example.net TTL exceeds the maximum TTL for the zone
 Reply to question for qname='capped-ttl.example.net.', qtype=A
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
-0      capped-ttl.example.net. IN      A       5       192.0.2.35
+0      capped-ttl.example.net. 5       IN      A       192.0.2.35
 ==> defpol-with-ttl.example.net should use the default policy's TTL and not the zone one
 Reply to question for qname='defpol-with-ttl.example.net.', qtype=A
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
-0      defpol-with-ttl.example.net.    IN      CNAME   10      default.example.net.
-0      default.example.net.    IN      A       15      192.0.2.42
+0      defpol-with-ttl.example.net.    10      IN      CNAME   default.example.net.
+0      default.example.net.    15      IN      A       192.0.2.42
 ==> defpol-with-ttl-capped.example.net should use the default policy's TTL, but capped to maxTTL
 Reply to question for qname='defpol-with-ttl-capped.example.net.', qtype=A
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
-0      defpol-with-ttl-capped.example.net.     IN      CNAME   20      default.example.net.
-0      default.example.net.    IN      A       15      192.0.2.42
+0      defpol-with-ttl-capped.example.net.     20      IN      CNAME   default.example.net.
+0      default.example.net.    15      IN      A       192.0.2.42
 ==> defpol-without-ttl.example.net should use the zone's TTL
 Reply to question for qname='defpol-without-ttl.example.net.', qtype=A
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
-0      defpol-without-ttl.example.net. IN      CNAME   7200    default.example.net.
-0      default.example.net.    IN      A       15      192.0.2.42
+0      defpol-without-ttl.example.net. 7200    IN      CNAME   default.example.net.
+0      default.example.net.    15      IN      A       192.0.2.42
 ==> defpol-without-ttl-capped.example.net should use the zone's TTL but capped to maxTTL
 Reply to question for qname='defpol-without-ttl-capped.example.net.', qtype=A
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
-0      defpol-without-ttl-capped.example.net.  IN      CNAME   50      default.example.net.
-0      default.example.net.    IN      A       15      192.0.2.42
+0      defpol-without-ttl-capped.example.net.  50      IN      CNAME   default.example.net.
+0      default.example.net.    15      IN      A       192.0.2.42
 ==> unsupported.example.net has an unsupported target, should be ignored from the RPZ zone
 Reply to question for qname='unsupported.example.net.', qtype=A
 Rcode: 3 (Non-Existent domain), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
-1      example.net.    IN      SOA     15      ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
+1      example.net.    15      IN      SOA     ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
 ==> unsupported2.example.net has an unsupported target, should be ignored from the RPZ zone
 Reply to question for qname='unsupported2.example.net.', qtype=A
 Rcode: 3 (Non-Existent domain), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
-1      example.net.    IN      SOA     15      ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
+1      example.net.    15      IN      SOA     ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
 ==> not-rpz.example.net is _not_ an RPZ target and should be processed
 Reply to question for qname='not-rpz.example.net.', qtype=A
 Rcode: 3 (Non-Existent domain), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
-0      not-rpz.example.net.    IN      CNAME   5       rpz-not.com.
-1      .       IN      SOA     15      ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
+0      not-rpz.example.net.    5       IN      CNAME   rpz-not.com.
+1      .       15      IN      SOA     ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
 ==> echo-me.wildcard-target.example.net is an RPZ wildcard target
 Reply to question for qname='echo-me.wildcard-target.example.net.', qtype=A
 Rcode: 3 (Non-Existent domain), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
-0      echo-me.wildcard-target.example.net.    IN      CNAME   7200    echo-me.wildcard-target.example.net.walled-garden.example.net.
-1      example.net.    IN      SOA     15      ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
+0      echo-me.wildcard-target.example.net.    7200    IN      CNAME   echo-me.wildcard-target.example.net.walled-garden.example.net.
+1      example.net.    15      IN      SOA     ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
index 329992db1e36eb899a9487d717678ab85430b2ef..e08674652b42232a01ae4a247de204b20c7e9ea1 100755 (executable)
@@ -1 +1 @@
-cleandig service.box.answer-cname-in-local.example.net. A | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig service.box.answer-cname-in-local.example.net. A | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
index a039a015881a619d5cf7f35d94643c2bfea66bfe..bf504b8423de0de9ae1e0502c131215374bde850 100644 (file)
@@ -1,5 +1,5 @@
-0      pfs.global.box.answer-cname-in-local.example.net.       IN      CNAME   3600    vip-reunion.pfsbox.answer-cname-in-local.example.net.
-0      service.box.answer-cname-in-local.example.net.  IN      CNAME   3600    pfs.global.box.answer-cname-in-local.example.net.
-0      vip-reunion.pfsbox.answer-cname-in-local.example.net.   IN      A       3600    10.1.1.1
+0      pfs.global.box.answer-cname-in-local.example.net.       3600    IN      CNAME   vip-reunion.pfsbox.answer-cname-in-local.example.net.
+0      service.box.answer-cname-in-local.example.net.  3600    IN      CNAME   pfs.global.box.answer-cname-in-local.example.net.
+0      vip-reunion.pfsbox.answer-cname-in-local.example.net.   3600    IN      A       10.1.1.1
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='service.box.answer-cname-in-local.example.net.', qtype=A
index e065224f993067cd631812af879de8b6971f1c22..997e097a25b390802fb20a0353576aa406b8812a 100755 (executable)
@@ -1,2 +1,2 @@
-cleandig host1.something.auth-zone.example.net. A | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
-cleandig host1.something.auth-zone.example.net. AAAA | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig host1.something.auth-zone.example.net. A | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
+cleandig host1.something.auth-zone.example.net. AAAA | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
index 7789f52444769f4e6eb91e5084efd98579f1f9e2..64c3c63af280650d35bfab3c7abaaf9f3bdb3fb8 100644 (file)
@@ -1,8 +1,8 @@
-0      host1.auth-zone.example.net.    IN      A       3600    127.0.0.55
-0      host1.something.auth-zone.example.net.  IN      CNAME   3600    host1.auth-zone.example.net.
+0      host1.auth-zone.example.net.    3600    IN      A       127.0.0.55
+0      host1.something.auth-zone.example.net.  3600    IN      CNAME   host1.auth-zone.example.net.
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='host1.something.auth-zone.example.net.', qtype=A
-0      host1.auth-zone.example.net.    IN      AAAA    3600    2001:db8::1:45ba
-0      host1.something.auth-zone.example.net.  IN      CNAME   3600    host1.auth-zone.example.net.
+0      host1.auth-zone.example.net.    3600    IN      AAAA    2001:db8::1:45ba
+0      host1.something.auth-zone.example.net.  3600    IN      CNAME   host1.auth-zone.example.net.
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='host1.something.auth-zone.example.net.', qtype=AAAA
index 96c443eb40d0cfd0c05886555902f7fb02fcbf06..bb1fe28a154b4e9d0f4c26b432683ca5fa9f22cf 100755 (executable)
@@ -1,2 +1,2 @@
-cleandig www.france.auth-zone.example.net. A | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
-cleandig france.auth-zone.example.net. A | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig www.france.auth-zone.example.net. A | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
+cleandig france.auth-zone.example.net. A | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
index 2388e911b160f17ee2d052e0c219c814293353f8..6137a36688aacd2ff72e1fc5e57162acb6b86cd9 100644 (file)
@@ -1,6 +1,6 @@
-0      www.france.auth-zone.example.net.       IN      A       3600    192.0.2.23
+0      www.france.auth-zone.example.net.       3600    IN      A       192.0.2.23
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='www.france.auth-zone.example.net.', qtype=A
-0      france.auth-zone.example.net.   IN      A       3600    192.0.2.223
+0      france.auth-zone.example.net.   3600    IN      A       192.0.2.223
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='france.auth-zone.example.net.', qtype=A
index 46d061e40175c4b4666890505627058e0a65570c..75aa5df105f87c06bd9d5dfeee61faaeae1be2ec 100755 (executable)
@@ -1,7 +1,7 @@
-cleandig host1.auth-zone.example.net. A | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
-cleandig host1.auth-zone.example.net. AAAA | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
-cleandig host2.auth-zone.example.net. A | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
-cleandig host3.auth-zone.example.net. A | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
-cleandig you-are.wild.auth-zone.example.net. TXT | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig host1.auth-zone.example.net. A | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
+cleandig host1.auth-zone.example.net. AAAA | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
+cleandig host2.auth-zone.example.net. A | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
+cleandig host3.auth-zone.example.net. A | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
+cleandig you-are.wild.auth-zone.example.net. TXT | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
 # Non-existing QTYPE at the apex
-cleandig auth-zone.example.net. TXT | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig auth-zone.example.net. TXT | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
index 49b5b5aaad8546a77c00da91b0c8009fe0215198..23d4019cb805bb9cb0d89dc1afb6e2ce2aa4b124 100644 (file)
@@ -1,20 +1,20 @@
-0      host1.auth-zone.example.net.    IN      A       3600    127.0.0.55
+0      host1.auth-zone.example.net.    3600    IN      A       127.0.0.55
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='host1.auth-zone.example.net.', qtype=A
-0      host1.auth-zone.example.net.    IN      AAAA    3600    2001:db8::1:45ba
+0      host1.auth-zone.example.net.    3600    IN      AAAA    2001:db8::1:45ba
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='host1.auth-zone.example.net.', qtype=AAAA
-0      host1.another-auth-zone.example.net.    IN      A       3600    127.0.0.56
-0      host2.auth-zone.example.net.    IN      CNAME   3600    host1.another-auth-zone.example.net.
+0      host1.another-auth-zone.example.net.    3600    IN      A       127.0.0.56
+0      host2.auth-zone.example.net.    3600    IN      CNAME   host1.another-auth-zone.example.net.
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='host2.auth-zone.example.net.', qtype=A
-0      host1.not-auth-zone.example.net.        IN      A       3600    127.0.0.57
-0      host3.auth-zone.example.net.    IN      CNAME   3600    host1.not-auth-zone.example.net.
+0      host1.not-auth-zone.example.net.        3600    IN      A       127.0.0.57
+0      host3.auth-zone.example.net.    3600    IN      CNAME   host1.not-auth-zone.example.net.
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='host3.auth-zone.example.net.', qtype=A
-0      you-are.wild.auth-zone.example.net.     IN      TXT     3600    "Hi there!"
+0      you-are.wild.auth-zone.example.net.     3600    IN      TXT     "Hi there!"
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='you-are.wild.auth-zone.example.net.', qtype=TXT
-1      auth-zone.example.net.  IN      SOA     3600    ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
+1      auth-zone.example.net.  3600    IN      SOA     ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='auth-zone.example.net.', qtype=TXT
index 59bf9ae79bac51983ac14a9823913cfd0ad69be5..684fd39372897abe4e9b4382689d20d20f0162ec 100755 (executable)
@@ -1,4 +1,4 @@
 #!/bin/bash
 $SDIG $nameserver 5302 www.arthur.example.net a recurse
 sleep 3
-$SDIG $nameserver 5302 www.arthur.example.net a recurse | sed 's/\(.*\tIN\tA\t\)\(11\)/\112/'
+$SDIG $nameserver 5302 www.arthur.example.net a recurse | sed 's/\(.*\t\)\(11\tIN\)/\112\tIN/'
index 702663ffd5cbc7492f88f0c1f5f369245e2ba8fa..e209d3490141740112d57e2105444d5ca641a3a1 100644 (file)
@@ -1,6 +1,6 @@
 Reply to question for qname='www.arthur.example.net.', qtype=A
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
-0      www.arthur.example.net. IN      A       15      192.0.2.2
+0      www.arthur.example.net. 15      IN      A       192.0.2.2
 Reply to question for qname='www.arthur.example.net.', qtype=A
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
-0      www.arthur.example.net. IN      A       12      192.0.2.2
+0      www.arthur.example.net. 12      IN      A       192.0.2.2
index 9c31250f7b1a9479208ec926580c316313a8117b..577827b4dd5ebdae2d641dc4ecda28904c1bb257 100755 (executable)
@@ -1,2 +1,2 @@
 #!/bin/sh
-cleandig www-a.prefect.example.net a | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig www-a.prefect.example.net a | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
index 33d85eeef8c4058cd8603c79c348e4b782ff5f4c..23550b790ff92d48338aa3cd8098e17e6437c7ae 100644 (file)
@@ -1,4 +1,4 @@
-0      www-a.prefect.example.net.      IN      CNAME   3600    www-a-2.prefect.example.net.
-1      prefect.example.net.    IN      SOA     3600    ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
+0      www-a.prefect.example.net.      3600    IN      CNAME   www-a-2.prefect.example.net.
+1      prefect.example.net.    3600    IN      SOA     ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
 Rcode: 3 (Non-Existent domain), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='www-a.prefect.example.net.', qtype=A
index b1e93dd588270dbe594094e16a36f7f98ee2d516..a3baa398ea7dcf34d33f7108e65c14076d0fbf99 100755 (executable)
@@ -1,2 +1,2 @@
 #!/bin/sh
-cleandig www.trillian.example.net a | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig www.trillian.example.net a | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
index 490a8a27af3cab51db574146048c498960e1f626..3d98336fea5ec972e063053a0ad621329654190c 100644 (file)
@@ -1,4 +1,4 @@
-0      www.trillian.example.net.       IN      CNAME   3600    www3.arthur.example.net.
-0      www3.arthur.example.net.        IN      A       3600    192.0.2.6
+0      www.trillian.example.net.       3600    IN      CNAME   www3.arthur.example.net.
+0      www3.arthur.example.net.        3600    IN      A       192.0.2.6
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='www.trillian.example.net.', qtype=A
index 2fd457d758d4013d8e8e6b0ef92d4ad081190313..0b8d797df093c7e2a629d477401e1309f00fe035 100755 (executable)
@@ -1,2 +1,2 @@
 #!/bin/sh
-cleandig www-a.prefect.example.net cname | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig www-a.prefect.example.net cname | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
index a87a800ab13095467d04f61a196f3c9060098739..5aa686b2b05ed10c130f93a9eea16c168210ee30 100644 (file)
@@ -1,3 +1,3 @@
-0      www-a.prefect.example.net.      IN      CNAME   3600    www-a-2.prefect.example.net.
+0      www-a.prefect.example.net.      3600    IN      CNAME   www-a-2.prefect.example.net.
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='www-a.prefect.example.net.', qtype=CNAME
index 50f42e7f0eee07e296fb450921c90c52e8c836fb..a0421da98809585ffbed0fba3d0acd82d89a91d5 100755 (executable)
@@ -1,2 +1,2 @@
 #!/bin/sh
-cleandig www-d.prefect.example.net cname | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig www-d.prefect.example.net cname | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
index baa2fb6e5fc6c7ffc1c66c5da3c8e1d62f4adb68..2d1f746335310b980b29f85d4913e9f2402d5705 100644 (file)
@@ -1,3 +1,3 @@
-0      www-d.prefect.example.net.      IN      CNAME   3600    www.arthur.example.net.
+0      www-d.prefect.example.net.      3600    IN      CNAME   www.arthur.example.net.
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='www-d.prefect.example.net.', qtype=CNAME
index 2cd49ff0b0895d140a84087f949e7d6e87cf9737..91bda25864b0c2d3345ed251d895f3c4febe9b07 100755 (executable)
@@ -1,13 +1,13 @@
 #!/bin/sh
 . vars
 rm -f configs/$PREFIX.17/drop-1
-cleandig a.www.1.ghost.example.net a | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig a.www.1.ghost.example.net a | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
 sleep 8
 touch configs/$PREFIX.17/drop-1
-cleandig b.www.1.ghost.example.net a | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig b.www.1.ghost.example.net a | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
 sleep 5
-cleandig c.www.1.ghost.example.net a | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig c.www.1.ghost.example.net a | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
 sleep 5
-cleandig d.www.1.ghost.example.net a | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig d.www.1.ghost.example.net a | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
 sleep 5
-cleandig e.www.1.ghost.example.net a | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig e.www.1.ghost.example.net a | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
index 84d79e90935343f62adf90e5f51e87f5ac929410..bc000e8412804af40cb54a21e83b683b9c3e8f5e 100644 (file)
@@ -1,15 +1,15 @@
-0      a.www.1.ghost.example.net.      IN      A       3600    192.0.2.7
+0      a.www.1.ghost.example.net.      3600    IN      A       192.0.2.7
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='a.www.1.ghost.example.net.', qtype=A
-0      b.www.1.ghost.example.net.      IN      A       3600    192.0.2.7
+0      b.www.1.ghost.example.net.      3600    IN      A       192.0.2.7
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='b.www.1.ghost.example.net.', qtype=A
-0      c.www.1.ghost.example.net.      IN      A       3600    192.0.2.7
+0      c.www.1.ghost.example.net.      3600    IN      A       192.0.2.7
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='c.www.1.ghost.example.net.', qtype=A
-1      ghost.example.net.      IN      SOA     3600    ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
+1      ghost.example.net.      3600    IN      SOA     ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
 Rcode: 3 (Non-Existent domain), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='d.www.1.ghost.example.net.', qtype=A
-1      ghost.example.net.      IN      SOA     3600    ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
+1      ghost.example.net.      3600    IN      SOA     ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
 Rcode: 3 (Non-Existent domain), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='e.www.1.ghost.example.net.', qtype=A
index f22207aed89a6f9bc2ac988d83923f9e55563f61..fb141b093228adc5f7f8c61efaa32da264dd0198 100755 (executable)
@@ -1,13 +1,13 @@
 #!/bin/sh
 . vars
 rm -f configs/$PREFIX.17/drop-2
-cleandig a.www.2.ghost.example.net a | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig a.www.2.ghost.example.net a | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
 sleep 8
 touch configs/$PREFIX.17/drop-2
-cleandig b.www.2.ghost.example.net a | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig b.www.2.ghost.example.net a | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
 sleep 5
-cleandig c.www.2.ghost.example.net a | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig c.www.2.ghost.example.net a | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
 sleep 5
-cleandig d.www.2.ghost.example.net a | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig d.www.2.ghost.example.net a | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
 sleep 5
-cleandig e.www.2.ghost.example.net a | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig e.www.2.ghost.example.net a | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
index 58f4b44342ef2c8d020257d63c5029fe616cbffb..7a2e7325d91693592ca94c572c7f552ca2f48b79 100644 (file)
@@ -1,15 +1,15 @@
-0      a.www.2.ghost.example.net.      IN      A       3600    192.0.2.8
+0      a.www.2.ghost.example.net.      3600    IN      A       192.0.2.8
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='a.www.2.ghost.example.net.', qtype=A
-0      b.www.2.ghost.example.net.      IN      A       3600    192.0.2.8
+0      b.www.2.ghost.example.net.      3600    IN      A       192.0.2.8
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='b.www.2.ghost.example.net.', qtype=A
-0      c.www.2.ghost.example.net.      IN      A       3600    192.0.2.8
+0      c.www.2.ghost.example.net.      3600    IN      A       192.0.2.8
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='c.www.2.ghost.example.net.', qtype=A
-1      ghost.example.net.      IN      SOA     3600    ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
+1      ghost.example.net.      3600    IN      SOA     ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
 Rcode: 3 (Non-Existent domain), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='d.www.2.ghost.example.net.', qtype=A
-1      ghost.example.net.      IN      SOA     3600    ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
+1      ghost.example.net.      3600    IN      SOA     ns.example.net. hostmaster.example.net. 1 3600 1800 1209600 300
 Rcode: 3 (Non-Existent domain), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='e.www.2.ghost.example.net.', qtype=A
index 2733d940cf8e1b5a8e708b38eaed718241525cc3..30bfb74c6df86c4aade8e2210ba63d22dfbd7437 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
 . vars
-cleandig hijacker.example.net ns | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
-cleandig www.hijackme.example.net a | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig hijacker.example.net ns | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
+cleandig www.hijackme.example.net a | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
 sleep 5
\ No newline at end of file
index f5d3502e13b458522ac4dcb77622648dd758f15f..f803316cf1f6c8b9be9aa65c47076b92b55760c9 100644 (file)
@@ -1,6 +1,6 @@
-0      hijacker.example.net.   IN      NS      3600    ns.hijackme.example.net.
+0      hijacker.example.net.   3600    IN      NS      ns.hijackme.example.net.
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='hijacker.example.net.', qtype=NS
-0      www.hijackme.example.net.       IN      A       3600    192.0.2.20
+0      www.hijackme.example.net.       3600    IN      A       192.0.2.20
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='www.hijackme.example.net.', qtype=A
index cb2297357dff343171c06fa684a2b2517e093b61..13c0a3dfa235ef8bd1edd9a9a5a81ced1f9bcfe8 100755 (executable)
@@ -1,2 +1,2 @@
 #!/bin/sh
-cleandig www.marvin.example.net a | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig www.marvin.example.net a | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
index 7719481a75a6ee6a0eedc0fa9fdb21d4036e2a2a..0af41f5edcd1704dbc458b7412f5620340e5a993 100644 (file)
@@ -1,4 +1,4 @@
-0      android.marvin.example.net.     IN      A       3600    192.0.2.5
-0      www.marvin.example.net. IN      CNAME   3600    android.marvin.example.net.
+0      android.marvin.example.net.     3600    IN      A       192.0.2.5
+0      www.marvin.example.net. 3600    IN      CNAME   android.marvin.example.net.
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='www.marvin.example.net.', qtype=A
index 04e25b154e76189ec615a3355df88febba60c6da..f5ef8a33d845b4e4ee2233bb547e6ed68bfb494a 100755 (executable)
@@ -1,2 +1,2 @@
 #!/bin/sh
-cleandig www.ford.example.net A | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig www.ford.example.net A | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
index 8450c9083be273b3ce08278c1c177be66ee0cf76..7956de32336bebe9a1d33d2cf7badbd781334ef5 100755 (executable)
@@ -1,2 +1,2 @@
 #!/bin/sh
-cleandig www.example.net a | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig www.example.net a | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
index 7e3a2b901f6444eafa45bfe7446909f57f118fb4..640dc00744c7fda3d7bb5df4f1350b0e11b1fecc 100644 (file)
@@ -1,3 +1,3 @@
-0      www.example.net.        IN      A       3600    192.0.2.1
+0      www.example.net.        3600    IN      A       192.0.2.1
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='www.example.net.', qtype=A
index b62eeaf9b2242e889153ab679a56e4453d366868..59e7eef2776553bfa0f8a5c587f7c6b683a51e67 100755 (executable)
@@ -1,2 +1,2 @@
 #!/bin/sh
-cleandig www-d.prefect.example.net a | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig www-d.prefect.example.net a | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
index fdf433f3f58578a0f025adf46067e3153a2ba389..3768214482abc47b9cd0c30504dad9aa967d2ee5 100644 (file)
@@ -1,4 +1,4 @@
-0      www-d.prefect.example.net.      IN      CNAME   3600    www.arthur.example.net.
-0      www.arthur.example.net. IN      A       3600    192.0.2.2
+0      www-d.prefect.example.net.      3600    IN      CNAME   www.arthur.example.net.
+0      www.arthur.example.net. 3600    IN      A       192.0.2.2
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='www-d.prefect.example.net.', qtype=A
index d5de10e485f9646b54f32889c266febcc15daed2..80a4efdbaa1a8824da8357c24a7de3029ceb7396 100755 (executable)
@@ -1,4 +1,4 @@
 #!/bin/sh
-cleandig srv.arthur.example.net srv | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
-cleandig rp.arthur.example.net rp | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
-cleandig type1234.arthur.example.net TYPE1234 | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig srv.arthur.example.net srv | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
+cleandig rp.arthur.example.net rp | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
+cleandig type1234.arthur.example.net TYPE1234 | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
index 51c0c3ed9ed2b8d674fb813199365732b126504e..5696d8891f3af9abe6a9008e0c8c9a26683297b4 100644 (file)
@@ -1,9 +1,9 @@
-0      srv.arthur.example.net. IN      SRV     3600    0 100 389 server2.example.net.
+0      srv.arthur.example.net. 3600    IN      SRV     0 100 389 server2.example.net.
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='srv.arthur.example.net.', qtype=SRV
-0      rp.arthur.example.net.  IN      RP      3600    ahu.ds9a.nl. counter.arthur.example.net.
+0      rp.arthur.example.net.  3600    IN      RP      ahu.ds9a.nl. counter.arthur.example.net.
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='rp.arthur.example.net.', qtype=RP
-0      type1234.arthur.example.net.    IN      TYPE1234        3600    \# 2 4142
+0      type1234.arthur.example.net.    3600    IN      TYPE1234        \# 2 4142
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='type1234.arthur.example.net.', qtype=TYPE1234
index 5898ab45dfb305b08d6b0b42bbab077483e72bbf..269f1ab45510f7a7c9219f675611c8f779d5c6c9 100755 (executable)
@@ -1,2 +1,2 @@
 #!/bin/sh
-cleandig big.arthur.example.net txt | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig big.arthur.example.net txt | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
index d12c03b647a9f20c35e1713cd6e46495b42afabf..985842507f72a92dec4bf67dc78186c76fcee661 100755 (executable)
@@ -1,2 +1,2 @@
 #!/bin/sh
-cleandig weirdtxt.example.net txt | sed 's/\(.*\tIN\t[A-Z0-9]\+\t\)\([0-9]\+\)/\13600/'
+cleandig weirdtxt.example.net txt | sed 's/\(.*\t\)\([0-9]\+\tIN\)/\13600\tIN/'
index 039d2c54e76260171ca16fadbe7ffb5bbfb01c61..b080d5348f417230a167800e9fae055da340ea86 100644 (file)
@@ -1,3 +1,3 @@
-0      weirdtxt.example.net.   IN      TXT     3600    "x\014x"
+0      weirdtxt.example.net.   3600    IN      TXT     "x\014x"
 Rcode: 0 (No Error), RD: 1, QR: 1, TC: 0, AA: 0, opcode: 0
 Reply to question for qname='weirdtxt.example.net.', qtype=TXT
index d32a3cce32d192e61b4df841133b8313e6d67f59..6fb6e5a1ff8682e641ea9075567cae0fd80272fd 100644 (file)
@@ -82,7 +82,7 @@ __EOF__
             fi
             if [ "$zone" = "tsig.com" ]; then
                 $PDNSUTIL --config-dir=. --config-name=bind import-tsig-key test $ALGORITHM $KEY
-                $PDNSUTIL --config-dir=. --config-name=bind activate-tsig-key tsig.com test master
+                $PDNSUTIL --config-dir=. --config-name=bind activate-tsig-key tsig.com test primary
             fi
         done
 
index e002f53298415001297379ad032b6d4df0215cdb..ba10778a8e8f651b787872d557b081e9039e8a05 100644 (file)
@@ -33,7 +33,7 @@
        port=$((port+100))
 
        $RUNWRAPPER $PDNS2 --daemon=no --local-port=$port --socket-dir=./ \
-               --no-shuffle --launch=bind --bind-config=./named-slave.conf --slave \
+               --no-shuffle --launch=bind --bind-config=./named-slave.conf --secondary \
                --retrieval-threads=1  --config-name=bind-slave \
                --dnsupdate=yes \
                --cache-ttl=$cachettl --no-config --dname-processing --bind-dnssec-db=./dnssec-slave.sqlite3 \
index 4b7b02ddb74f0add0bb86a1e6c1bd467b2451678..1c58ac2337b7a84fa7173dda84af0d3b0a80951b 100644 (file)
@@ -18,7 +18,7 @@ __EOF__
                echo "INSERT INTO domains (name, type, master) VALUES('$zone','SLAVE','127.0.0.1:$port');" | $ISQL -b
                if [ "$zone" = "tsig.com" ]; then
                        ../pdns/pdnssec --config-dir=. --config-name=godbc2 import-tsig-key test $ALGORITHM $KEY
-                       ../pdns/pdnssec --config-dir=. --config-name=godbc2 activate-tsig-key tsig.com test slave
+                       ../pdns/pdnssec --config-dir=. --config-name=godbc2 activate-tsig-key tsig.com test secondary
                fi
                if [ "$zone" = "stest.com" ]; then
                        if [[ $skipreasons != *nolua* ]]; then
@@ -31,8 +31,8 @@ __EOF__
 
        $RUNWRAPPER $PDNS2 --daemon=no --local-port=$port --config-dir=. \
                --config-name=godbc2 --socket-dir=./ --no-shuffle \
-               --slave --retrieval-threads=4 \
-               --slave-cycle-interval=300 --dname-processing &
+               --secondary --retrieval-threads=4 \
+               --xfr-cycle-interval=300 --dname-processing &
 
        echo 'waiting for zones to be slaved'
        set +e
index 89c11cb2189e85e4102472b94860e252bed65a16..1a6074a357ae27d08a4a6b501b4bc34a8e3507a3 100644 (file)
@@ -41,8 +41,8 @@ godbc-get-tsig-key-query=select algorithm, secret from tsigkeys where name=?
 godbc-get-tsig-keys-query=select name,algorithm, secret from tsigkeys
 godbc-publish-domain-key-query=update cryptokeys set published=1 where domain_id=(select id from domains where name=?) and  cryptokeys.id=?
 godbc-id-query=SELECT content,ttl,prio,type,domain_id,disabled,name,auth FROM records WHERE disabled=0 and type=? and name=? and domain_id=?
-godbc-info-all-master-query=select domains.id, domains.name, domains.type, domains.notified_serial, domains.options, domains.catalog, records.content from records join domains on records.domain_id=domains.id and records.name=domains.name where records.type='SOA' and records.disabled=0 and domains.type in ('MASTER', 'PRODUCER')
-godbc-info-all-slaves-query=select domains.id, domains.name, domains.type, domains.master, domains.last_check, records.content from domains LEFT JOIN records ON records.domain_id=domains.id AND records.type='SOA' AND records.name=domains.name where domains.type in ('SLAVE', 'CONSUMER')
+godbc-info-all-primary-query=select domains.id, domains.name, domains.type, domains.notified_serial, domains.options, domains.catalog, records.content from records join domains on records.domain_id=domains.id and records.name=domains.name where records.type='SOA' and records.disabled=0 and domains.type in ('MASTER', 'PRODUCER')
+godbc-info-all-secondaries-query=select domains.id, domains.name, domains.type, domains.master, domains.last_check, records.content from domains LEFT JOIN records ON records.domain_id=domains.id AND records.type='SOA' AND records.name=domains.name where domains.type in ('SLAVE', 'CONSUMER')
 godbc-info-zone-query=select id,name,master,last_check,notified_serial,type,options,catalog,account from domains where name=?
 godbc-info-producer-members-query=select domains.id, domains.name, domains.options from records join domains on records.domain_id=domains.id and records.name=domains.name where domains.type='MASTER' and domains.catalog=? and records.type='SOA' and records.disabled=0
 godbc-info-consumer-members-query=select id, name, options, master from domains where type='SLAVE' and catalog=?
@@ -62,12 +62,12 @@ godbc-search-comments-query=SELECT domain_id,name,type,modified_at,account,comme
 godbc-search-records-query=SELECT content,ttl,prio,type,domain_id,disabled,name,auth FROM records WHERE name LIKE ? OR content LIKE ? LIMIT ?
 godbc-set-domain-metadata-query=insert into domainmetadata (domain_id, kind, content) select id, ?, ? from domains where name=?
 godbc-set-tsig-key-query=replace into tsigkeys (name,algorithm,secret) values(?,?,?)
-godbc-supermaster-query=select account from supermasters where ip=? and nameserver=?
+godbc-autoprimary-query=select account from supermasters where ip=? and nameserver=?
 godbc-unpublish-domain-key-query=update cryptokeys set published=0 where domain_id=(select id from domains where name=?) and  cryptokeys.id=?
 godbc-update-account-query=update domains set account=? where name=?
 godbc-update-kind-query=update domains set type=? where name=?
 godbc-update-lastcheck-query=update domains set last_check=? where id=?
-godbc-update-master-query=update domains set master=? where name=?
+godbc-update-primary-query=update domains set master=? where name=?
 godbc-update-ordername-and-auth-query=update records set ordername=?,auth=? where domain_id=? and name=? and disabled=0
 godbc-update-ordername-and-auth-type-query=update records set ordername=?,auth=? where domain_id=? and name=? and type=? and disabled=0
 godbc-update-serial-query=update domains set notified_serial=? where id=?
index 7c727266ee73e2124958fe09cadd6d0722591bf9..e1b06f057279fcc9e91a27b9883a1fa12807e8b1 100644 (file)
@@ -27,7 +27,7 @@ __EOF__
                "$GPGSQL2DB"
                if [ "$zone" = "tsig.com" ]; then
                        $PDNSUTIL --config-dir=. --config-name=gpgsql2 import-tsig-key test $ALGORITHM $KEY
-                       $PDNSUTIL --config-dir=. --config-name=gpgsql2 activate-tsig-key tsig.com test slave
+                       $PDNSUTIL --config-dir=. --config-name=gpgsql2 activate-tsig-key tsig.com test secondary
                fi
                if [ "$zone" = "stest.com" ]; then
                        if [[ $skipreasons != *nolua* ]]; then
@@ -40,8 +40,8 @@ __EOF__
 
        $RUNWRAPPER $PDNS2 --daemon=no --local-port=$port --config-dir=. \
                --config-name=gpgsql2 --socket-dir=./ --no-shuffle \
-               --slave --retrieval-threads=4 \
-               --slave-cycle-interval=300 --dname-processing &
+               --secondary --retrieval-threads=4 \
+               --xfr-cycle-interval=300 --dname-processing &
 
        echo 'waiting for zones to be slaved'
        loopcount=0
index 494eb0a7f9c9003766541941f75cd25fc68a9539..a1134d23118c6dc1f41ad7f9ec84103d1b2960d1 100644 (file)
@@ -41,7 +41,7 @@ gsql_master()
         fi
         if [ "$zone" = "tsig.com" ]; then
             $PDNSUTIL --config-dir=. --config-name=$backend import-tsig-key test $ALGORITHM $KEY
-            $PDNSUTIL --config-dir=. --config-name=$backend activate-tsig-key tsig.com test master
+            $PDNSUTIL --config-dir=. --config-name=$backend activate-tsig-key tsig.com test primary
         fi
     done
 
index 88bea544966b8a7d157460e31df791cb150c3606..6dcc71376e892ab83826d60c37ca6aad0ef752ef 100644 (file)
@@ -22,7 +22,7 @@ __EOF__
                sqlite3 pdns.sqlite32 "INSERT INTO domains (name, type, master) VALUES('$zone','SLAVE','127.0.0.1:$port');"
                if [ "$zone" = "tsig.com" ]; then
                        $PDNSUTIL --config-dir=. --config-name=gsqlite32 import-tsig-key test $ALGORITHM $KEY
-                       $PDNSUTIL --config-dir=. --config-name=gsqlite32 activate-tsig-key tsig.com test slave
+                       $PDNSUTIL --config-dir=. --config-name=gsqlite32 activate-tsig-key tsig.com test secondary
                fi
                if [ "$zone" = "stest.com" ]; then
                        if [[ $skipreasons != *nolua* ]]; then
index 6b6a18016f8c42c67d7af90a27ba1f75fd36467d..c1bf9346b205b1cd6517b965c24947e4816eedda 100644 (file)
@@ -47,7 +47,7 @@ __EOF__
             fi
             if [ "$zone" = "tsig.com" ]; then
                 $PDNSUTIL --config-dir=. --config-name=lmdb import-tsig-key test $ALGORITHM $KEY
-                $PDNSUTIL --config-dir=. --config-name=lmdb activate-tsig-key tsig.com test master
+                $PDNSUTIL --config-dir=. --config-name=lmdb activate-tsig-key tsig.com test primary
             fi
         done
 
index e647349c1f2962e424414b8ff73fd63c505f576d..cad79ed1d771c9d11234bef6e5f7b740cd8ac7d8 100644 (file)
--- a/tasks.py
+++ b/tasks.py
@@ -152,7 +152,6 @@ doc_deps_pdf = [
 
 @task
 def apt_fresh(c):
-    c.sudo('sed -i \'s/azure\.//\' /etc/apt/sources.list')
     c.sudo('apt-get update')
     c.sudo('apt-get -y --allow-downgrades dist-upgrade')
 
@@ -180,7 +179,7 @@ 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(f'CC=clang-{clang_version} CXX=clang-{clang_version} '
+        c.run(f'CC={get_c_compiler()} CXX={get_cxx_compiler()} '
               'cmake -B build '
               '-DCMAKE_INSTALL_PREFIX=/usr/local '
               '-DCMAKE_INSTALL_LIBDIR=lib '
@@ -203,7 +202,8 @@ def install_doc_deps_pdf(c):
 @task
 def install_auth_build_deps(c):
     c.sudo('apt-get install -y --no-install-recommends ' + ' '.join(all_build_deps + git_build_deps + auth_build_deps))
-    install_libdecaf(c, 'pdns-auth')
+    if os.getenv('DECAF_SUPPORT', 'no') == 'yes':
+        install_libdecaf(c, 'pdns-auth')
 
 def is_coverage_enabled():
     sanitizers = os.getenv('SANITIZERS')
@@ -213,6 +213,9 @@ def is_coverage_enabled():
             return False
     return os.getenv('COVERAGE') == 'yes'
 
+def get_coverage():
+    return '--enable-coverage=clang' if is_coverage_enabled() else ''
+
 @task
 def install_coverage_deps(c):
     if is_coverage_enabled():
@@ -266,9 +269,10 @@ def install_auth_test_deps(c, backend): # FIXME: rename this, we do way more tha
     # FIXME we may want to start a background recursor here to make ALIAS tests more robust
     setup_authbind(c)
 
-    # Copy libdecaf out
-    c.sudo('mkdir -p /usr/local/lib')
-    c.sudo('cp /opt/pdns-auth/libdecaf/libdecaf.so* /usr/local/lib/.')
+    if os.getenv('DECAF_SUPPORT', 'no') == 'yes':
+        # Copy libdecaf out
+        c.sudo('mkdir -p /usr/local/lib')
+        c.sudo('cp /opt/pdns-auth/libdecaf/libdecaf.so* /usr/local/lib/.')
 
 @task
 def install_rec_bulk_deps(c): # FIXME: rename this, we do way more than apt-get
@@ -366,22 +370,46 @@ def ci_docs_add_ssh(c, ssh_key, host_key):
 
 
 def get_sanitizers():
-    sanitizers = os.getenv('SANITIZERS')
+    sanitizers = os.getenv('SANITIZERS', '')
     if sanitizers != '':
         sanitizers = sanitizers.split('+')
         sanitizers = ['--enable-' + sanitizer for sanitizer in sanitizers]
         sanitizers = ' '.join(sanitizers)
     return sanitizers
 
+def get_unit_tests(auth=False):
+    if os.getenv('UNIT_TESTS') != 'yes':
+        return ''
+    return '--enable-unit-tests --enable-backend-unit-tests' if auth else '--enable-unit-tests'
+
+def get_build_concurrency(default=8):
+    return os.getenv('CONCURRENCY', default)
+
+def get_fuzzing_targets():
+    return '--enable-fuzz-targets' if os.getenv('FUZZING_TARGETS') == 'yes' else ''
+
+def is_compiler_clang():
+    compiler = os.getenv('COMPILER', 'clang')
+    return compiler == 'clang'
+
+def get_c_compiler():
+    return f'clang-{clang_version}' if is_compiler_clang() else 'gcc'
+
+def get_cxx_compiler():
+    return f'clang++-{clang_version}' if is_compiler_clang() else 'g++'
+
+def get_optimizations():
+    optimizations = os.getenv('OPTIMIZATIONS', 'yes')
+    return '-O1' if optimizations == 'yes' else '-O0'
 
 def get_cflags():
     return " ".join([
-        "-O1",
+        get_optimizations(),
         "-Werror=vla",
         "-Werror=shadow",
         "-Wformat=2",
         "-Werror=format-security",
-        "-Werror=string-plus-int",
+        "-Werror=string-plus-int" if is_compiler_clang() else '',
     ])
 
 
@@ -392,35 +420,29 @@ def get_cxxflags():
     ])
 
 
-def get_base_configure_cmd():
+def get_base_configure_cmd(additional_c_flags='', additional_cxx_flags='', enable_systemd=True, enable_sodium=True):
+    cflags = " ".join([get_cflags(), additional_c_flags])
+    cxxflags = " ".join([get_cxxflags(), additional_cxx_flags])
     return " ".join([
-        f'CFLAGS="{get_cflags()}"',
-        f'CXXFLAGS="{get_cxxflags()}"',
+        f'CFLAGS="{cflags}"',
+        f'CXXFLAGS="{cxxflags}"',
         './configure',
-        f"CC='clang-{clang_version}'",
-        f"CXX='clang++-{clang_version}'",
+        f"CC='{get_c_compiler()}'",
+        f"CXX='{get_cxx_compiler()}'",
         "--enable-option-checking=fatal",
-        "--enable-systemd",
-        "--with-libsodium",
+        "--enable-systemd" if enable_systemd else '',
+        "--with-libsodium" if enable_sodium else '',
         "--enable-fortify-source=auto",
         "--enable-auto-var-init=pattern",
+        get_coverage(),
+        get_sanitizers()
     ])
 
 
 @task
 def ci_auth_configure(c):
-    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 ''
-    coverage = '--enable-coverage=clang' if is_coverage_enabled() else ''
-
+    unittests = get_unit_tests(True)
+    fuzz_targets = get_fuzzing_targets()
     modules = " ".join([
         "bind",
         "geoip",
@@ -440,17 +462,16 @@ def ci_auth_configure(c):
         "LDFLAGS='-L/usr/local/lib -Wl,-rpath,/usr/local/lib'",
         f"--with-modules='{modules}'",
         "--enable-tools",
+        "--enable-dns-over-tls",
         "--enable-experimental-pkcs11",
         "--enable-experimental-gss-tsig",
         "--enable-remotebackend-zeromq",
         "--with-lmdb=/usr",
-        "--with-libdecaf",
+        "--with-libdecaf" if os.getenv('DECAF_SUPPORT', 'no') == 'yes' else '',
         "--prefix=/opt/pdns-auth",
         "--enable-ixfrdist",
-        sanitizers,
         unittests,
-        fuzz_targets,
-        coverage,
+        fuzz_targets
     ])
     res = c.run(configure_cmd, warn=True)
     if res.exited != 0:
@@ -460,11 +481,7 @@ def ci_auth_configure(c):
 
 @task
 def ci_rec_configure(c):
-    sanitizers = get_sanitizers()
-
-    unittests = os.getenv('UNIT_TESTS')
-    unittests = '--enable-unit-tests' if unittests == 'yes' else ''
-    coverage = '--enable-coverage=clang' if is_coverage_enabled() else ''
+    unittests = get_unit_tests()
 
     configure_cmd = " ".join([
         get_base_configure_cmd(),
@@ -474,9 +491,7 @@ def ci_rec_configure(c):
         "--with-libcap",
         "--with-net-snmp",
         "--enable-dns-over-tls",
-        sanitizers,
         unittests,
-        coverage,
     ])
     res = c.run(configure_cmd, warn=True)
     if res.exited != 0:
@@ -502,7 +517,7 @@ def ci_dnsdist_configure(c, features):
                       --with-libcap \
                       --with-net-snmp \
                       --with-nghttp2 \
-                      --with-re2 '
+                      --with-re2'
     else:
       features_set = '--disable-dnstap \
                       --disable-dnscrypt \
@@ -517,7 +532,7 @@ def ci_dnsdist_configure(c, features):
                       --without-lmdb \
                       --without-net-snmp \
                       --without-nghttp2 \
-                      --without-re2 '
+                      --without-re2'
       additional_flags = '-DDISABLE_COMPLETION \
                           -DDISABLE_DELAY_PIPE \
                           -DDISABLE_DYNBLOCKS \
@@ -549,55 +564,49 @@ def ci_dnsdist_configure(c, features):
                           -DDISABLE_HASHED_CREDENTIALS \
                           -DDISABLE_FALSE_SHARING_PADDING \
                           -DDISABLE_NPN'
-    unittests = ' --enable-unit-tests' if os.getenv('UNIT_TESTS') == 'yes' else ''
-    fuzztargets = '--enable-fuzz-targets' if os.getenv('FUZZING_TARGETS') == 'yes' else ''
-    sanitizers = ' '.join('--enable-'+x for x in os.getenv('SANITIZERS').split('+')) if os.getenv('SANITIZERS') != '' else ''
-    coverage = '--enable-coverage=clang' if is_coverage_enabled() else ''
-    cflags = get_cflags()
-    cxxflags = " ".join([get_cxxflags(), additional_flags])
-    res = c.run(f'''CFLAGS="%s" \
-                   CXXFLAGS="%s" \
-                   AR=llvm-ar-{clang_version} \
-                   RANLIB=llvm-ranlib-{clang_version} \
-                   ./configure \
-                     CC='clang-{clang_version}' \
-                     CXX='clang++-{clang_version}' \
-                     --enable-option-checking=fatal \
-                     --enable-fortify-source=auto \
-                     --enable-auto-var-init=pattern \
-                     --enable-lto=thin \
-                     --prefix=/opt/dnsdist %s %s %s %s %s''' % (cflags, cxxflags, features_set, sanitizers, unittests, fuzztargets, coverage), warn=True)
+    unittests = get_unit_tests()
+    fuzztargets = get_fuzzing_targets()
+    tools = f'''AR=llvm-ar-{clang_version} RANLIB=llvm-ranlib-{clang_version}''' if is_compiler_clang() else ''
+    configure_cmd = " ".join([
+        tools,
+        get_base_configure_cmd(additional_c_flags='', additional_cxx_flags=additional_flags, enable_systemd=False, enable_sodium=False),
+        features_set,
+        unittests,
+        fuzztargets,
+        ' --enable-lto=thin',
+        '--prefix=/opt/dnsdist'
+    ])
+
+    res = c.run(configure_cmd, warn=True)
     if res.exited != 0:
         c.run('cat config.log')
         raise UnexpectedExit(res)
 
 @task
 def ci_auth_make(c):
-    c.run('make -j8 -k V=1')
+    c.run(f'make -j{get_build_concurrency()} -k V=1')
 
 @task
 def ci_auth_make_bear(c):
-    # Needed for clang-tidy -line-filter vs project structure shenanigans
-    with c.cd('pdns'):
-        c.run('bear --append -- make -j8 -k V=1 -C ..')
+    c.run(f'bear --append -- make -j{get_build_concurrency()} -k V=1')
 
 @task
 def ci_rec_make(c):
-    c.run('make -j8 -k V=1')
+    c.run(f'make -j{get_build_concurrency()} -k V=1')
 
 @task
 def ci_rec_make_bear(c):
     # Assumed to be running under ./pdns/recursordist/
-    c.run('bear --append -- make -j8 -k V=1')
+    c.run(f'bear --append -- make -j{get_build_concurrency()} -k V=1')
 
 @task
 def ci_dnsdist_make(c):
-    c.run('make -j4 -k V=1')
+    c.run(f'make -j{get_build_concurrency(4)} -k V=1')
 
 @task
 def ci_dnsdist_make_bear(c):
     # Assumed to be running under ./pdns/dnsdistdist/
-    c.run('bear --append -- make -j4 -k V=1')
+    c.run(f'bear --append -- make -j{get_build_concurrency(4)} -k V=1')
 
 @task
 def ci_auth_install_remotebackend_test_deps(c):