]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Give backends the ability to perform extra actions during zone rectify. 15894/head
authorMiod Vallat <miod.vallat@powerdns.com>
Wed, 23 Jul 2025 12:26:09 +0000 (14:26 +0200)
committerMiod Vallat <miod.vallat@powerdns.com>
Thu, 31 Jul 2025 10:30:27 +0000 (12:30 +0200)
Use this is the LMDB backend to purge possibly orphaned (dangling) NSEC3
records created by 4.x servers.

Signed-off-by: Miod Vallat <miod.vallat@powerdns.com>
modules/lmdbbackend/lmdbbackend.cc
modules/lmdbbackend/lmdbbackend.hh
pdns/dbdnsseckeeper.cc
pdns/dnsbackend.hh

index 7da2de0b0e871c4909f87c4859c626891d25254a..27120cd166b4c2104177b2aef2231f2079566bb9 100644 (file)
@@ -1107,7 +1107,7 @@ static std::shared_ptr<DNSRecordContent> 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<StringView>()) == 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:
index 3665533a0a9e99871aacf498b3f59f489bf6f28a..1f09850f1231063e6736c38491d1dc11844325cf 100644 (file)
@@ -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<uint32_t, uint32_t> getSchemaVersionAndShards(std::string& filename);
   static bool upgradeToSchemav5(std::string& filename);
@@ -335,7 +337,7 @@ private:
   std::shared_ptr<RecordsROTransaction> getRecordsROTransaction(domainid_t id, const std::shared_ptr<LMDBBackend::RecordsRWTransaction>& rwtxn = nullptr);
   bool genChangeDomain(const ZoneName& domain, const std::function<void(DomainInfo&)>& func);
   bool genChangeDomain(domainid_t id, const std::function<void(DomainInfo&)>& 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<DomainInfo>* domains, const std::function<bool(DomainInfo&)>& allow);
 
index 5c9d1f806305553e7dca3fa8cb3e7293bc8d42aa..376c9a9493d476d963f7bcc2af178e72737846bb 100644 (file)
@@ -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();
 
index f87391e63cdb4ca31e4681a49a4c8559b0e8ee14..6807461cd7fb10f713f67be9fd44bdb661abe564 100644 (file)
@@ -513,6 +513,10 @@ public:
     return false;
   }
 
+  virtual void rectifyZoneHook(domainid_t /*domain_id*/, bool /*before*/) const
+  {
+  }
+
   const string& getPrefix() { return d_prefix; };
 
 protected: