Package: release.debian.org Severity: normal X-Debbugs-Cc: p...@packages.debian.org Control: affects -1 + src:pdns User: release.debian....@packages.debian.org Usertags: unblock
Please unblock package pdns pdns 4.9.7 is an upstream bugfix release in the 4.9 series. Previously we had 4.9.4; upstream released 4.9.5 (after the freeze started) and 4.9.7 (today) - 4.9.6 was skipped. I'd like to take the latest upstream release into unstable and testing. Have not uploaded it yet. [ Reason ] Accepting the upstream bugfix release will hopefully make applying future security fixes easier, or we can just use a future bugfix release for them. 4.9.5 includes the patch we applied to 4.9.4 to fix tests on s390x. [ Impact ] If we stay on 4.9.4, the diff for security fixes will be larger and thus harder. We'll also miss out on upstream bug- and performance-fixes to the LMDB backend, better exception handling in Lua functions leading to SERVFAILs, an interop fix for TSIG and a compile fix for newer gcc. [ Tests ] In Debian we only have smoke tests, however they did find the s390x mysql issue in the past. Upstream has a big test suite they run for releases. [ Risks ] Not sure. The diff seems right to me for the fixes upstream described. [ Checklist ] [x] all changes are documented in the d/changelog [x] I reviewed all changes and I approve them [x] attach debdiff against the package in testing [ Other info ] The attached debdiff was produced using: debdiff pdns_4.9.4-2.dsc pdns_4.9.7-1.dsc | filterdiff -x '*.1' > pdns_4.9.7-1.filtered.debdiff to exclude the date changes to the xxx.1 manpages. unblock pdns/4.9.7-1
diff -Nru pdns-4.9.4/configure pdns-4.9.7/configure --- pdns-4.9.4/configure 2025-02-06 16:18:00.000000000 +0100 +++ pdns-4.9.7/configure 2025-07-07 09:42:38.000000000 +0200 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for pdns 4.9.4. +# Generated by GNU Autoconf 2.71 for pdns 4.9.7. # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, @@ -618,8 +618,8 @@ # Identity of this package. PACKAGE_NAME='pdns' PACKAGE_TARNAME='pdns' -PACKAGE_VERSION='4.9.4' -PACKAGE_STRING='pdns 4.9.4' +PACKAGE_VERSION='4.9.7' +PACKAGE_STRING='pdns 4.9.7' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1698,7 +1698,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures pdns 4.9.4 to adapt to many kinds of systems. +\`configure' configures pdns 4.9.7 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1769,7 +1769,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of pdns 4.9.4:";; + short | recursive ) echo "Configuration of pdns 4.9.7:";; esac cat <<\_ACEOF @@ -2040,7 +2040,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -pdns configure 4.9.4 +pdns configure 4.9.7 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -2529,7 +2529,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by pdns $as_me 4.9.4, which was +It was created by pdns $as_me 4.9.7, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -4027,7 +4027,7 @@ # Define the identity of the package. PACKAGE='pdns' - VERSION='4.9.4' + VERSION='4.9.7' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -32467,7 +32467,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by pdns $as_me 4.9.4, which was +This file was extended by pdns $as_me 4.9.7, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -32535,7 +32535,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -pdns config.status 4.9.4 +pdns config.status 4.9.7 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff -Nru pdns-4.9.4/configure.ac pdns-4.9.7/configure.ac --- pdns-4.9.4/configure.ac 2025-02-06 16:17:52.000000000 +0100 +++ pdns-4.9.7/configure.ac 2025-07-07 09:42:29.000000000 +0200 @@ -1,6 +1,6 @@ AC_PREREQ([2.69]) -AC_INIT([pdns], [4.9.4]) +AC_INIT([pdns], [4.9.7]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE([foreign dist-bzip2 no-dist-gzip tar-ustar -Wno-portability subdir-objects parallel-tests 1.11]) AM_SILENT_RULES([yes]) diff -Nru pdns-4.9.4/debian/changelog pdns-4.9.7/debian/changelog --- pdns-4.9.4/debian/changelog 2025-03-21 13:09:53.000000000 +0100 +++ pdns-4.9.7/debian/changelog 2025-07-07 12:15:52.000000000 +0200 @@ -1,3 +1,10 @@ +pdns (4.9.7-1) unstable; urgency=medium + + * New upstream version 4.9.7 + * Drop upstream-applied patch + + -- Chris Hofstaedtler <z...@debian.org> Mon, 07 Jul 2025 12:15:52 +0200 + pdns (4.9.4-2) unstable; urgency=medium * Add upstream-pending patch to fix mysqlbackend on s390x diff -Nru pdns-4.9.4/debian/patches/series pdns-4.9.7/debian/patches/series --- pdns-4.9.4/debian/patches/series 2025-03-21 13:09:34.000000000 +0100 +++ pdns-4.9.7/debian/patches/series 2025-07-07 12:15:39.000000000 +0200 @@ -1 +0,0 @@ -upstream/0001-mysql-use-MYSQL_TYPE_LONGLONG-on-64bit-platforms.patch diff -Nru pdns-4.9.4/debian/patches/upstream/0001-mysql-use-MYSQL_TYPE_LONGLONG-on-64bit-platforms.patch pdns-4.9.7/debian/patches/upstream/0001-mysql-use-MYSQL_TYPE_LONGLONG-on-64bit-platforms.patch --- pdns-4.9.4/debian/patches/upstream/0001-mysql-use-MYSQL_TYPE_LONGLONG-on-64bit-platforms.patch 2025-03-21 13:09:34.000000000 +0100 +++ pdns-4.9.7/debian/patches/upstream/0001-mysql-use-MYSQL_TYPE_LONGLONG-on-64bit-platforms.patch 1970-01-01 01:00:00.000000000 +0100 @@ -1,43 +0,0 @@ -From: Chris Hofstaedtler <chris.hofstaedt...@deduktiva.com> -Date: Fri, 21 Mar 2025 12:54:21 +0100 -Subject: mysql: use MYSQL_TYPE_LONGLONG on 64bit platforms - -Found on s390x. - -https://github.com/PowerDNS/pdns/pull/15340/ ---- - modules/gmysqlbackend/smysql.cc | 14 ++++++++++++-- - 1 file changed, 12 insertions(+), 2 deletions(-) - -diff --git a/modules/gmysqlbackend/smysql.cc b/modules/gmysqlbackend/smysql.cc -index efcbffd..4cc7856 100644 ---- a/modules/gmysqlbackend/smysql.cc -+++ b/modules/gmysqlbackend/smysql.cc -@@ -116,7 +116,12 @@ public: - releaseStatement(); - throw SSqlException("Attempt to bind more parameters than query has: " + d_query); - } -- d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONG; -+ if constexpr (sizeof(long) == 4) { -+ d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONG; -+ } -+ else { -+ d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONGLONG; -+ } - d_req_bind[d_paridx].buffer = new long[1]; - *((long*)d_req_bind[d_paridx].buffer) = value; - d_paridx++; -@@ -129,7 +134,12 @@ public: - releaseStatement(); - throw SSqlException("Attempt to bind more parameters than query has: " + d_query); - } -- d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONG; -+ if constexpr (sizeof(long) == 4) { -+ d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONG; -+ } -+ else { -+ d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONGLONG; -+ } - d_req_bind[d_paridx].buffer = new unsigned long[1]; - d_req_bind[d_paridx].is_unsigned = 1; - *((unsigned long*)d_req_bind[d_paridx].buffer) = value; diff -Nru pdns-4.9.4/docs/ixfrdist.yml.5 pdns-4.9.7/docs/ixfrdist.yml.5 --- pdns-4.9.4/docs/ixfrdist.yml.5 2025-02-06 16:19:08.000000000 +0100 +++ pdns-4.9.7/docs/ixfrdist.yml.5 2025-07-07 09:43:48.000000000 +0200 @@ -27,7 +27,7 @@ .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "IXFRDIST.YML" "5" "Feb 06, 2025" "" "PowerDNS Authoritative Server" +.TH "IXFRDIST.YML" "5" "Jul 07, 2025" "" "PowerDNS Authoritative Server" .SH NAME ixfrdist.yml \- The ixfrdist configuration file .SH SYNOPSIS diff -Nru pdns-4.9.4/ext/lmdb-safe/lmdb-safe.hh pdns-4.9.7/ext/lmdb-safe/lmdb-safe.hh --- pdns-4.9.4/ext/lmdb-safe/lmdb-safe.hh 2025-02-06 16:17:38.000000000 +0100 +++ pdns-4.9.7/ext/lmdb-safe/lmdb-safe.hh 2025-07-07 09:42:15.000000000 +0200 @@ -12,6 +12,8 @@ #include <mutex> #include <vector> #include <algorithm> +#include <string> +#include <string_view> #include "config.h" @@ -24,6 +26,13 @@ #endif using std::string_view; +using std::string; + +#if BOOST_VERSION >= 106100 +#define StringView string_view +#else +#define StringView string +#endif /* open issues: * @@ -98,7 +107,7 @@ std::map<std::thread::id, int> d_ROtransactionsOut; }; -std::shared_ptr<MDBEnv> getMDBEnv(const char* fname, int flags, int mode, uint64_t mapsizeMB=(sizeof(void *)==4) ? 100 : 16000); +std::shared_ptr<MDBEnv> getMDBEnv(const char* fname, int flags, int mode, uint64_t mapsizeMB); #ifndef DNSDIST @@ -300,6 +309,9 @@ return ret; } + template <class T> + T get() const; + operator MDB_val&() { return d_mdbval; @@ -312,6 +324,12 @@ #endif }; +template <> +inline std::string MDBInVal::get<std::string>() const +{ + return {static_cast<char*>(d_mdbval.mv_data), d_mdbval.mv_size}; +} + class MDBROCursor; class MDBROTransactionImpl @@ -415,6 +433,7 @@ private: std::vector<T*> *d_registry; MDB_cursor* d_cursor{nullptr}; + std::string d_prefix{""}; public: MDB_txn* d_txn{nullptr}; // ew, public uint64_t d_txtime{0}; @@ -523,6 +542,9 @@ while (true) { auto sval = data.getNoStripHeader<std::string_view>(); + if (d_prefix.length() > 0 && key.getNoStripHeader<StringView>().rfind(d_prefix, 0) != 0) { + return MDB_NOTFOUND; + } if (!LMDBLS::LSisDeleted(sval)) { // done! @@ -573,6 +595,7 @@ public: int get(MDBOutVal& key, MDBOutVal& data, MDB_cursor_op op) { + d_prefix.clear(); int rc = mdb_cursor_get(d_cursor, &key.d_mdbval, &data.d_mdbval, op); if(rc && rc != MDB_NOTFOUND) throw std::runtime_error("Unable to get from cursor: " + std::string(mdb_strerror(rc))); @@ -581,6 +604,7 @@ int find(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data) { + d_prefix.clear(); key.d_mdbval = in.d_mdbval; int rc=mdb_cursor_get(d_cursor, const_cast<MDB_val*>(&key.d_mdbval), &data.d_mdbval, MDB_SET); if(rc && rc != MDB_NOTFOUND) @@ -588,8 +612,20 @@ return skipDeleted(key, data, MDB_SET, rc); } + int prefix(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data) + { + d_prefix = in.get<string>(); + return _lower_bound(in, key, data); + } + int lower_bound(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data) { + d_prefix.clear(); + return _lower_bound(in, key, data); + } + + int _lower_bound(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data) // used by prefix() and lower_bound() + { key.d_mdbval = in.d_mdbval; int rc = mdb_cursor_get(d_cursor, const_cast<MDB_val*>(&key.d_mdbval), &data.d_mdbval, MDB_SET_RANGE); diff -Nru pdns-4.9.4/ext/lmdb-safe/lmdb-typed.hh pdns-4.9.7/ext/lmdb-safe/lmdb-typed.hh --- pdns-4.9.4/ext/lmdb-safe/lmdb-typed.hh 2025-02-06 16:17:38.000000000 +0100 +++ pdns-4.9.7/ext/lmdb-safe/lmdb-typed.hh 2025-07-07 09:42:15.000000000 +0200 @@ -284,14 +284,19 @@ // } //! Get item with id, from main table directly - bool get(uint32_t id, T& t) + int get2(uint32_t itemId, T& value) { - MDBOutVal data; - if((*d_parent.d_txn)->get(d_parent.d_parent->d_main, id, data)) - return false; - - serFromString(data.get<std::string>(), t); - return true; + MDBOutVal data{}; + int rc; + rc = (*d_parent.d_txn)->get(d_parent.d_parent->d_main, itemId, data); + if (rc == 0) { + serFromString(data.get<std::string>(), value); + } + return rc; + } + bool get(uint32_t itemId, T& value) + { + return get2(itemId, value) == 0; } //! Get item through index N, then via the main database @@ -309,17 +314,24 @@ // because we know we only want one item, pass onlyOldest=true to consistently get the same one out of a set of duplicates get_multi<N>(key, ids, true); - if (ids.size() == 0) { + switch (ids.size()) { + case 0: return 0; - } - - if (ids.size() == 1) { - if (get(ids[0], out)) { + case 1: { + auto rc = get2(ids[0], out); + if (rc == 0) { return ids[0]; } + if (rc == MDB_NOTFOUND) { + /* element not present, or has been marked deleted */ + return 0; + } + throw std::runtime_error("in index get, failed (" + std::to_string(rc) + ")"); + break; + } + default: + throw std::runtime_error("in index get, found more than one item"); } - - throw std::runtime_error("in index get, found more than one item"); } // //! Cardinality of index N diff -Nru pdns-4.9.4/modules/gmysqlbackend/smysql.cc pdns-4.9.7/modules/gmysqlbackend/smysql.cc --- pdns-4.9.4/modules/gmysqlbackend/smysql.cc 2025-02-06 16:17:38.000000000 +0100 +++ pdns-4.9.7/modules/gmysqlbackend/smysql.cc 2025-07-07 09:42:15.000000000 +0200 @@ -116,7 +116,12 @@ releaseStatement(); throw SSqlException("Attempt to bind more parameters than query has: " + d_query); } - d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONG; + if constexpr (sizeof(long) == 4) { + d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONG; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + } + else { + d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONGLONG; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + } d_req_bind[d_paridx].buffer = new long[1]; *((long*)d_req_bind[d_paridx].buffer) = value; d_paridx++; @@ -129,7 +134,12 @@ releaseStatement(); throw SSqlException("Attempt to bind more parameters than query has: " + d_query); } - d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONG; + if constexpr (sizeof(long) == 4) { + d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONG; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + } + else { + d_req_bind[d_paridx].buffer_type = MYSQL_TYPE_LONGLONG; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + } d_req_bind[d_paridx].buffer = new unsigned long[1]; d_req_bind[d_paridx].is_unsigned = 1; *((unsigned long*)d_req_bind[d_paridx].buffer) = value; diff -Nru pdns-4.9.4/modules/lmdbbackend/lmdbbackend.cc pdns-4.9.7/modules/lmdbbackend/lmdbbackend.cc --- pdns-4.9.4/modules/lmdbbackend/lmdbbackend.cc 2025-02-06 16:17:38.000000000 +0100 +++ pdns-4.9.7/modules/lmdbbackend/lmdbbackend.cc 2025-07-07 09:42:15.000000000 +0200 @@ -656,8 +656,6 @@ string syncMode = toLower(getArg("sync-mode")); - d_random_ids = mustDo("random-ids"); - if (syncMode == "nosync") d_asyncFlag = MDB_NOSYNC; else if (syncMode == "nometasync") @@ -667,17 +665,14 @@ else throw std::runtime_error("Unknown sync mode " + syncMode + " requested for LMDB backend"); - uint64_t mapSize = 0; + d_mapsize = 0; try { - mapSize = std::stoll(getArg("map-size")); + d_mapsize = std::stoll(getArg("map-size")); } catch (const std::exception& e) { throw std::runtime_error(std::string("Unable to parse the 'map-size' LMDB value: ") + e.what()); } - LMDBLS::s_flag_deleted = mustDo("flag-deleted"); - d_handle_dups = false; - if (mustDo("lightning-stream")) { d_random_ids = true; d_handle_dups = true; @@ -687,6 +682,11 @@ throw std::runtime_error(std::string("running with Lightning Stream support requires shards=1")); } } + else { + d_random_ids = mustDo("random-ids"); + d_handle_dups = false; + LMDBLS::s_flag_deleted = mustDo("flag-deleted"); + } bool opened = false; @@ -723,7 +723,7 @@ throw std::runtime_error("Somehow, we are not at schema version 5. Giving up"); } - d_tdomains = std::make_shared<tdomains_t>(getMDBEnv(getArg("filename").c_str(), MDB_NOSUBDIR | d_asyncFlag, 0600, mapSize), "domains_v5"); + d_tdomains = std::make_shared<tdomains_t>(getMDBEnv(getArg("filename").c_str(), MDB_NOSUBDIR | d_asyncFlag, 0600, d_mapsize), "domains_v5"); d_tmeta = std::make_shared<tmeta_t>(d_tdomains->getEnv(), "metadata_v5"); d_tkdb = std::make_shared<tkdb_t>(d_tdomains->getEnv(), "keydata_v5"); d_ttsig = std::make_shared<ttsig_t>(d_tdomains->getEnv(), "tsig_v5"); @@ -770,7 +770,7 @@ } if (!opened) { - d_tdomains = std::make_shared<tdomains_t>(getMDBEnv(getArg("filename").c_str(), MDB_NOSUBDIR | d_asyncFlag, 0600, mapSize), "domains_v5"); + d_tdomains = std::make_shared<tdomains_t>(getMDBEnv(getArg("filename").c_str(), MDB_NOSUBDIR | d_asyncFlag, 0600, d_mapsize), "domains_v5"); d_tmeta = std::make_shared<tmeta_t>(d_tdomains->getEnv(), "metadata_v5"); d_tkdb = std::make_shared<tkdb_t>(d_tdomains->getEnv(), "keydata_v5"); d_ttsig = std::make_shared<ttsig_t>(d_tdomains->getEnv(), "tsig_v5"); @@ -1211,7 +1211,7 @@ auto& shard = d_trecords[id % s_shards]; if (!shard.env) { shard.env = getMDBEnv((getArg("filename") + "-" + std::to_string(id % s_shards)).c_str(), - MDB_NOSUBDIR | d_asyncFlag, 0600); + MDB_NOSUBDIR | d_asyncFlag, 0600, d_mapsize); shard.dbi = shard.env->openDB("records_v5", MDB_CREATE); } auto ret = std::make_shared<RecordsRWTransaction>(shard.env->getRWTransaction()); @@ -1228,7 +1228,7 @@ throw DBException("attempting to start nested transaction without open parent env"); } shard.env = getMDBEnv((getArg("filename") + "-" + std::to_string(id % s_shards)).c_str(), - MDB_NOSUBDIR | d_asyncFlag, 0600); + MDB_NOSUBDIR | d_asyncFlag, 0600, d_mapsize); shard.dbi = shard.env->openDB("records_v5", MDB_CREATE); } @@ -1405,10 +1405,7 @@ d_matchkey = co(di.id); MDBOutVal key, val; - auto a = d_getcursor->lower_bound(d_matchkey, key, val); - auto b0 = key.getNoStripHeader<StringView>(); - auto b = b0.rfind(d_matchkey, 0); - if (a || b != 0) { + if (d_getcursor->prefix(d_matchkey, key, val) != 0) { d_getcursor.reset(); } @@ -1470,7 +1467,7 @@ d_matchkey = co(zoneId, relqname, type.getCode()); } - if (d_getcursor->lower_bound(d_matchkey, key, val) || key.getNoStripHeader<StringView>().rfind(d_matchkey, 0) != 0) { + if (d_getcursor->prefix(d_matchkey, key, val) != 0) { d_getcursor.reset(); if (d_dolog) { g_log << Logger::Warning << "Query " << ((long)(void*)this) << ": " << d_dtime.udiffNoReset() << " us to execute (found nothing)" << endl; @@ -1508,7 +1505,7 @@ if (zr.dr.d_type == QType::NSEC3) { // Hit a magic NSEC3 skipping - if (d_getcursor->next(d_currentKey, d_currentVal) || d_currentKey.getNoStripHeader<StringView>().rfind(d_matchkey, 0) != 0) { + if (d_getcursor->next(d_currentKey, d_currentVal) != 0) { // cerr<<"resetting d_getcursor 1"<<endl; d_getcursor.reset(); } @@ -1536,7 +1533,7 @@ if (d_currentrrsetpos >= d_currentrrset.size()) { d_currentrrset.clear(); // will invalidate lrr - if (d_getcursor->next(d_currentKey, d_currentVal) || d_currentKey.getNoStripHeader<StringView>().rfind(d_matchkey, 0) != 0) { + if (d_getcursor->next(d_currentKey, d_currentVal) != 0) { // cerr<<"resetting d_getcursor 2"<<endl; d_getcursor.reset(); } @@ -2423,7 +2420,7 @@ auto cursor = txn->txn->getCursor(txn->db->dbi); MDBOutVal key, val; - if (cursor.lower_bound(matchkey, key, val)) { + if (cursor.prefix(matchkey, key, val) != 0) { // cout << "Could not find anything"<<endl; return false; } @@ -2431,7 +2428,7 @@ bool hasOrderName = !ordername.empty(); bool needNSEC3 = hasOrderName; - for (; key.getNoStripHeader<StringView>().rfind(matchkey, 0) == 0;) { + do { vector<LMDBResourceRecord> lrrs; if (co.getQType(key.getNoStripHeader<StringView>()) != QType::NSEC3) { @@ -2456,9 +2453,7 @@ } } - if (cursor.next(key, val)) - break; - } + } while (cursor.next(key, val) == 0); bool del = false; LMDBResourceRecord lrr; diff -Nru pdns-4.9.4/modules/lmdbbackend/lmdbbackend.hh pdns-4.9.7/modules/lmdbbackend/lmdbbackend.hh --- pdns-4.9.4/modules/lmdbbackend/lmdbbackend.hh 2025-02-06 16:17:38.000000000 +0100 +++ pdns-4.9.7/modules/lmdbbackend/lmdbbackend.hh 2025-07-07 09:42:15.000000000 +0200 @@ -333,4 +333,5 @@ bool d_random_ids; bool d_handle_dups; DTime d_dtime; // used only for logging + uint64_t d_mapsize; }; diff -Nru pdns-4.9.4/pdns/credentials.hh pdns-4.9.7/pdns/credentials.hh --- pdns-4.9.4/pdns/credentials.hh 2025-02-06 16:17:38.000000000 +0100 +++ pdns-4.9.7/pdns/credentials.hh 2025-07-07 09:42:15.000000000 +0200 @@ -21,7 +21,7 @@ */ #pragma once -#include <memory> +#include <cstdint> #include <string> class SensitiveData diff -Nru pdns-4.9.4/pdns/dnssecinfra.cc pdns-4.9.7/pdns/dnssecinfra.cc --- pdns-4.9.4/pdns/dnssecinfra.cc 2025-02-06 16:17:38.000000000 +0100 +++ pdns-4.9.7/pdns/dnssecinfra.cc 2025-07-07 09:42:15.000000000 +0200 @@ -782,7 +782,7 @@ DNSPacketWriter dw(signVect, DNSName(), 0); auto pos=signVect.size(); if(!timersonly) { - dw.xfrName(tsigKeyName, false); + dw.xfrName(tsigKeyName.makeLowerCase(), false); dw.xfr16BitInt(QClass::ANY); // class dw.xfr32BitInt(0); // TTL dw.xfrName(trc.d_algoName.makeLowerCase(), false); diff -Nru pdns-4.9.4/pdns/lua-record.cc pdns-4.9.7/pdns/lua-record.cc --- pdns-4.9.4/pdns/lua-record.cc 2025-02-06 16:17:38.000000000 +0100 +++ pdns-4.9.7/pdns/lua-record.cc 2025-07-07 09:42:15.000000000 +0200 @@ -915,81 +915,87 @@ return std::string("error"); }); lua.writeFunction("createForward", []() { - static string allZerosIP("0.0.0.0"); - DNSName rel=s_lua_record_ctx->qname.makeRelative(s_lua_record_ctx->zone); - // parts is something like ["1", "2", "3", "4", "static"] or - // ["1", "2", "3", "4"] or ["ip40414243", "ip-addresses", ...] - auto parts = rel.getRawLabels(); - // Yes, this still breaks if an 1-2-3-4.XXXX is nested too deeply... - if(parts.size()>=4) { - try { - ComboAddress ca(parts[0]+"."+parts[1]+"."+parts[2]+"."+parts[3]); - return ca.toString(); - } catch (const PDNSException &e) { - return allZerosIP; - } - } else if (!parts.empty()) { - auto& input = parts.at(0); - - // allow a word without - in front, as long as it does not contain anything that could be a number - size_t nonhexprefix = strcspn(input.c_str(), "0123456789abcdefABCDEF"); - if (nonhexprefix > 0) { - input = input.substr(nonhexprefix); - } - - // either hex string, or 12-13-14-15 - vector<string> ip_parts; - - stringtok(ip_parts, input, "-"); - unsigned int x1, x2, x3, x4; - if (ip_parts.size() >= 4) { - // 1-2-3-4 with any prefix (e.g. ip-foo-bar-1-2-3-4) - string ret; - for (size_t index=4; index > 0; index--) { - auto octet = ip_parts[ip_parts.size() - index]; - try { - auto octetVal = std::stol(octet); + static string allZerosIP{"0.0.0.0"}; + try { + DNSName rel{s_lua_record_ctx->qname.makeRelative(s_lua_record_ctx->zone)}; + + // parts is something like ["1", "2", "3", "4", "static"] or + // ["1", "2", "3", "4"] or ["ip40414243", "ip-addresses", ...] + auto parts = rel.getRawLabels(); + // Yes, this still breaks if an 1-2-3-4.XXXX is nested too deeply... + if (parts.size() >= 4) { + ComboAddress address(parts[0]+"."+parts[1]+"."+parts[2]+"."+parts[3]); + return address.toString(); + } + if (!parts.empty()) { + auto& input = parts.at(0); + + // allow a word without - in front, as long as it does not contain anything that could be a number + size_t nonhexprefix = strcspn(input.c_str(), "0123456789abcdefABCDEF"); + if (nonhexprefix > 0) { + input = input.substr(nonhexprefix); + } + + // either hex string, or 12-13-14-15 + vector<string> ip_parts; + + stringtok(ip_parts, input, "-"); + if (ip_parts.size() >= 4) { + // 1-2-3-4 with any prefix (e.g. ip-foo-bar-1-2-3-4) + string ret; + for (size_t index=4; index > 0; index--) { + auto octet = ip_parts.at(ip_parts.size() - index); + auto octetVal = std::stol(octet); // may throw if (octetVal >= 0 && octetVal <= 255) { - ret += ip_parts.at(ip_parts.size() - index) + "."; + ret += octet + "."; } else { return allZerosIP; } - } catch (const std::exception &e) { - return allZerosIP; } + ret.resize(ret.size() - 1); // remove trailing dot after last octet + return ret; } - ret.resize(ret.size() - 1); // remove trailing dot after last octet - return ret; - } - if(input.length() >= 8) { - auto last8 = input.substr(input.length()-8); - if(sscanf(last8.c_str(), "%02x%02x%02x%02x", &x1, &x2, &x3, &x4)==4) { - return std::to_string(x1) + "." + std::to_string(x2) + "." + std::to_string(x3) + "." + std::to_string(x4); + if (input.length() >= 8) { + auto last8 = input.substr(input.length()-8); + unsigned int part1{0}; + unsigned int part2{0}; + unsigned int part3{0}; + unsigned int part4{0}; + if (sscanf(last8.c_str(), "%02x%02x%02x%02x", &part1, &part2, &part3, &part4) == 4) { + ComboAddress address(std::to_string(part1) + "." + std::to_string(part2) + "." + std::to_string(part3) + "." + std::to_string(part4)); + return address.toString(); + } } } + return allZerosIP; + } catch (const PDNSException &e) { + return allZerosIP; } - return allZerosIP; }); lua.writeFunction("createForward6", []() { - DNSName rel=s_lua_record_ctx->qname.makeRelative(s_lua_record_ctx->zone); - auto parts = rel.getRawLabels(); - if(parts.size()==8) { - string tot; - for(int i=0; i<8; ++i) { - if(i) - tot.append(1,':'); - tot+=parts[i]; + static string allZerosIP{"::"}; + try { + DNSName rel{s_lua_record_ctx->qname.makeRelative(s_lua_record_ctx->zone)}; + + auto parts = rel.getRawLabels(); + if (parts.size() == 8) { + string tot; + for (int chunk = 0; chunk < 8; ++chunk) { + if (chunk != 0) { + tot.append(1, ':'); + } + tot += parts.at(chunk); + } + ComboAddress address(tot); + return address.toString(); } - ComboAddress ca(tot); - return ca.toString(); - } - else if(parts.size()==1) { - if (parts[0].find('-') != std::string::npos) { - boost::replace_all(parts[0],"-",":"); - ComboAddress ca(parts[0]); - return ca.toString(); - } else { + if (parts.size() == 1) { + if (parts[0].find('-') != std::string::npos) { + std::replace(parts[0].begin(), parts[0].end(), '-', ':'); + ComboAddress address(parts[0]); + return address.toString(); + } if (parts[0].size() >= 32) { auto ippart = parts[0].substr(parts[0].size()-32); auto fulladdress = @@ -1002,57 +1008,63 @@ ippart.substr(24, 4) + ":" + ippart.substr(28, 4); - ComboAddress ca(fulladdress); - return ca.toString(); + ComboAddress address(fulladdress); + return address.toString(); } } + return allZerosIP; + } catch (const PDNSException &e) { + return allZerosIP; } - - return std::string("::"); }); - lua.writeFunction("createReverse6", [](string format, boost::optional<std::unordered_map<string,string>> e){ + lua.writeFunction("createReverse6", [](const string &format, boost::optional<std::unordered_map<string,string>> excp){ vector<ComboAddress> candidates; try { auto labels= s_lua_record_ctx->qname.getRawLabels(); - if(labels.size()<32) + if (labels.size()<32) { return std::string("unknown"); + } boost::format fmt(format); fmt.exceptions( boost::io::all_error_bits ^ ( boost::io::too_many_args_bit | boost::io::too_few_args_bit ) ); string together; vector<string> quads; - for(int i=0; i<8; ++i) { - if(i) - together+=":"; + for (int chunk = 0; chunk < 8; ++chunk) { + if (chunk != 0) { + together += ":"; + } string lquad; - for(int j=0; j <4; ++j) { - lquad.append(1, labels[31-i*4-j][0]); - together += labels[31-i*4-j][0]; + for (int quartet = 0; quartet < 4; ++quartet) { + lquad.append(1, labels[31 - chunk * 4 - quartet][0]); + together += labels[31 - chunk * 4 - quartet][0]; } quads.push_back(lquad); } - ComboAddress ip6(together,0); + ComboAddress ip6(together,0); - if(e) { - auto& addrs=*e; + if (excp) { + auto& addrs=*excp; for(const auto& addr: addrs) { // this makes sure we catch all forms of the address - if(ComboAddress(addr.first,0)==ip6) + if (ComboAddress(addr.first, 0) == ip6) { return addr.second; + } } } string dashed=ip6.toString(); boost::replace_all(dashed, ":", "-"); - for(int i=31; i>=0; --i) - fmt % labels[i]; + for (int byte = 31; byte >= 0; --byte) { + fmt % labels[byte]; + } fmt % dashed; - for(const auto& lquad : quads) + for(const auto& lquad : quads) { fmt % lquad; + } return fmt.str(); } diff -Nru pdns-4.9.4/pdns/test-tsig.cc pdns-4.9.7/pdns/test-tsig.cc --- pdns-4.9.4/pdns/test-tsig.cc 2025-02-06 16:17:38.000000000 +0100 +++ pdns-4.9.7/pdns/test-tsig.cc 2025-07-07 09:42:15.000000000 +0200 @@ -141,6 +141,17 @@ checkTSIG(tsigName, tsigAlgo.makeLowerCase(), tsigSecret, packet); } +BOOST_AUTO_TEST_CASE(test_TSIG_different_case_name) { + DNSName tsigName("tsig.Name"); + DNSName tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT"); + DNSName qname("test.valid.tsig"); + string tsigSecret("verysecret"); + + vector<uint8_t> packet = generateTSIGQuery(qname, tsigName, tsigAlgo, tsigSecret); + + checkTSIG(tsigName.makeLowerCase(), tsigAlgo.makeLowerCase(), tsigSecret, packet); +} + BOOST_AUTO_TEST_CASE(test_TSIG_different_name_same_algo) { DNSName tsigName("tsig.name"); DNSName tsigAlgo("HMAC-MD5.SIG-ALG.REG.INT");