From: Miod Vallat Date: Mon, 21 Jul 2025 14:47:36 +0000 (+0200) Subject: Add a "list" backend-cmd which allows us to get NSEC3 ordername data. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d675c92086a59e25527d329f9bced9c1ab7d0e8c;p=thirdparty%2Fpdns.git Add a "list" backend-cmd which allows us to get NSEC3 ordername data. Signed-off-by: Miod Vallat --- diff --git a/modules/lmdbbackend/lmdbbackend.cc b/modules/lmdbbackend/lmdbbackend.cc index a65bf8c02..2ee47ce97 100644 --- a/modules/lmdbbackend/lmdbbackend.cc +++ b/modules/lmdbbackend/lmdbbackend.cc @@ -1854,24 +1854,32 @@ void LMDBBackend::lookupStart(domainid_t domain_id, const std::string& match, bo } } -bool LMDBBackend::get(DNSZoneRecord& zr) +bool LMDBBackend::getInternal(DNSName& basename, std::string_view& key) { for (;;) { + if (!d_currentrrset.empty()) { + if (++d_currentrrsetpos >= d_currentrrset.size()) { + d_currentrrset.clear(); // will invalidate lrr + if (d_getcursor && d_getcursor->next(d_currentKey, d_currentVal) != 0) { + // cerr<<"resetting d_getcursor 2"<(); } try { - const auto& lrr = d_currentrrset.at(d_currentrrsetpos++); - DNSName basename; + const auto& lrr = d_currentrrset.at(d_currentrrsetpos); bool validRecord = d_includedisabled || !lrr.disabled; if (validRecord) { @@ -1899,24 +1906,6 @@ bool LMDBBackend::get(DNSZoneRecord& zr) } } - 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()) { - d_currentrrset.clear(); // will invalidate lrr - if (d_getcursor->next(d_currentKey, d_currentVal) != 0) { - // cerr<<"resetting d_getcursor 2"<& argv) +{ + ostringstream ret; + + if (argv.size() < 2) { + ret << "need a domain name" << endl; + return ret.str(); + } + ZoneName zone(argv[1]); + + DomainInfo info; + if (!getDomainInfo(zone, info, false)) { + ret << "zone " << zone << " not found" << endl; + return ret.str(); + } + list(zone, info.id, true); + { + DNSName basename; + std::string_view key; + while (getInternal(basename, key)) { + const auto& lrr = d_currentrrset.at(d_currentrrsetpos); + DNSName qname = basename + d_lookupdomain.operator const DNSName&(); + QType qtype = compoundOrdername::getQType(key); + DNSRecord record; + record.setContent(deserializeContentZR(qtype, qname, lrr.content)); + std::string content = record.getContent()->getZoneRepresentation(true); + // Mimic the `prio' field in SQL + int prio{0}; + if (qtype == QType::MX || qtype == QType::SRV) { + if (auto pos = content.find_first_not_of("0123456789"); pos != std::string::npos) { + pdns::checked_stoi_into(prio, content.substr(0, pos)); + content.erase(0, pos); + boost::trim_left(content); + } + } + ret << qname << "\t" << qtype.toString() << "\t" << prio << "\t" << content << "\t" << lrr.ttl; + if (lrr.hasOrderName) { + ret << "\t'"; + // The get() logic skips the NSEC3 records containing the information + // we need, and there is no way to nest lookups. But the NSEC3 + // record has a unique key we can compute, so we can fetch it + // without disturbing the current get() cursor. + compoundOrdername order; + MDBOutVal val{}; + if (d_rotxn->txn->get(d_rotxn->db->dbi, order(info.id, basename, QType::NSEC3), val) == 0) { + LMDBResourceRecord nsec3rr; + deserializeFromBuffer(val.get(), nsec3rr); + DNSName ordername(nsec3rr.content.c_str(), nsec3rr.content.size(), 0, false); + ret << ordername; + } + ret << "'\t"; + ret << static_cast(lrr.auth); + } + ret << std::endl; + } + } + return ret.str(); +} + bool LMDBBackend::hasCreatedLocalFiles() const { // Since the lmdb file creation counter is global, if multiple LMDB backends diff --git a/modules/lmdbbackend/lmdbbackend.hh b/modules/lmdbbackend/lmdbbackend.hh index 95841e9d9..c3859ecfb 100644 --- a/modules/lmdbbackend/lmdbbackend.hh +++ b/modules/lmdbbackend/lmdbbackend.hh @@ -344,6 +344,7 @@ private: void lookupStart(domainid_t domain_id, const std::string& match, bool dolog); void lookupInternal(const QType& type, const DNSName& qdomain, domainid_t zoneId, DNSPacket* p, bool include_disabled); bool getSerial(DomainInfo& di); + bool getInternal(DNSName& basename, std::string_view& key); static bool getAfterForward(MDBROCursor& cursor, MDBOutVal& key, MDBOutVal& val, domainid_t id, DNSName& after); static bool getAfterForwardFromStart(MDBROCursor& cursor, MDBOutVal& key, MDBOutVal& val, domainid_t id, DNSName& after); @@ -353,6 +354,8 @@ private: static void deleteNSEC3RecordPair(const std::shared_ptr& txn, domainid_t domain_id, const DNSName& qname); void writeNSEC3RecordPair(const std::shared_ptr& txn, domainid_t domain_id, const DNSName& qname, const DNSName& ordername); + string directBackendCmd_list(std::vector& argv); + ZoneName d_lookupdomain; DNSName d_lookupsubmatch; vector d_currentrrset;