From be43b2e70193b13c01a268381b654dce8b6cc7ec Mon Sep 17 00:00:00 2001 From: Miod Vallat Date: Wed, 23 Jul 2025 14:26:09 +0200 Subject: [PATCH] Give backends the ability to perform extra actions during zone rectify. Use this is the LMDB backend to purge possibly orphaned (dangling) NSEC3 records created by 4.x servers. Signed-off-by: Miod Vallat --- modules/lmdbbackend/lmdbbackend.cc | 25 +++++++++++++++++++++++-- modules/lmdbbackend/lmdbbackend.hh | 4 +++- pdns/dbdnsseckeeper.cc | 4 ++++ pdns/dnsbackend.hh | 4 ++++ 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/modules/lmdbbackend/lmdbbackend.cc b/modules/lmdbbackend/lmdbbackend.cc index 7da2de0b0..27120cd16 100644 --- a/modules/lmdbbackend/lmdbbackend.cc +++ b/modules/lmdbbackend/lmdbbackend.cc @@ -1107,7 +1107,7 @@ static std::shared_ptr deserializeContentZR(uint16_t qtype, co #define StringView string #endif -void LMDBBackend::deleteDomainRecords(RecordsRWTransaction& txn, const std::string& match) +void LMDBBackend::deleteDomainRecords(RecordsRWTransaction& txn, const std::string& match, QType qtype) { auto cursor = txn.txn->getCursor(txn.db->dbi); MDBOutVal key{}; @@ -1115,7 +1115,9 @@ void LMDBBackend::deleteDomainRecords(RecordsRWTransaction& txn, const std::stri if (cursor.prefix(match, key, val) == 0) { do { - cursor.del(key); + if (qtype == QType::ANY || compoundOrdername::getQType(key.getNoStripHeader()) == qtype) { + cursor.del(key); + } } while (cursor.next(key, val) == 0); } } @@ -3180,6 +3182,25 @@ bool LMDBBackend::hasCreatedLocalFiles() const return MDBDbi::d_creationCount != 0; } +// Hook for rectifyZone operation. +// Before the operation starts, we forcibly remove all NSEC3 records from the +// domain, since logic flaws in older versions may have left us with dangling +// records. The appropriate records will be regenerated with +// updateDNSSECOrderNameAndAuth() calls anyway. +void LMDBBackend::rectifyZoneHook(domainid_t domain_id, bool before) const +{ + if (!before) { + return; + } + + if (!d_rwtxn) { + throw DBException("rectifyZoneHook invoked outside of a transaction"); + } + + compoundOrdername order; + LMDBBackend::deleteDomainRecords(*d_rwtxn, order(domain_id), QType::NSEC3); +} + class LMDBFactory : public BackendFactory { public: diff --git a/modules/lmdbbackend/lmdbbackend.hh b/modules/lmdbbackend/lmdbbackend.hh index 3665533a0..1f09850f1 100644 --- a/modules/lmdbbackend/lmdbbackend.hh +++ b/modules/lmdbbackend/lmdbbackend.hh @@ -171,6 +171,8 @@ public: bool hasCreatedLocalFiles() const override; + void rectifyZoneHook(domainid_t domain_id, bool before) const override; + // functions to use without constructing a backend object static std::pair getSchemaVersionAndShards(std::string& filename); static bool upgradeToSchemav5(std::string& filename); @@ -335,7 +337,7 @@ private: std::shared_ptr getRecordsROTransaction(domainid_t id, const std::shared_ptr& rwtxn = nullptr); bool genChangeDomain(const ZoneName& domain, const std::function& func); bool genChangeDomain(domainid_t id, const std::function& func); - static void deleteDomainRecords(RecordsRWTransaction& txn, const std::string& match); + static void deleteDomainRecords(RecordsRWTransaction& txn, const std::string& match, QType qtype = QType::ANY); void getAllDomainsFiltered(vector* domains, const std::function& allow); diff --git a/pdns/dbdnsseckeeper.cc b/pdns/dbdnsseckeeper.cc index 5c9d1f806..376c9a949 100644 --- a/pdns/dbdnsseckeeper.cc +++ b/pdns/dbdnsseckeeper.cc @@ -847,6 +847,8 @@ bool DNSSECKeeper::rectifyZone(const ZoneName& zone, string& error, string& info if (doTransaction) sd.db->startTransaction(zone, UnknownDomainID); + sd.db->rectifyZoneHook(sd.domain_id, true); + bool realrr=true; bool doent=true; int updates=0; @@ -959,6 +961,8 @@ bool DNSSECKeeper::rectifyZone(const ZoneName& zone, string& error, string& info } } + sd.db->rectifyZoneHook(sd.domain_id, false); + if (doTransaction) sd.db->commitTransaction(); diff --git a/pdns/dnsbackend.hh b/pdns/dnsbackend.hh index f87391e63..6807461cd 100644 --- a/pdns/dnsbackend.hh +++ b/pdns/dnsbackend.hh @@ -513,6 +513,10 @@ public: return false; } + virtual void rectifyZoneHook(domainid_t /*domain_id*/, bool /*before*/) const + { + } + const string& getPrefix() { return d_prefix; }; protected: -- 2.47.2