From 02dac74beb5f63b4e5008d724dbd7eca59647659 Mon Sep 17 00:00:00 2001 From: Fred Morcos Date: Wed, 3 Jul 2024 11:50:24 +0200 Subject: [PATCH 1/4] Rework the QType class This adds QType::fromString() which does error checking and throws exceptions when invalid input is provided. Cleans up the anti-pattern that was previously there where you could only construct a QType object from a string by assigning to a dummy one. Also removes access to internals like chartocode which was being used all around in place of that anti-pattern. --- pdns/qtype.cc | 96 ++++++++++++++++++------------------ pdns/qtype.hh | 132 ++++++++++++++++++++++++++++---------------------- 2 files changed, 122 insertions(+), 106 deletions(-) diff --git a/pdns/qtype.cc b/pdns/qtype.cc index a0d5732cd10e..283633638467 100644 --- a/pdns/qtype.cc +++ b/pdns/qtype.cc @@ -19,12 +19,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "dns.hh" -#include + +#include +#include #include -#include #include -#include #include "qtype.hh" #include "misc.hh" @@ -100,73 +99,76 @@ const map QType::names = { #endif }; -static map swapElements(const map& names) { - map ret; - - for (const auto& n : names) { - ret.emplace(n.second, n.first); - } - return ret; -} - -const map QType::numbers = swapElements(names); - - -bool QType::isSupportedType() const +static auto parsingError(const string& name) -> std::runtime_error { - return numbers.count(code) == 1; + string fullErrorMessage{"Unknown or invalid record type `"}; + fullErrorMessage += name; + fullErrorMessage += "`"; + return std::runtime_error{fullErrorMessage}; } -bool QType::isMetadataType() const +static auto invalidEmptyRecordType() -> std::runtime_error { - // rfc6895 section 3.1, note ANY is 255 and falls outside the range - if (code == QType::OPT || (code >= rfc6895MetaLowerBound && code <= rfc6895MetaUpperBound)) { - return true; - } - return false; + string fullErrorMessage{"Invalid empty record type"}; + return std::runtime_error{fullErrorMessage}; } -const string QType::toString() const +auto QType::fromString(const string& name) -> QType { - const auto& name = numbers.find(code); - if (name != numbers.cend()) { - return name->second; + if (name.empty()) { + throw invalidEmptyRecordType(); } - return "TYPE" + std::to_string(code); -} -uint16_t QType::chartocode(const char *p) -{ - string P = toUpper(p); + const auto& upperName = toUpper(name); - const auto& num = names.find(P); + const auto& num = names.find(upperName); if (num != names.cend()) { return num->second; } - if (*p == '#') { - return static_cast(atoi(p + 1)); + + if (name.at(0) == '#') { + return pdns::checked_stoi(&name[1]); } - if (boost::starts_with(P, "TYPE")) { - return static_cast(atoi(p + 4)); + if (boost::starts_with(upperName, "TYPE")) { + return pdns::checked_stoi(&name[4]); } - return 0; + throw parsingError(name); +} + +string QType::toString() const +{ + const auto& name = numbers.find(qtype); + if (name != numbers.cend()) { + return name->second; + } + return "TYPE" + std::to_string(qtype); +} + +static map swapElements(const map& names) +{ + map ret; + for (const auto& name : names) { + ret.emplace(name.second, name.first); + } + return ret; } -QType &QType::operator=(const char *p) +const map QType::numbers = swapElements(names); + +bool QType::isSupportedType() const { - code = chartocode(p); - return *this; + return numbers.count(qtype) == 1; } -QType &QType::operator=(const string &s) +bool QType::isMetadataType() const { - code = chartocode(s.c_str()); - return *this; + // rfc6895 section 3.1, note ANY is 255 and falls outside the range + return qtype == QType::OPT || (qtype >= rfc6895MetaLowerBound && qtype <= rfc6895MetaUpperBound); } -const std::string QClass::toString() const +std::string QClass::toString() const { switch (qclass) { case IN: @@ -177,7 +179,7 @@ const std::string QClass::toString() const return "NONE"; case ANY: return "ANY"; - default : + default: return "CLASS" + std::to_string(qclass); } } diff --git a/pdns/qtype.hh b/pdns/qtype.hh index f5a879bef8f5..ea74fca57987 100644 --- a/pdns/qtype.hh +++ b/pdns/qtype.hh @@ -20,41 +20,47 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #pragma once -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif #include "namespaces.hh" +#include -/** The QType class is meant to deal easily with the different kind of resource types, like 'A', 'NS', - * 'CNAME' etcetera. These types have both a name and a number. This class can seamlessly move between - * them. Use it like this: +/** + * The QType class is meant to be used to easily deal with the different kinds of resource + * types like 'A', 'NS' and 'CNAME'. These types have both a name and a number. This class + * can seamlessly convert between them. Use it like this: \code - QType t; - t="CNAME"; - cout< QType; - operator uint16_t() const { - return code; + operator uint16_t() const + { + return qtype; } - const string toString() const; - uint16_t getCode() const + auto operator=(std::string& value) -> QType& { - return code; + *this = QType::fromString(value); + return *this; + } + + [[nodiscard]] string toString() const; + + [[nodiscard]] uint16_t getCode() const + { + return qtype; } /** @@ -63,31 +69,31 @@ public: * This does not presume that we have an implemented a content representation for this type, * for that please see DNSRecordContent::isRegisteredType(). */ - bool isSupportedType() const; + [[nodiscard]] bool isSupportedType() const; + /** * \brief Whether the type is either a QTYPE or Meta-Type as defined by rfc6895 section 3.1. * * Note that ANY is 255 and falls outside the range. */ - bool isMetadataType() const; + [[nodiscard]] bool isMetadataType() const; - static uint16_t chartocode(const char* p); - - enum typeenum : uint16_t { + enum QTypeEnum : uint16_t + { ENT = 0, - A = 1, - NS = 2, + A = 1, // NOLINT(readability-identifier-length) + NS = 2, // NOLINT(readability-identifier-length) CNAME = 5, SOA = 6, - MB = 7, - MG = 8, - MR = 9, + MB = 7, // NOLINT(readability-identifier-length) + MG = 8, // NOLINT(readability-identifier-length) + MR = 9, // NOLINT(readability-identifier-length) PTR = 12, HINFO = 13, MINFO = 14, - MX = 15, + MX = 15, // NOLINT(readability-identifier-length) TXT = 16, - RP = 17, + RP = 17, // NOLINT(readability-identifier-length) AFSDB = 18, SIG = 24, KEY = 25, @@ -95,13 +101,13 @@ public: LOC = 29, SRV = 33, NAPTR = 35, - KX = 36, + KX = 36, // NOLINT(readability-identifier-length) CERT = 37, - A6 = 38, + A6 = 38, // NOLINT(readability-identifier-length) DNAME = 39, OPT = 41, APL = 42, - DS = 43, + DS = 43, // NOLINT(readability-identifier-length) SSHFP = 44, IPSECKEY = 45, RRSIG = 46, @@ -124,7 +130,7 @@ public: NID = 104, L32 = 105, L64 = 106, - LP = 107, + LP = 107, // NOLINT(readability-identifier-length) EUI48 = 108, EUI64 = 109, TKEY = 249, @@ -140,29 +146,32 @@ public: ADDR = 65400, #if !defined(RECURSOR) ALIAS = 65401, - LUA = 65402 + LUA = 65402, #endif }; - const static uint16_t rfc6895MetaLowerBound = 128; - const static uint16_t rfc6895MetaUpperBound = 254; // Note 255: ANY is not included - const static uint16_t rfc6895Reserved = 65535; + static const uint16_t rfc6895MetaLowerBound = 128; + static const uint16_t rfc6895MetaUpperBound = 254; // Note 255: ANY is not included + static const uint16_t rfc6895Reserved = 65535; - const static map names; - const static map numbers; + static const map names; + static const map numbers; private: - - uint16_t code; + uint16_t qtype; }; // Define hash function on QType. See https://en.cppreference.com/w/cpp/utility/hash -namespace std { - template<> struct hash { - std::size_t operator()(QType qtype) const noexcept { - return std::hash{}(qtype.getCode()); - } - }; +namespace std +{ +template <> +struct hash +{ + std::size_t operator()(QType qtype) const noexcept + { + return std::hash{}(qtype.getCode()); + } +}; } inline std::ostream& operator<<(std::ostream& stream, const QType& qtype) @@ -171,24 +180,29 @@ inline std::ostream& operator<<(std::ostream& stream, const QType& qtype) } // Used by e.g. boost multi-index -inline size_t hash_value(const QType qtype) { +inline size_t hash_value(const QType qtype) +{ return qtype.getCode(); } struct QClass { - constexpr QClass(uint16_t code = 0) : qclass(code) {} + constexpr QClass(uint16_t code = 0) : + qclass(code) {} - constexpr operator uint16_t() const { + constexpr operator uint16_t() const + { return qclass; } - constexpr uint16_t getCode() const + + [[nodiscard]] constexpr uint16_t getCode() const { return qclass; } - const std::string toString() const; - static const QClass IN; + [[nodiscard]] std::string toString() const; + + static const QClass IN; // NOLINT(readability-identifier-length) static const QClass CHAOS; static const QClass NONE; static const QClass ANY; @@ -197,12 +211,12 @@ private: uint16_t qclass; }; -constexpr QClass QClass::IN(1); +constexpr QClass QClass::IN(1); // NOLINT(readability-identifier-length) constexpr QClass QClass::CHAOS(3); constexpr QClass QClass::NONE(254); constexpr QClass QClass::ANY(255); -inline std::ostream& operator<<(std::ostream& s, QClass qclass) +inline std::ostream& operator<<(std::ostream& stream, QClass qclass) { - return s << qclass.toString(); + return stream << qclass.toString(); } From 49414ecfb80f0bb8eb70b4273e31c371678b458e Mon Sep 17 00:00:00 2001 From: Fred Morcos Date: Wed, 3 Jul 2024 11:50:52 +0200 Subject: [PATCH 2/4] Auth: Adapt to QType class changes --- modules/bindbackend/bindbackend2.cc | 2 +- modules/geoipbackend/geoipbackend.cc | 2 +- modules/ldapbackend/ldapbackend.cc | 2 +- modules/lua2backend/lua2api2.hh | 2 +- modules/pipebackend/pipebackend.cc | 2 +- modules/remotebackend/remotebackend.cc | 4 ++-- pdns/backends/gsql/gsqlbackend.cc | 4 ++-- pdns/lua-auth4.cc | 4 ++-- pdns/lua-base4.cc | 6 +++--- pdns/pdnsutil.cc | 7 +++--- pdns/test-dnsrecords_cc.cc | 30 +++++++++++++------------- pdns/ws-auth.cc | 8 +++---- 12 files changed, 37 insertions(+), 36 deletions(-) diff --git a/modules/bindbackend/bindbackend2.cc b/modules/bindbackend/bindbackend2.cc index 3c9b5409d7d6..86e24e711942 100644 --- a/modules/bindbackend/bindbackend2.cc +++ b/modules/bindbackend/bindbackend2.cc @@ -869,7 +869,7 @@ void Bind2Backend::doEmptyNonTerminals(std::shared_ptr& records } DNSResourceRecord rr; - rr.qtype = "#0"; + rr.qtype = QType::fromString("#0"); rr.content = ""; rr.ttl = 0; for (auto& nt : nonterm) { diff --git a/modules/geoipbackend/geoipbackend.cc b/modules/geoipbackend/geoipbackend.cc index 7a87bf48f988..e25a0582faa1 100644 --- a/modules/geoipbackend/geoipbackend.cc +++ b/modules/geoipbackend/geoipbackend.cc @@ -237,7 +237,7 @@ bool GeoIPBackend::loadDomain(const YAML::Node& domain, std::uint32_t domainID, } else { string qtype = boost::to_upper_copy(rec->first.as()); - rr.qtype = qtype; + rr.qtype = QType::fromString(qtype); } rr.has_weight = false; rr.weight = 100; diff --git a/modules/ldapbackend/ldapbackend.cc b/modules/ldapbackend/ldapbackend.cc index c1e91b692f4d..ed08903f57e5 100644 --- a/modules/ldapbackend/ldapbackend.cc +++ b/modules/ldapbackend/ldapbackend.cc @@ -180,7 +180,7 @@ void LdapBackend::extract_entry_results(const DNSName& domain, const DNSResult& attrname = attribute.first; // extract qtype string from ldap attribute name by removing the 'Record' suffix. qstr = attrname.substr(0, attrname.length() - 6); - qt = toUpper(qstr); + qt = QType::fromString(qstr); for (const auto& value : attribute.second) { if (qtype != qt && qtype != QType::ANY) { diff --git a/modules/lua2backend/lua2api2.hh b/modules/lua2backend/lua2api2.hh index b2f298cfcec4..3054ed336e73 100644 --- a/modules/lua2backend/lua2api2.hh +++ b/modules/lua2backend/lua2api2.hh @@ -143,7 +143,7 @@ public: if (item.second.which() == 1) rec.qtype = QType(boost::get(item.second)); else if (item.second.which() == 3) - rec.qtype = boost::get(item.second); + rec.qtype = QType::fromString(boost::get(item.second)); else if (item.second.which() == 4) rec.qtype = boost::get(item.second); else diff --git a/modules/pipebackend/pipebackend.cc b/modules/pipebackend/pipebackend.cc index 68173dc3a43e..ddc7b4c31ea5 100644 --- a/modules/pipebackend/pipebackend.cc +++ b/modules/pipebackend/pipebackend.cc @@ -312,7 +312,7 @@ bool PipeBackend::get(DNSResourceRecord& r) r.auth = true; } r.qname = DNSName(parts[1 + extraFields]); - r.qtype = parts[3 + extraFields]; + r.qtype = QType::fromString(parts[3 + extraFields]); pdns::checked_stoi_into(r.ttl, parts[4 + extraFields]); pdns::checked_stoi_into(r.domain_id, parts[5 + extraFields]); diff --git a/modules/remotebackend/remotebackend.cc b/modules/remotebackend/remotebackend.cc index d4d68c97bf5b..745caa96171a 100644 --- a/modules/remotebackend/remotebackend.cc +++ b/modules/remotebackend/remotebackend.cc @@ -252,7 +252,7 @@ bool RemoteBackend::get(DNSResourceRecord& rr) return false; } - rr.qtype = stringFromJson(d_result["result"][d_index], "qtype"); + rr.qtype = QType::fromString(stringFromJson(d_result["result"][d_index], "qtype")); rr.qname = DNSName(stringFromJson(d_result["result"][d_index], "qname")); rr.qclass = QClass::IN; rr.content = stringFromJson(d_result["result"][d_index], "content"); @@ -853,7 +853,7 @@ bool RemoteBackend::searchRecords(const string& pattern, size_t maxResults, vect for (const auto& row : answer["result"].array_items()) { DNSResourceRecord rr; - rr.qtype = stringFromJson(row, "qtype"); + rr.qtype = QType::fromString(stringFromJson(row, "qtype")); rr.qname = DNSName(stringFromJson(row, "qname")); rr.qclass = QClass::IN; rr.content = stringFromJson(row, "content"); diff --git a/pdns/backends/gsql/gsqlbackend.cc b/pdns/backends/gsql/gsqlbackend.cc index 8ebb3c8acff7..e719619cd861 100644 --- a/pdns/backends/gsql/gsqlbackend.cc +++ b/pdns/backends/gsql/gsqlbackend.cc @@ -2283,7 +2283,7 @@ void GSQLBackend::extractRecord(SSqlStatement::row_t& row, DNSResourceRecord& r) else r.qname=DNSName(row[6]); - r.qtype=row[3]; + r.qtype = QType::fromString(row[3]); if (d_upgradeContent && DNSRecordContent::isUnknownType(row[3]) && DNSRecordContent::isRegisteredType(r.qtype, r.qclass)) { r.content = DNSRecordContent::upgradeContent(r.qname, r.qtype, row[0]); @@ -2324,7 +2324,7 @@ void GSQLBackend::extractComment(SSqlStatement::row_t& row, Comment& comment) { pdns::checked_stoi_into(comment.domain_id, row[0]); comment.qname = DNSName(row[1]); - comment.qtype = row[2]; + comment.qtype = QType::fromString(row[2]); pdns::checked_stoi_into(comment.modified_at, row[3]); comment.account = std::move(row[4]); comment.content = std::move(row[5]); diff --git a/pdns/lua-auth4.cc b/pdns/lua-auth4.cc index 77f7caa9035e..698558ecdb0a 100644 --- a/pdns/lua-auth4.cc +++ b/pdns/lua-auth4.cc @@ -55,7 +55,7 @@ void AuthLua4::postPrepareContext() { d_lw->registerFunction("clearRecords",[](DNSPacket &p){p.clearRecords();}); d_lw->registerFunction("addRecord", [](DNSPacket &p, DNSRecord &dr, bool auth) { DNSZoneRecord dzr; dzr.dr = dr; dzr.auth = auth; p.addRecord(std::move(dzr)); }); d_lw->registerFunction >&)>("addRecords", [](DNSPacket &p, const vector >& records){ for(const auto &dr: records){ DNSZoneRecord dzr; dzr.dr = std::get<1>(dr); dzr.auth = true; p.addRecord(std::move(dzr)); }}); - d_lw->registerFunction("setQuestion", [](DNSPacket &p, unsigned int opcode, const DNSName &name, const string &type){ QType qtype; qtype = type; p.setQuestion(static_cast(opcode), name, static_cast(qtype.getCode())); }); + d_lw->registerFunction("setQuestion", [](DNSPacket &packet, unsigned int opcode, const DNSName &name, const string &type){ QType qtype; qtype = QType::fromString(type); packet.setQuestion(static_cast(opcode), name, static_cast(qtype.getCode())); }); d_lw->registerFunction("isEmpty", [](DNSPacket &p){return p.isEmpty();}); d_lw->registerFunction()>("replyPacket",[](DNSPacket& p){ return p.replyPacket();}); d_lw->registerFunction("hasEDNSSubnet", [](DNSPacket &p){return p.hasEDNSSubnet();}); @@ -70,7 +70,7 @@ void AuthLua4::postPrepareContext() { d_lw->registerMember("qdomainzone", [](const DNSPacket &p) -> DNSName { return p.qdomainzone; }, [](DNSPacket &p, const DNSName& name) { p.qdomainzone = name; }); d_lw->registerMember("d_peer_principal", [](const DNSPacket &p) -> std::string { return p.d_peer_principal; }, [](DNSPacket &p, const std::string &princ) { p.d_peer_principal = princ; }); - d_lw->registerMember("qtype", [](const DNSPacket &p) -> const std::string { return p.qtype.toString(); }, [](DNSPacket &p, const std::string &type) { p.qtype = type; }); + d_lw->registerMember("qtype", [](const DNSPacket &packet) -> std::string { return packet.qtype.toString(); }, [](DNSPacket &packet, const std::string &type) { packet.qtype = QType::fromString(type); }); /* End of DNSPacket */ diff --git a/pdns/lua-base4.cc b/pdns/lua-base4.cc index 3984fe62e974..823e811f2b3b 100644 --- a/pdns/lua-base4.cc +++ b/pdns/lua-base4.cc @@ -82,7 +82,7 @@ void BaseLua4::prepareContext() { d_lw->writeFunction("newDRR", [](const DNSName& qname, const string& qtype, const unsigned int ttl, const string& content, boost::optional domain_id, boost::optional auth){ auto drr = DNSResourceRecord(); drr.qname = qname; - drr.qtype = qtype; + drr.qtype = QType::fromString(qtype); drr.ttl = ttl; drr.setContent(content); if (domain_id) @@ -177,7 +177,7 @@ void BaseLua4::prepareContext() { d_lw->registerFunction("check",[](const cas_t& cas, const ComboAddress&ca) { return cas.count(ca)>0; }); // QType - d_lw->writeFunction("newQType", [](const string& s) { QType q; q = s; return q; }); + d_lw->writeFunction("newQType", [](const string& newQType) { QType qType; qType = QType::fromString(newQType); return qType; }); d_lw->registerFunction("getCode", &QType::getCode); d_lw->registerFunction("getName", &QType::toString); d_lw->registerEqFunction([](const QType& a, const QType& b){ return a == b;}); // operator overloading confuses LuaContext @@ -216,7 +216,7 @@ void BaseLua4::prepareContext() { d_lw->registerFunction("match", (bool (NetmaskGroup::*)(const ComboAddress&) const)&NetmaskGroup::match); // DNSRecord - d_lw->writeFunction("newDR", [](const DNSName& name, const std::string& type, unsigned int ttl, const std::string& content, int place) { QType qtype; qtype = type; auto dr = DNSRecord(); dr.d_name = name; dr.d_type = qtype.getCode(); dr.d_ttl = ttl; dr.setContent(shared_ptr(DNSRecordContent::make(dr.d_type, QClass::IN, content))); dr.d_place = static_cast(place); return dr; }); + d_lw->writeFunction("newDR", [](const DNSName& name, const std::string& type, unsigned int ttl, const std::string& content, int place) { QType qtype; qtype = QType::fromString(type); auto dnsRecord = DNSRecord(); dnsRecord.d_name = name; dnsRecord.d_type = qtype.getCode(); dnsRecord.d_ttl = ttl; dnsRecord.setContent(shared_ptr(DNSRecordContent::make(dnsRecord.d_type, QClass::IN, content))); dnsRecord.d_place = static_cast(place); return dnsRecord; }); d_lw->registerMember("name", &DNSRecord::d_name); d_lw->registerMember("type", &DNSRecord::d_type); d_lw->registerMember("ttl", &DNSRecord::d_ttl); diff --git a/pdns/pdnsutil.cc b/pdns/pdnsutil.cc index aa890d9dc2b8..1056f3b2606e 100644 --- a/pdns/pdnsutil.cc +++ b/pdns/pdnsutil.cc @@ -1,4 +1,5 @@ #include "dnsrecords.hh" +#include "qtype.hh" #include #ifdef HAVE_CONFIG_H #include "config.h" @@ -1497,7 +1498,7 @@ static int createZone(const DNSName &zone, const DNSName& nsname) { rr.qname = zone; rr.auth = true; rr.ttl = ::arg().asNum("default-ttl"); - rr.qtype = "SOA"; + rr.qtype = QType::fromString("SOA"); string soa = ::arg()["default-soa-content"]; boost::replace_all(soa, "@", zone.toStringNoDot()); @@ -1735,9 +1736,9 @@ static int deleteRRSet(const std::string& zone_, const std::string& name_, const else name=DNSName(name_)+zone; - QType qt(QType::chartocode(type_.c_str())); + QType qType(QType::fromString(type_)); di.backend->startTransaction(zone, -1); - di.backend->replaceRRSet(di.id, name, qt, vector()); + di.backend->replaceRRSet(di.id, name, qType, vector()); di.backend->commitTransaction(); return EXIT_SUCCESS; } diff --git a/pdns/test-dnsrecords_cc.cc b/pdns/test-dnsrecords_cc.cc index c790b89a9134..284aaf007622 100644 --- a/pdns/test-dnsrecords_cc.cc +++ b/pdns/test-dnsrecords_cc.cc @@ -45,8 +45,8 @@ BOOST_AUTO_TEST_SUITE(test_dnsrecords_cc) BOOST_AUTO_TEST_CASE(test_record_types) { // tuple contains - typedef boost::tuple case_t; - typedef std::list cases_t; + using case_t = boost::tuple; + using cases_t = std::list; MRRecordContent::report(); IPSECKEYRecordContent::report(); KXRecordContent::report(); @@ -283,7 +283,7 @@ BOOST_AUTO_TEST_CASE(test_record_types) { (CASE_S(QType::CAA, "0 issue \"aaaaaaa\"", "\x00\x05\x69\x73\x73\x75\x65\x61\x61\x61\x61\x61\x61\x61")) (CASE_S(QType::CAA, "0 issue \"aaaaaaa.aaa\"", "\x00\x05\x69\x73\x73\x75\x65\x61\x61\x61\x61\x61\x61\x61\x2e\x61\x61\x61")) (CASE_S(QType::DLV, "20642 8 2 04443abe7e94c3985196beae5d548c727b044dda5151e60d7cd76a9fd931d00e", "\x50\xa2\x08\x02\x04\x44\x3a\xbe\x7e\x94\xc3\x98\x51\x96\xbe\xae\x5d\x54\x8c\x72\x7b\x04\x4d\xda\x51\x51\xe6\x0d\x7c\xd7\x6a\x9f\xd9\x31\xd0\x0e")) - (CASE_S((QType::typeenum)65226,"\\# 3 414243","\x41\x42\x43")) + (CASE_S((QType::QTypeEnum)65226,"\\# 3 414243","\x41\x42\x43")) ; @@ -349,8 +349,8 @@ BOOST_AUTO_TEST_CASE(test_record_types_bad_values) { enum class case_type_t { zone, wire }; // qtype, value, zone/wire format, broken - typedef boost::tuple case_t; - typedef std::list cases_t; + using case_t = boost::tuple; + using cases_t = std::list; #define ZONE_CASE(type, input) case_t(type, BINARY(input), case_type_t::zone, broken_marker::WORKING) #define WIRE_CASE(type, input) case_t(type, BINARY(input), case_type_t::wire, broken_marker::WORKING) @@ -471,27 +471,27 @@ BOOST_AUTO_TEST_CASE(test_opt_record_out) { // special record test, because Unknown record types are the worst BOOST_AUTO_TEST_CASE(test_unknown_records_in) { - auto validUnknown = DNSRecordContent::make(static_cast(65534), QClass::IN, "\\# 1 42"); + auto validUnknown = DNSRecordContent::make(static_cast(65534), QClass::IN, "\\# 1 42"); // we need at least two parts - BOOST_CHECK_THROW(auto notEnoughPartsUnknown = DNSRecordContent::make(static_cast(65534), QClass::IN, "\\#"), MOADNSException); + BOOST_CHECK_THROW(auto notEnoughPartsUnknown = DNSRecordContent::make(static_cast(65534), QClass::IN, "\\#"), MOADNSException); // two parts are OK when the RDATA size is 0, not OK otherwise - auto validEmptyUnknown = DNSRecordContent::make(static_cast(65534), QClass::IN, "\\# 0"); - BOOST_CHECK_THROW(auto twoPartsNotZeroUnknown = DNSRecordContent::make(static_cast(65534), QClass::IN, "\\# 1"), MOADNSException); + auto validEmptyUnknown = DNSRecordContent::make(static_cast(65534), QClass::IN, "\\# 0"); + BOOST_CHECK_THROW(auto twoPartsNotZeroUnknown = DNSRecordContent::make(static_cast(65534), QClass::IN, "\\# 1"), MOADNSException); // the first part has to be "\#" - BOOST_CHECK_THROW(auto invalidFirstPartUnknown = DNSRecordContent::make(static_cast(65534), QClass::IN, "\\$ 0"), MOADNSException); + BOOST_CHECK_THROW(auto invalidFirstPartUnknown = DNSRecordContent::make(static_cast(65534), QClass::IN, "\\$ 0"), MOADNSException); // RDATA length is not even - BOOST_CHECK_THROW(auto unevenUnknown = DNSRecordContent::make(static_cast(65534), QClass::IN, "\\# 1 A"), MOADNSException); + BOOST_CHECK_THROW(auto unevenUnknown = DNSRecordContent::make(static_cast(65534), QClass::IN, "\\# 1 A"), MOADNSException); // RDATA length is not equal to the expected size - BOOST_CHECK_THROW(auto wrongRDATASizeUnknown = DNSRecordContent::make(static_cast(65534), QClass::IN, "\\# 2 AA"), MOADNSException); + BOOST_CHECK_THROW(auto wrongRDATASizeUnknown = DNSRecordContent::make(static_cast(65534), QClass::IN, "\\# 2 AA"), MOADNSException); // RDATA is invalid (invalid hex value) try { - auto invalidRDATAUnknown = DNSRecordContent::make(static_cast(65534), QClass::IN, "\\# 1 JJ"); + auto invalidRDATAUnknown = DNSRecordContent::make(static_cast(65534), QClass::IN, "\\# 1 JJ"); // we should not reach that code BOOST_CHECK(false); // but if we do let's see what we got (likely what was left over on the stack) @@ -596,7 +596,7 @@ BOOST_AUTO_TEST_CASE(test_nsec_records_types) { auto nsecContent = std::dynamic_pointer_cast(validNSEC); BOOST_REQUIRE(nsecContent); - for (const auto type : { QType::A, QType::MX, QType::RRSIG, QType::NSEC, static_cast(1234) }) { + for (const auto type : { QType::A, QType::MX, QType::RRSIG, QType::NSEC, static_cast(1234) }) { BOOST_CHECK(nsecContent->isSet(type)); } BOOST_CHECK_EQUAL(nsecContent->isSet(QType::NSEC3), false); @@ -648,7 +648,7 @@ BOOST_AUTO_TEST_CASE(test_nsec3_records_types) { auto nsec3Content = std::dynamic_pointer_cast(validNSEC3); BOOST_REQUIRE(nsec3Content); - for (const auto type : { QType::A, QType::MX, QType::RRSIG, QType::NSEC3, static_cast(1234), static_cast(65535) }) { + for (const auto type : { QType::A, QType::MX, QType::RRSIG, QType::NSEC3, static_cast(1234), static_cast(65535) }) { BOOST_CHECK(nsec3Content->isSet(type)); } BOOST_CHECK_EQUAL(nsec3Content->isSet(QType::NSEC), false); diff --git a/pdns/ws-auth.cc b/pdns/ws-auth.cc index 5002ffaeb684..ab1098b27a42 100644 --- a/pdns/ws-auth.cc +++ b/pdns/ws-auth.cc @@ -457,7 +457,7 @@ static void fillZone(UeberBackend& backend, const DNSName& zonename, HttpRespons qType = QType::ANY; } else { - qType = req->getvars["rrset_type"]; + qType = QType::fromString(req->getvars["rrset_type"]); } domainInfo.backend->lookup(qType, DNSName(req->getvars["rrset_name"]), static_cast(domainInfo.id)); } @@ -1908,7 +1908,7 @@ static void apiServerZonesPOST(HttpRequest* req, HttpResponse* resp) DNSName qname = apiNameToDNSName(stringFromJson(rrset, "name")); apiCheckQNameAllowedCharacters(qname.toString()); QType qtype; - qtype = stringFromJson(rrset, "type"); + qtype = QType::fromString(stringFromJson(rrset, "type")); if (qtype.getCode() == 0) { throw ApiException("RRset " + qname.toString() + " IN " + stringFromJson(rrset, "type") + ": unknown type given"); } @@ -2124,7 +2124,7 @@ static void apiServerZoneDetailPUT(HttpRequest* req, HttpResponse* resp) DNSName qname = apiNameToDNSName(stringFromJson(rrset, "name")); apiCheckQNameAllowedCharacters(qname.toString()); QType qtype; - qtype = stringFromJson(rrset, "type"); + qtype = QType::fromString(stringFromJson(rrset, "type")); if (qtype.getCode() == 0) { throw ApiException("RRset " + qname.toString() + " IN " + stringFromJson(rrset, "type") + ": unknown type given"); } @@ -2337,7 +2337,7 @@ static void patchZone(UeberBackend& backend, const DNSName& zonename, DomainInfo DNSName qname = apiNameToDNSName(stringFromJson(rrset, "name")); apiCheckQNameAllowedCharacters(qname.toString()); QType qtype; - qtype = stringFromJson(rrset, "type"); + qtype = QType::fromString(stringFromJson(rrset, "type")); if (qtype.getCode() == 0) { throw ApiException("RRset " + qname.toString() + " IN " + stringFromJson(rrset, "type") + ": unknown type given"); } From 47792d69de01cb8e2efb488a1a7fbe8e035d2460 Mon Sep 17 00:00:00 2001 From: Fred Morcos Date: Wed, 3 Jul 2024 11:51:03 +0200 Subject: [PATCH 3/4] Rec: Adapt to QType class changes --- pdns/recursordist/rec-lua-conf.cc | 2 +- pdns/recursordist/rec_channel_rec.cc | 2 +- pdns/recursordist/settings/cxxsupport.cc | 8 ++++---- pdns/recursordist/syncres.cc | 2 +- pdns/recursordist/ws-recursor.cc | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pdns/recursordist/rec-lua-conf.cc b/pdns/recursordist/rec-lua-conf.cc index 98a8c15e8865..a56973bd02de 100644 --- a/pdns/recursordist/rec-lua-conf.cc +++ b/pdns/recursordist/rec-lua-conf.cc @@ -216,7 +216,7 @@ static void parseProtobufOptions(const boost::optional& vars, qtype = std::stoul(type); } catch (const std::exception& ex) { - qtype = QType::chartocode(type.c_str()); + qtype = QType::fromString(type); if (qtype == 0) { throw std::runtime_error("Unknown QType '" + type + "' in protobuf's export types"); } diff --git a/pdns/recursordist/rec_channel_rec.cc b/pdns/recursordist/rec_channel_rec.cc index a2b040cb339b..0cd83fc7eb5f 100644 --- a/pdns/recursordist/rec_channel_rec.cc +++ b/pdns/recursordist/rec_channel_rec.cc @@ -2350,7 +2350,7 @@ RecursorControlChannel::Answer RecursorControlParser::getAnswer(int socket, cons if (begin == end) { return {1, "Need a qtype\n"}; } - uint16_t qtype = QType::chartocode(begin->c_str()); + uint16_t qtype = QType::fromString(*begin); if (qtype == 0) { return {1, "Unknown qtype " + *begin + "\n"}; } diff --git a/pdns/recursordist/settings/cxxsupport.cc b/pdns/recursordist/settings/cxxsupport.cc index 92373e6d8c8b..6a208df34128 100644 --- a/pdns/recursordist/settings/cxxsupport.cc +++ b/pdns/recursordist/settings/cxxsupport.cc @@ -1095,7 +1095,7 @@ void fromRustToLuaConfig(const pdns::rust::settings::rec::ProtobufServer& pbServ exp.enabled = true; exp.exportTypes.clear(); for (const auto& type : pbServer.exportTypes) { - exp.exportTypes.emplace(QType::chartocode(std::string(type).c_str())); + exp.exportTypes.emplace(QType::fromString(std::string(type))); } for (const auto& server : pbServer.servers) { exp.servers.emplace_back(std::string(server)); @@ -1253,10 +1253,10 @@ void fromRustToLuaConfig(const rust::Vec& s void fromRustToLuaConfig(const rust::Vec& alloweds, std::map, AdditionalMode>>& lua) { for (const auto& allowed : alloweds) { - QType qtype(QType::chartocode(std::string(allowed.qtype).c_str())); + QType qtype = QType::fromString(std::string(allowed.qtype)); std::set set; for (const auto& target : allowed.targets) { - set.emplace(QType::chartocode(std::string(target).c_str())); + set.emplace(QType::fromString(std::string(target))); } AdditionalMode mode = AdditionalMode::CacheOnlyRequireAuth; mode = cvtAdditional(std::string(allowed.mode)); @@ -1384,7 +1384,7 @@ pdns::settings::rec::YamlSettingsStatus pdns::settings::rec::tryReadYAML(const s uint16_t pdns::rust::settings::rec::qTypeStringToCode(::rust::Str str) { std::string tmp(str.data(), str.length()); - return QType::chartocode(tmp.c_str()); + return QType::fromString(std::string(tmp)); } bool pdns::rust::settings::rec::isValidHostname(::rust::Str str) diff --git a/pdns/recursordist/syncres.cc b/pdns/recursordist/syncres.cc index 1e5864aaa9e8..f8446862c8e5 100644 --- a/pdns/recursordist/syncres.cc +++ b/pdns/recursordist/syncres.cc @@ -851,7 +851,7 @@ bool SyncRes::doSpecialNamesResolve(const DNSName& qname, const QType qtype, con static const DNSName negativetrustanchorserver("negativetrustanchor.server."); bool handled = false; - vector> answers; + vector> answers; if ((qname == arpa || qname == ip6_arpa) && qclass == QClass::IN) { handled = true; diff --git a/pdns/recursordist/ws-recursor.cc b/pdns/recursordist/ws-recursor.cc index 342d54c4308c..5939cc871c21 100644 --- a/pdns/recursordist/ws-recursor.cc +++ b/pdns/recursordist/ws-recursor.cc @@ -479,7 +479,7 @@ static void apiServerCacheFlush(HttpRequest* req, HttpResponse* resp) bool subtree = req->getvars.count("subtree") > 0 && req->getvars["subtree"] == "true"; uint16_t qtype = 0xffff; if (req->getvars.count("type") != 0) { - qtype = QType::chartocode(req->getvars["type"].c_str()); + qtype = QType::fromString(req->getvars["type"]); } struct WipeCacheResult res = wipeCaches(canon, subtree, qtype); From 6f9335e306f152b704c1bf36579924b0a203d4fc Mon Sep 17 00:00:00 2001 From: Fred Morcos Date: Wed, 3 Jul 2024 12:17:32 +0200 Subject: [PATCH 4/4] DNSdist: Adapt to QType class changes --- pdns/dnsdistdist/dnsdist-lua-rules.cc | 2 +- pdns/dnsdistdist/dnsdist-rings.cc | 2 +- pdns/dnsdistdist/dnsdist-web.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pdns/dnsdistdist/dnsdist-lua-rules.cc b/pdns/dnsdistdist/dnsdist-lua-rules.cc index a4d7adbcfdd3..9e2a364e44b0 100644 --- a/pdns/dnsdistdist/dnsdist-lua-rules.cc +++ b/pdns/dnsdistdist/dnsdist-lua-rules.cc @@ -544,7 +544,7 @@ void setupLuaRules(LuaContext& luaCtx) } else { string val = boost::get(str); - qtype = QType::chartocode(val.c_str()); + qtype = QType::fromString(val); if (qtype == 0) { throw std::runtime_error("Unable to convert '" + val + "' to a DNS type"); } diff --git a/pdns/dnsdistdist/dnsdist-rings.cc b/pdns/dnsdistdist/dnsdist-rings.cc index ba55561fede9..33730d40bafd 100644 --- a/pdns/dnsdistdist/dnsdist-rings.cc +++ b/pdns/dnsdistdist/dnsdist-rings.cc @@ -202,7 +202,7 @@ size_t Rings::loadFromFile(const std::string& filepath, const struct timespec& n /* skip ID */ idx++; DNSName qname(parts.at(idx++)); - QType qtype(QType::chartocode(parts.at(idx++).c_str())); + QType qtype(QType::fromString(parts.at(idx++))); if (isResponse) { insertResponse(when, from, qname, qtype.getCode(), 0, 0, dnsHeader, dest, protocol); diff --git a/pdns/dnsdistdist/dnsdist-web.cc b/pdns/dnsdistdist/dnsdist-web.cc index 368ee9e75a63..04e8033489e6 100644 --- a/pdns/dnsdistdist/dnsdist-web.cc +++ b/pdns/dnsdistdist/dnsdist-web.cc @@ -1583,7 +1583,7 @@ static void handleCacheManagement(const YaHTTP::Request& req, YaHTTP::Response& return; } if (expungeType != req.getvars.end()) { - type = QType::chartocode(expungeType->second.c_str()); + type = QType::fromString(expungeType->second); } std::shared_ptr pool;