From: Miod Vallat Date: Thu, 10 Jul 2025 07:12:47 +0000 (+0200) Subject: Implement listSubZone in LMDB backend. X-Git-Tag: rec-5.4.0-alpha0~34^2~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eb737948afb5705bf5ac1c6fadac5887eeaa8102;p=thirdparty%2Fpdns.git Implement listSubZone in LMDB backend. Signed-off-by: Miod Vallat --- diff --git a/modules/lmdbbackend/lmdbbackend.cc b/modules/lmdbbackend/lmdbbackend.cc index 0501902ab0..8dc749ed48 100644 --- a/modules/lmdbbackend/lmdbbackend.cc +++ b/modules/lmdbbackend/lmdbbackend.cc @@ -1722,6 +1722,7 @@ bool LMDBBackend::deleteDomain(const ZoneName& domain) * * d_lookupdomain: current domain being processed (appended to the * results' names) + * d_lookupsubmatch: relative name used for submatching (for listSubZone) * d_currentrrset: temporary vector of results (records found at the same * cursor, i.e. same qname but possibly different qtype) * d_currentrrsetpos: position in the above when returning its elements one @@ -1734,6 +1735,7 @@ bool LMDBBackend::deleteDomain(const ZoneName& domain) bool LMDBBackend::list(const ZoneName& target, domainid_t domain_id, bool include_disabled) { d_lookupdomain = target; + d_lookupsubmatch.clear(); d_includedisabled = include_disabled; compoundOrdername order; @@ -1743,6 +1745,33 @@ bool LMDBBackend::list(const ZoneName& target, domainid_t domain_id, bool includ return true; } +bool LMDBBackend::listSubZone(const ZoneName& target, domainid_t domain_id) +{ + // 1. from domain_id get base domain name + DomainInfo info; + if (!d_tdomains->getROTransaction().get(domain_id, info)) { + return false; + } + + // 2. make target relative to it + DNSName relqname = target.operator const DNSName&().makeRelative(info.zone); + if (relqname.empty()) { + return false; + } + + // 3. enumerate complete domain, but tell get() to ignore entries which are + // not subsets of target + d_lookupdomain = std::move(info.zone); + d_lookupsubmatch = std::move(relqname); + d_includedisabled = true; + + compoundOrdername order; + std::string match = order(domain_id); + + lookupStart(domain_id, match, false); + return true; +} + void LMDBBackend::lookupInternal(const QType& type, const DNSName& qdomain, domainid_t zoneId, DNSPacket* /* p */, bool include_disabled) { if (d_dolog) { @@ -1780,6 +1809,7 @@ void LMDBBackend::lookupInternal(const QType& type, const DNSName& qdomain, doma // cout<<"get will look for "<prefix(match, key, val) != 0) { d_getcursor.reset(); // will cause get() to fail if (dolog) { @@ -1852,15 +1883,24 @@ bool LMDBBackend::get(DNSZoneRecord& zr) } try { const auto& lrr = d_currentrrset.at(d_currentrrsetpos++); + DNSName basename; + bool validRecord = d_includedisabled || !lrr.disabled; + + if (validRecord) { + basename = compoundOrdername::getQName(key); + if (!d_lookupsubmatch.empty()) { + validRecord = basename.isPartOf(d_lookupsubmatch); + } + } - zr.disabled = lrr.disabled; - if (!zr.disabled || d_includedisabled) { - zr.dr.d_name = compoundOrdername::getQName(key) + d_lookupdomain.operator const DNSName&(); + if (validRecord) { + zr.dr.d_name = basename + d_lookupdomain.operator const DNSName&(); zr.domain_id = compoundOrdername::getDomainID(key); zr.dr.d_type = compoundOrdername::getQType(key).getCode(); zr.dr.d_ttl = lrr.ttl; zr.dr.setContent(deserializeContentZR(zr.dr.d_type, zr.dr.d_name, lrr.content)); zr.auth = lrr.auth; + zr.disabled = lrr.disabled; } if (d_currentrrsetpos >= d_currentrrset.size()) { @@ -1871,7 +1911,7 @@ bool LMDBBackend::get(DNSZoneRecord& zr) } } - if (zr.disabled && !d_includedisabled) { + if (!validRecord) { continue; } } diff --git a/modules/lmdbbackend/lmdbbackend.hh b/modules/lmdbbackend/lmdbbackend.hh index 94c535d96d..86b1cc9670 100644 --- a/modules/lmdbbackend/lmdbbackend.hh +++ b/modules/lmdbbackend/lmdbbackend.hh @@ -75,6 +75,7 @@ public: unsigned int getCapabilities() override; bool list(const ZoneName& target, domainid_t domain_id, bool include_disabled) override; + bool listSubZone(const ZoneName& target, domainid_t domain_id) override; bool getDomainInfo(const ZoneName& domain, DomainInfo& info, bool getserial = true) override; bool createDomain(const ZoneName& domain, const DomainInfo::DomainKind kind, const vector& primaries, const string& account) override; @@ -350,6 +351,7 @@ private: void writeNSEC3RecordPair(const std::shared_ptr& txn, domainid_t domain_id, const DNSName& qname, const DNSName& ordername); ZoneName d_lookupdomain; + DNSName d_lookupsubmatch; vector d_currentrrset; size_t d_currentrrsetpos; MDBOutVal d_currentKey;