From: Miod Vallat Date: Mon, 31 Mar 2025 14:08:40 +0000 (+0200) Subject: Allow backends to report a coarse-grained capabilities mask. X-Git-Tag: dnsdist-2.0.0-alpha2~96^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5fa7f3563af83689dc69c53d47912df6789f50aa;p=thirdparty%2Fpdns.git Allow backends to report a coarse-grained capabilities mask. The current capabilities are DNSSEC supports, comments, direct backend commands, and zone listing (AXFR) ability. doesDNSSEC() is rewritten as a trivial wrapper around this. --- diff --git a/docs/appendices/backend-writers-guide.rst b/docs/appendices/backend-writers-guide.rst index d67a2ac4a9..7fd50f2a25 100644 --- a/docs/appendices/backend-writers-guide.rst +++ b/docs/appendices/backend-writers-guide.rst @@ -66,14 +66,14 @@ following methods are relevant: class DNSBackend { public: - + virtual unsigned int getCapabilities()=0; virtual void lookup(const QType &qtype, const string &qdomain, int zoneId=-1, DNSPacket *pkt_p=nullptr)=0; virtual bool list(const string &target, int domain_id)=0; virtual bool get(DNSResourceRecord &r)=0; virtual bool getSOA(const string &name, SOAData &soadata); }; -Note that the first three methods must be implemented. ``getSOA()`` has +Note that the first four methods must be implemented. ``getSOA()`` has a useful default implementation. The semantics are simple. Each instance of your class only handles one @@ -162,9 +162,11 @@ furthermore, only about its A record: class RandomBackend : public DNSBackend { public: + unsigned int getCapabilities() override { return 0; } + bool list(const string &target, int id) { - return false; // we don't support AXFR + return false; // we don't support pdnsutil list-zone or AXFR } void lookup(const QType &type, const string &qdomain, int zoneId, DNSPacket *p) @@ -234,7 +236,7 @@ and such. as 'overlay', makes the zone incompatible with some operations that assume that a single zone is always entirely stored in the same backend. Such operations include zone transfers, listing and editing zone content via - the API or :doc:`pdnsutil `. + the API or :doc:`pdnsutil <../manpages/pdnsutil.1>`. .. warning:: When the content of a zone is spread across multiple backends, all the types @@ -345,6 +347,14 @@ Classes Methods ~~~~~~~ +.. cpp:function:: unsigned int getCapabilities() + + This function returns a bitmask representing various capabilities of + the backend. The currently used capabilities are: + +* `CAP_DNSSEC` Backend implements :ref:`backend-dnssec`. +* `CAP_LIST` Backend implements `list`, for AXFR or `pdnsutil list-zone` + .. cpp:function:: void DNSBackend::lookup(const QType &qtype, const string &qdomain, int zoneId=-1, DNSPacket *pkt=nullptr) This function is used to initiate a straight lookup for a record of name @@ -855,6 +865,8 @@ In order for a backend to support the storage of TSIG keys, the following operat /* ... */ } +.. _backend-dnssec: + DNSSEC support -------------- @@ -872,8 +884,9 @@ In order for a backend to support DNSSEC, quite a few number of additional opera class DNSBackend { public: + virtual unsigned int getCapabilities(); + /* ... */ - virtual bool doesDNSSEC(); virtual bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after); /* update operations */ @@ -894,9 +907,8 @@ In order for a backend to support DNSSEC, quite a few number of additional opera /* ... */ } -.. cpp:function:: virtual bool doesDNSSEC() - - Returns true if that backend supports DNSSEC. +In addition to these methods, the return value of `getCapabilities` must +contain `CAP_DNSSEC` if that backend supports DNSSEC. .. cpp:function:: virtual bool getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) diff --git a/modules/bindbackend/bindbackend2.hh b/modules/bindbackend/bindbackend2.hh index 118151d669..9fee224004 100644 --- a/modules/bindbackend/bindbackend2.hh +++ b/modules/bindbackend/bindbackend2.hh @@ -181,6 +181,7 @@ class Bind2Backend : public DNSBackend public: Bind2Backend(const string& suffix = "", bool loadZones = true); ~Bind2Backend() override; + unsigned int getCapabilities() override; void getUnfreshSecondaryInfos(vector* unfreshDomains) override; void getUpdatedPrimaries(vector& changedDomains, std::unordered_set& catalogs, CatalogHashMap& catalogHashes) override; bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial = true) override; @@ -220,7 +221,6 @@ public: bool setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) override; bool deleteTSIGKey(const DNSName& name) override; bool getTSIGKeys(std::vector& keys) override; - bool doesDNSSEC() override; // end of DNSSEC typedef multi_index_container* domains, bool getSerial, bool include_disabled) override; // dnssec support - bool doesDNSSEC() override { return d_dnssec; }; bool getAllDomainMetadata(const DNSName& name, std::map>& meta) override; bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector& meta) override; bool getDomainKeys(const DNSName& name, std::vector& keys) override; diff --git a/modules/ldapbackend/ldapbackend.hh b/modules/ldapbackend/ldapbackend.hh index 830cae7c7e..77cab28fc2 100644 --- a/modules/ldapbackend/ldapbackend.hh +++ b/modules/ldapbackend/ldapbackend.hh @@ -170,6 +170,7 @@ public: ~LdapBackend() override; // Native backend + unsigned int getCapabilities() override { return CAP_LIST; } bool list(const DNSName& target, int domain_id, bool include_disabled = false) override; void lookup(const QType& qtype, const DNSName& qdomain, int zoneid, DNSPacket* p = nullptr) override; bool get(DNSResourceRecord& rr) override; diff --git a/modules/lmdbbackend/lmdbbackend.hh b/modules/lmdbbackend/lmdbbackend.hh index 523f248711..40c046b32a 100644 --- a/modules/lmdbbackend/lmdbbackend.hh +++ b/modules/lmdbbackend/lmdbbackend.hh @@ -62,6 +62,7 @@ public: explicit LMDBBackend(const string& suffix = ""); ~LMDBBackend(); + unsigned int getCapabilities() override { return CAP_DNSSEC | CAP_DIRECT | CAP_LIST; } bool list(const DNSName& target, int id, bool include_disabled) override; bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getserial = true) override; @@ -143,11 +144,6 @@ public: bool updateEmptyNonTerminals(uint32_t domain_id, set& insert, set& erase, bool remove) override; - bool doesDNSSEC() override - { - return true; - } - // other string directBackendCmd(const string& query) override; diff --git a/modules/lua2backend/lua2api2.hh b/modules/lua2backend/lua2api2.hh index ba744da99a..0272768903 100644 --- a/modules/lua2backend/lua2api2.hh +++ b/modules/lua2backend/lua2api2.hh @@ -129,9 +129,14 @@ public: } } - bool doesDNSSEC() override + unsigned int getCapabilities() override { - return d_dnssec; + if (d_dnssec) { + return CAP_DNSSEC | CAP_DIRECT | CAP_LIST; + } + else { + return CAP_DIRECT | CAP_LIST; + } } void parseLookup(const lookup_result_t& result) diff --git a/modules/pipebackend/pipebackend.hh b/modules/pipebackend/pipebackend.hh index 776533a5a2..64b4b3477e 100644 --- a/modules/pipebackend/pipebackend.hh +++ b/modules/pipebackend/pipebackend.hh @@ -50,6 +50,8 @@ class PipeBackend : public DNSBackend public: PipeBackend(const string& suffix = ""); ~PipeBackend() override; + + unsigned int getCapabilities() override { return CAP_DIRECT | CAP_LIST; } void lookup(const QType&, const DNSName& qdomain, int zoneId, DNSPacket* p = nullptr) override; bool list(const DNSName& target, int domain_id, bool include_disabled = false) override; bool get(DNSResourceRecord& r) override; diff --git a/modules/remotebackend/remotebackend.cc b/modules/remotebackend/remotebackend.cc index d4d68c97bf..1639c237d8 100644 --- a/modules/remotebackend/remotebackend.cc +++ b/modules/remotebackend/remotebackend.cc @@ -506,9 +506,12 @@ bool RemoteBackend::unpublishDomainKey(const DNSName& name, unsigned int id) return this->send(query) && this->recv(answer); } -bool RemoteBackend::doesDNSSEC() +unsigned int RemoteBackend::getCapabilities() { - return d_dnssec; + if (d_dnssec) { + return CAP_DNSSEC | CAP_DIRECT | CAP_LIST; + } + return CAP_DIRECT | CAP_LIST; } bool RemoteBackend::getTSIGKey(const DNSName& name, DNSName& algorithm, std::string& content) diff --git a/modules/remotebackend/remotebackend.hh b/modules/remotebackend/remotebackend.hh index 69c80b1020..0949150872 100644 --- a/modules/remotebackend/remotebackend.hh +++ b/modules/remotebackend/remotebackend.hh @@ -167,6 +167,7 @@ public: RemoteBackend(const std::string& suffix = ""); ~RemoteBackend() override; + unsigned int getCapabilities() override; void lookup(const QType& qtype, const DNSName& qdomain, int zoneId = -1, DNSPacket* pkt_p = nullptr) override; bool get(DNSResourceRecord& rr) override; bool list(const DNSName& target, int domain_id, bool include_disabled = false) override; @@ -185,7 +186,6 @@ public: bool unpublishDomainKey(const DNSName& name, unsigned int id) override; bool getDomainInfo(const DNSName& domain, DomainInfo& di, bool getSerial = true) override; void setNotified(uint32_t id, uint32_t serial) override; - bool doesDNSSEC() override; bool autoPrimaryBackend(const string& ip, const DNSName& domain, const vector& nsset, string* nameserver, string* account, DNSBackend** ddb) override; bool createSecondaryDomain(const string& ip, const DNSName& domain, const string& nameserver, const string& account) override; bool replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector& rrset) override; diff --git a/modules/tinydnsbackend/tinydnsbackend.hh b/modules/tinydnsbackend/tinydnsbackend.hh index 26bce0784f..d227f51bd5 100644 --- a/modules/tinydnsbackend/tinydnsbackend.hh +++ b/modules/tinydnsbackend/tinydnsbackend.hh @@ -67,6 +67,8 @@ class TinyDNSBackend : public DNSBackend public: // Methods for simple operation TinyDNSBackend(const string& suffix); + + unsigned int getCapabilities() override { return CAP_LIST; } void lookup(const QType& qtype, const DNSName& qdomain, int zoneId, DNSPacket* pkt_p = nullptr) override; bool list(const DNSName& target, int domain_id, bool include_disabled = false) override; bool get(DNSResourceRecord& rr) override; diff --git a/pdns/backends/gsql/gsqlbackend.cc b/pdns/backends/gsql/gsqlbackend.cc index 80668e61c5..d943cf7c4a 100644 --- a/pdns/backends/gsql/gsqlbackend.cc +++ b/pdns/backends/gsql/gsqlbackend.cc @@ -866,9 +866,12 @@ bool GSQLBackend::updateEmptyNonTerminals(uint32_t domain_id, set& inse return true; } -bool GSQLBackend::doesDNSSEC() +unsigned int GSQLBackend::getCapabilities() { - return d_dnssecQueries; + if (d_dnssecQueries) { + return CAP_DNSSEC | CAP_COMMENTS | CAP_DIRECT | CAP_LIST; + } + return CAP_COMMENTS | CAP_DIRECT | CAP_LIST; } bool GSQLBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) diff --git a/pdns/backends/gsql/gsqlbackend.hh b/pdns/backends/gsql/gsqlbackend.hh index e54e5b2a3b..f0633d4da0 100644 --- a/pdns/backends/gsql/gsqlbackend.hh +++ b/pdns/backends/gsql/gsqlbackend.hh @@ -194,6 +194,7 @@ protected: } public: + unsigned int getCapabilities() override; void lookup(const QType &, const DNSName &qdomain, int zoneId, DNSPacket *p=nullptr) override; bool list(const DNSName &target, int domain_id, bool include_disabled=false) override; bool get(DNSResourceRecord &r) override; @@ -228,7 +229,6 @@ public: bool updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName& qname, const DNSName& ordername, bool auth, const uint16_t=QType::ANY) override; bool updateEmptyNonTerminals(uint32_t domain_id, set& insert ,set& erase, bool remove) override; - bool doesDNSSEC() override; bool replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector& rrset) override; bool listSubZone(const DNSName &zone, int domain_id) override; diff --git a/pdns/dnsbackend.hh b/pdns/dnsbackend.hh index 496b80ec58..ed7b0c491e 100644 --- a/pdns/dnsbackend.hh +++ b/pdns/dnsbackend.hh @@ -156,6 +156,16 @@ class DNSPacket; class DNSBackend { public: + enum Capabilities : unsigned int + { + CAP_DNSSEC = 1 << 0, // Backend supports DNSSEC + CAP_COMMENTS = 1 << 1, // Backend supports comments + CAP_DIRECT = 1 << 2, // Backend supports direct commands + CAP_LIST = 1 << 3, // Backend supports record enumeration + }; + + virtual unsigned int getCapabilities() = 0; + //! lookup() initiates a lookup. A lookup without results should not throw! virtual void lookup(const QType& qtype, const DNSName& qdomain, int zoneId = -1, DNSPacket* pkt_p = nullptr) = 0; virtual bool get(DNSResourceRecord&) = 0; //!< retrieves one DNSResource record, returns false if no more were available @@ -255,9 +265,9 @@ public: return false; } - virtual bool doesDNSSEC() + bool doesDNSSEC() { - return false; + return (getCapabilities() & CAP_DNSSEC) != 0; } // end DNSSEC diff --git a/pdns/test-ueberbackend_cc.cc b/pdns/test-ueberbackend_cc.cc index 5fc7d0d48a..2627e58f30 100644 --- a/pdns/test-ueberbackend_cc.cc +++ b/pdns/test-ueberbackend_cc.cc @@ -107,6 +107,8 @@ public: { } + unsigned int getCapabilities() override { return CAP_LIST; } + bool findZone(const DNSName& qdomain, int zoneId, std::shared_ptr& records, uint64_t& currentZoneId) const { currentZoneId = -1;