From: Remi Gacogne Date: Tue, 24 Dec 2024 11:50:41 +0000 (+0100) Subject: dnsdist: Stop using Actions for regular processing X-Git-Tag: dnsdist-2.0.0-alpha1~160^2~40 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=235804423f7899a7437344e599cbdfd96f571d3f;p=thirdparty%2Fpdns.git dnsdist: Stop using Actions for regular processing --- diff --git a/pdns/dnsdistdist/Makefile.am b/pdns/dnsdistdist/Makefile.am index 3ab92cb6d3..8a881c8b43 100644 --- a/pdns/dnsdistdist/Makefile.am +++ b/pdns/dnsdistdist/Makefile.am @@ -205,6 +205,7 @@ dnsdist_SOURCES = \ dnsdist-rule-chains.cc dnsdist-rule-chains.hh \ dnsdist-rules.cc dnsdist-rules.hh \ dnsdist-secpoll.cc dnsdist-secpoll.hh \ + dnsdist-self-answers.cc dnsdist-self-answers.hh \ dnsdist-session-cache.cc dnsdist-session-cache.hh \ dnsdist-snmp.cc dnsdist-snmp.hh \ dnsdist-svc.cc dnsdist-svc.hh \ @@ -312,6 +313,7 @@ testrunner_SOURCES = \ dnsdist-rings.cc dnsdist-rings.hh \ dnsdist-rule-chains.cc dnsdist-rule-chains.hh \ dnsdist-rules.cc dnsdist-rules.hh \ + dnsdist-self-answers.cc dnsdist-self-answers.hh \ dnsdist-session-cache.cc dnsdist-session-cache.hh \ dnsdist-svc.cc dnsdist-svc.hh \ dnsdist-tcp-downstream.cc \ diff --git a/pdns/dnsdistdist/dnsdist-lua-actions.cc b/pdns/dnsdistdist/dnsdist-lua-actions.cc index 17bc184dc6..24c13b4482 100644 --- a/pdns/dnsdistdist/dnsdist-lua-actions.cc +++ b/pdns/dnsdistdist/dnsdist-lua-actions.cc @@ -33,6 +33,7 @@ #include "dnsdist-proxy-protocol.hh" #include "dnsdist-kvs.hh" #include "dnsdist-rule-chains.hh" +#include "dnsdist-self-answers.hh" #include "dnsdist-snmp.hh" #include "dnsdist-svc.hh" @@ -411,8 +412,8 @@ private: class RCodeAction : public DNSAction { public: - RCodeAction(uint8_t rcode) : - d_rcode(rcode) {} + RCodeAction(uint8_t rcode, dnsdist::ResponseConfig responseConfig) : + d_responseConfig(responseConfig), d_rcode(rcode) {} DNSAction::Action operator()(DNSQuestion* dnsquestion, std::string* ruleresult) const override { dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsquestion->getMutableData(), [this](dnsheader& header) { @@ -427,10 +428,6 @@ public: { return "set rcode " + std::to_string(d_rcode); } - [[nodiscard]] dnsdist::ResponseConfig& getResponseConfig() - { - return d_responseConfig; - } private: dnsdist::ResponseConfig d_responseConfig; @@ -440,8 +437,8 @@ private: class ERCodeAction : public DNSAction { public: - ERCodeAction(uint8_t rcode) : - d_rcode(rcode) {} + ERCodeAction(uint8_t rcode, dnsdist::ResponseConfig responseConfig) : + d_responseConfig(responseConfig), d_rcode(rcode) {} DNSAction::Action operator()(DNSQuestion* dnsquestion, std::string* ruleresult) const override { dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsquestion->getMutableData(), [this](dnsheader& header) { @@ -457,10 +454,6 @@ public: { return "set ercode " + ERCode::to_s(d_rcode); } - [[nodiscard]] dnsdist::ResponseConfig& getResponseConfig() - { - return d_responseConfig; - } private: dnsdist::ResponseConfig d_responseConfig; @@ -470,7 +463,8 @@ private: class SpoofSVCAction : public DNSAction { public: - SpoofSVCAction(const LuaArray& parameters) + SpoofSVCAction(const LuaArray& parameters, dnsdist::ResponseConfig responseConfig) : + d_responseConfig(responseConfig) { d_payloads.reserve(parameters.size()); @@ -506,11 +500,6 @@ public: return "spoof SVC record "; } - [[nodiscard]] dnsdist::ResponseConfig& getResponseConfig() - { - return d_responseConfig; - } - private: dnsdist::ResponseConfig d_responseConfig; std::vector> d_payloads{}; @@ -884,177 +873,101 @@ private: std::atomic LuaFFIPerThreadResponseAction::s_functionsCounter = 0; thread_local std::map LuaFFIPerThreadResponseAction::t_perThreadStates; -thread_local std::default_random_engine SpoofAction::t_randomEngine; - -DNSAction::Action SpoofAction::operator()(DNSQuestion* dnsquestion, std::string* ruleresult) const +class SpoofAction : public DNSAction { - uint16_t qtype = dnsquestion->ids.qtype; - // do we even have a response? - if (d_cname.empty() && d_rawResponses.empty() && - // make sure pre-forged response is greater than sizeof(dnsheader) - (d_raw.size() < sizeof(dnsheader)) && d_types.count(qtype) == 0) { - return Action::None; - } - - if (d_raw.size() >= sizeof(dnsheader)) { - auto questionId = dnsquestion->getHeader()->id; - dnsquestion->getMutableData() = d_raw; - dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsquestion->getMutableData(), [questionId](dnsheader& header) { - header.id = questionId; - return true; - }); - return Action::HeaderModify; - } - std::vector addrs = {}; - std::vector rawResponses = {}; - unsigned int totrdatalen = 0; - size_t numberOfRecords = 0; - if (!d_cname.empty()) { - qtype = QType::CNAME; - totrdatalen += d_cname.getStorage().size(); - numberOfRecords = 1; - } - else if (!d_rawResponses.empty()) { - rawResponses.reserve(d_rawResponses.size()); - for (const auto& rawResponse : d_rawResponses) { - totrdatalen += rawResponse.size(); - rawResponses.push_back(rawResponse); - ++numberOfRecords; - } - if (rawResponses.size() > 1) { - shuffle(rawResponses.begin(), rawResponses.end(), t_randomEngine); - } - } - else { +public: + SpoofAction(const vector& addrs, const dnsdist::ResponseConfig& responseConfig) : + d_responseConfig(responseConfig), d_addrs(addrs) + { for (const auto& addr : d_addrs) { - if (qtype != QType::ANY && ((addr.sin4.sin_family == AF_INET && qtype != QType::A) || (addr.sin4.sin_family == AF_INET6 && qtype != QType::AAAA))) { - continue; + if (addr.isIPv4()) { + d_types.insert(QType::A); + } + else if (addr.isIPv6()) { + d_types.insert(QType::AAAA); } - totrdatalen += addr.sin4.sin_family == AF_INET ? sizeof(addr.sin4.sin_addr.s_addr) : sizeof(addr.sin6.sin6_addr.s6_addr); - addrs.push_back(addr); - ++numberOfRecords; } - } - if (addrs.size() > 1) { - shuffle(addrs.begin(), addrs.end(), t_randomEngine); + if (!d_addrs.empty()) { + d_types.insert(QType::ANY); + } } - unsigned int qnameWireLength = 0; - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) - DNSName ignore(reinterpret_cast(dnsquestion->getData().data()), dnsquestion->getData().size(), sizeof(dnsheader), false, nullptr, nullptr, &qnameWireLength); - - if (dnsquestion->getMaximumSize() < (sizeof(dnsheader) + qnameWireLength + 4 + numberOfRecords * 12 /* recordstart */ + totrdatalen)) { - return Action::None; + SpoofAction(const DNSName& cname, const dnsdist::ResponseConfig& responseConfig) : + d_responseConfig(responseConfig), d_cname(cname) + { } - bool dnssecOK = false; - bool hadEDNS = false; - if (dnsdist::configuration::getCurrentRuntimeConfiguration().d_addEDNSToSelfGeneratedResponses && queryHasEDNS(*dnsquestion)) { - hadEDNS = true; - dnssecOK = ((dnsdist::getEDNSZ(*dnsquestion) & EDNS_HEADER_FLAG_DO) != 0); + SpoofAction(const PacketBuffer& rawresponse) : + d_raw(rawresponse) + { } - auto& data = dnsquestion->getMutableData(); - data.resize(sizeof(dnsheader) + qnameWireLength + 4 + numberOfRecords * 12 /* recordstart */ + totrdatalen); // there goes your EDNS - uint8_t* dest = &(data.at(sizeof(dnsheader) + qnameWireLength + 4)); + SpoofAction(const vector& raws, std::optional typeForAny, const dnsdist::ResponseConfig& responseConfig) : + d_responseConfig(responseConfig), d_rawResponses(raws), d_rawTypeForAny(typeForAny) + { + } - dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsquestion->getMutableData(), [this](dnsheader& header) { - header.qr = true; // for good measure - setResponseHeadersFromConfig(header, d_responseConfig); - header.ancount = 0; - header.arcount = 0; // for now, forget about your EDNS, we're marching over it - return true; - }); + DNSAction::Action operator()(DNSQuestion* dnsquestion, string* ruleresult) const override; - uint32_t ttl = htonl(d_responseConfig.ttl); - uint16_t qclass = htons(dnsquestion->ids.qclass); - std::array recordstart = { - 0xc0, 0x0c, // compressed name - 0, 0, // QTYPE - 0, 0, // QCLASS - 0, 0, 0, 0, // TTL - 0, 0 // rdata length - }; - static_assert(recordstart.size() == 12, "sizeof(recordstart) must be equal to 12, otherwise the above check is invalid"); - memcpy(&recordstart[4], &qclass, sizeof(qclass)); - memcpy(&recordstart[6], &ttl, sizeof(ttl)); - - if (qtype == QType::CNAME) { - const auto& wireData = d_cname.getStorage(); // Note! This doesn't do compression! - uint16_t rdataLen = htons(wireData.length()); - qtype = htons(qtype); - memcpy(&recordstart[2], &qtype, sizeof(qtype)); - memcpy(&recordstart[10], &rdataLen, sizeof(rdataLen)); - - memcpy(dest, recordstart.data(), recordstart.size()); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - dest += recordstart.size(); - memcpy(dest, wireData.c_str(), wireData.length()); - dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsquestion->getMutableData(), [](dnsheader& header) { - header.ancount++; - return true; - }); - } - else if (!rawResponses.empty()) { - if (qtype == QType::ANY && d_rawTypeForAny) { - qtype = *d_rawTypeForAny; + string toString() const override + { + string ret = "spoof in "; + if (!d_cname.empty()) { + ret += d_cname.toString() + " "; + } + if (d_rawResponses.size() > 0) { + ret += "raw bytes "; + } + else { + for (const auto& a : d_addrs) + ret += a.toString() + " "; } - qtype = htons(qtype); - for (const auto& rawResponse : rawResponses) { - uint16_t rdataLen = htons(rawResponse.size()); - memcpy(&recordstart[2], &qtype, sizeof(qtype)); - memcpy(&recordstart[10], &rdataLen, sizeof(rdataLen)); + return ret; + } - memcpy(dest, recordstart.data(), sizeof(recordstart)); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - dest += recordstart.size(); +private: + dnsdist::ResponseConfig d_responseConfig; + std::vector d_addrs; + std::unordered_set d_types; + std::vector d_rawResponses; + PacketBuffer d_raw; + DNSName d_cname; + std::optional d_rawTypeForAny{}; +}; - memcpy(dest, rawResponse.c_str(), rawResponse.size()); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - dest += rawResponse.size(); +DNSAction::Action SpoofAction::operator()(DNSQuestion* dnsquestion, std::string* ruleresult) const +{ + uint16_t qtype = dnsquestion->ids.qtype; + // do we even have a response? + if (d_cname.empty() && d_rawResponses.empty() && + // make sure pre-forged response is greater than sizeof(dnsheader) + (d_raw.size() < sizeof(dnsheader)) && d_types.count(qtype) == 0) { + return Action::None; + } - dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsquestion->getMutableData(), [](dnsheader& header) { - header.ancount++; - return true; - }); + if (d_raw.size() >= sizeof(dnsheader)) { + dnsdist::self_answers::generateAnswerFromRawPacket(*dnsquestion, d_raw); + return Action::HeaderModify; + } + + if (!d_cname.empty()) { + if (dnsdist::self_answers::generateAnswerFromCNAME(*dnsquestion, d_cname, d_responseConfig)) { + return Action::HeaderModify; } } - else { - for (const auto& addr : addrs) { - uint16_t rdataLen = htons(addr.sin4.sin_family == AF_INET ? sizeof(addr.sin4.sin_addr.s_addr) : sizeof(addr.sin6.sin6_addr.s6_addr)); - qtype = htons(addr.sin4.sin_family == AF_INET ? QType::A : QType::AAAA); - memcpy(&recordstart[2], &qtype, sizeof(qtype)); - memcpy(&recordstart[10], &rdataLen, sizeof(rdataLen)); - - memcpy(dest, recordstart.data(), recordstart.size()); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - dest += sizeof(recordstart); - - memcpy(dest, - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) - addr.sin4.sin_family == AF_INET ? reinterpret_cast(&addr.sin4.sin_addr.s_addr) : reinterpret_cast(&addr.sin6.sin6_addr.s6_addr), - addr.sin4.sin_family == AF_INET ? sizeof(addr.sin4.sin_addr.s_addr) : sizeof(addr.sin6.sin6_addr.s6_addr)); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - dest += (addr.sin4.sin_family == AF_INET ? sizeof(addr.sin4.sin_addr.s_addr) : sizeof(addr.sin6.sin6_addr.s6_addr)); - dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsquestion->getMutableData(), [](dnsheader& header) { - header.ancount++; - return true; - }); + else if (!d_rawResponses.empty()) { + if (dnsdist::self_answers::generateAnswerFromRDataEntries(*dnsquestion, d_rawResponses, d_rawTypeForAny, d_responseConfig)) { + return Action::HeaderModify; } } - - auto finalANCount = dnsquestion->getHeader()->ancount; - dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsquestion->getMutableData(), [finalANCount](dnsheader& header) { - header.ancount = htons(finalANCount); - return true; - }); - - if (hadEDNS) { - addEDNS(dnsquestion->getMutableData(), dnsquestion->getMaximumSize(), dnssecOK, dnsdist::configuration::getCurrentRuntimeConfiguration().d_payloadSizeSelfGenAnswers, 0); + else { + if (dnsdist::self_answers::generateAnswerFromIPAddresses(*dnsquestion, d_addrs, d_responseConfig)) { + return Action::HeaderModify; + } } - return Action::HeaderModify; + return Action::None; } class SetMacAddrAction : public DNSAction @@ -2066,8 +1979,8 @@ private: class HTTPStatusAction : public DNSAction { public: - HTTPStatusAction(int code, PacketBuffer body, std::string contentType) : - d_body(std::move(body)), d_contentType(std::move(contentType)), d_code(code) + HTTPStatusAction(int code, PacketBuffer body, std::string contentType, dnsdist::ResponseConfig responseConfig) : + d_responseConfig(responseConfig), d_body(std::move(body)), d_contentType(std::move(contentType)), d_code(code) { } @@ -2103,11 +2016,6 @@ public: return "return an HTTP status of " + std::to_string(d_code); } - [[nodiscard]] dnsdist::ResponseConfig& getResponseConfig() - { - return d_responseConfig; - } - private: dnsdist::ResponseConfig d_responseConfig; PacketBuffer d_body; @@ -2246,8 +2154,8 @@ public: uint32_t minimum; }; - NegativeAndSOAAction(bool nxd, DNSName zone, uint32_t ttl, DNSName mname, DNSName rname, SOAParams params, bool soaInAuthoritySection) : - d_zone(std::move(zone)), d_mname(std::move(mname)), d_rname(std::move(rname)), d_ttl(ttl), d_params(params), d_nxd(nxd), d_soaInAuthoritySection(soaInAuthoritySection) + NegativeAndSOAAction(bool nxd, DNSName zone, uint32_t ttl, DNSName mname, DNSName rname, SOAParams params, bool soaInAuthoritySection, dnsdist::ResponseConfig responseConfig) : + d_responseConfig(responseConfig), d_zone(std::move(zone)), d_mname(std::move(mname)), d_rname(std::move(rname)), d_ttl(ttl), d_params(params), d_nxd(nxd), d_soaInAuthoritySection(soaInAuthoritySection) { } @@ -2269,10 +2177,6 @@ public: { return std::string(d_nxd ? "NXD" : "NODATA") + " with SOA"; } - [[nodiscard]] dnsdist::ResponseConfig& getResponseConfig() - { - return d_responseConfig; - } private: dnsdist::ResponseConfig d_responseConfig; @@ -2448,12 +2352,14 @@ static void addAction(IdentifierT identifier, const luadnsrule_t& var, const std using responseParams_t = std::unordered_map>; -static void parseResponseConfig(boost::optional& vars, dnsdist::ResponseConfig& config) +static dnsdist::ResponseConfig parseResponseConfig(boost::optional& vars) { + dnsdist::ResponseConfig config; getOptionalValue(vars, "ttl", config.ttl); getOptionalValue(vars, "aa", config.setAA); getOptionalValue(vars, "ad", config.setAD); getOptionalValue(vars, "ra", config.setRA); + return config; } // NOLINTNEXTLINE(readability-function-cognitive-complexity): this function declares Lua bindings, even with a good refactoring it will likely blow up the threshold @@ -2574,25 +2480,23 @@ void setupLuaActions(LuaContext& luaCtx) } } - auto ret = std::shared_ptr(new SpoofAction(addrs)); - auto spoofaction = std::dynamic_pointer_cast(ret); - parseResponseConfig(vars, spoofaction->getResponseConfig()); + auto responseConfig = parseResponseConfig(vars); checkAllParametersConsumed("SpoofAction", vars); + auto ret = std::shared_ptr(new SpoofAction(addrs, responseConfig)); return ret; }); luaCtx.writeFunction("SpoofSVCAction", [](const LuaArray& parameters, boost::optional vars) { - auto ret = std::shared_ptr(new SpoofSVCAction(parameters)); - auto spoofaction = std::dynamic_pointer_cast(ret); - parseResponseConfig(vars, spoofaction->getResponseConfig()); + auto responseConfig = parseResponseConfig(vars); + checkAllParametersConsumed("SpoofAction", vars); + auto ret = std::shared_ptr(new SpoofSVCAction(parameters, responseConfig)); return ret; }); luaCtx.writeFunction("SpoofCNAMEAction", [](const std::string& cname, boost::optional vars) { - auto ret = std::shared_ptr(new SpoofAction(DNSName(cname))); - auto spoofaction = std::dynamic_pointer_cast(ret); - parseResponseConfig(vars, spoofaction->getResponseConfig()); + auto responseConfig = parseResponseConfig(vars); checkAllParametersConsumed("SpoofCNAMEAction", vars); + auto ret = std::shared_ptr(new SpoofAction(DNSName(cname), responseConfig)); return ret; }); @@ -2616,10 +2520,9 @@ void setupLuaActions(LuaContext& luaCtx) if (qtypeForAny > 0) { qtypeForAnyParam = static_cast(qtypeForAny); } - auto ret = std::shared_ptr(new SpoofAction(raws, qtypeForAnyParam)); - auto spoofaction = std::dynamic_pointer_cast(ret); - parseResponseConfig(vars, spoofaction->getResponseConfig()); + auto responseConfig = parseResponseConfig(vars); checkAllParametersConsumed("SpoofRawAction", vars); + auto ret = std::shared_ptr(new SpoofAction(raws, qtypeForAnyParam, responseConfig)); return ret; }); @@ -2627,7 +2530,8 @@ void setupLuaActions(LuaContext& luaCtx) if (len < sizeof(dnsheader)) { throw std::runtime_error(std::string("SpoofPacketAction: given packet len is too small")); } - auto ret = std::shared_ptr(new SpoofAction(response.c_str(), len)); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + auto ret = std::shared_ptr(new SpoofAction(PacketBuffer(response.data(), response.data() + len))); return ret; }); @@ -2716,18 +2620,16 @@ void setupLuaActions(LuaContext& luaCtx) }); luaCtx.writeFunction("RCodeAction", [](uint8_t rcode, boost::optional vars) { - auto ret = std::shared_ptr(new RCodeAction(rcode)); - auto rca = std::dynamic_pointer_cast(ret); - parseResponseConfig(vars, rca->getResponseConfig()); + auto responseConfig = parseResponseConfig(vars); checkAllParametersConsumed("RCodeAction", vars); + auto ret = std::shared_ptr(new RCodeAction(rcode, responseConfig)); return ret; }); luaCtx.writeFunction("ERCodeAction", [](uint8_t rcode, boost::optional vars) { - auto ret = std::shared_ptr(new ERCodeAction(rcode)); - auto erca = std::dynamic_pointer_cast(ret); - parseResponseConfig(vars, erca->getResponseConfig()); + auto responseConfig = parseResponseConfig(vars); checkAllParametersConsumed("ERCodeAction", vars); + auto ret = std::shared_ptr(new ERCodeAction(rcode, responseConfig)); return ret; }); @@ -2914,10 +2816,9 @@ void setupLuaActions(LuaContext& luaCtx) #ifdef HAVE_DNS_OVER_HTTPS luaCtx.writeFunction("HTTPStatusAction", [](uint16_t status, std::string body, boost::optional contentType, boost::optional vars) { - auto ret = std::shared_ptr(new HTTPStatusAction(status, PacketBuffer(body.begin(), body.end()), contentType ? *contentType : "")); - auto hsa = std::dynamic_pointer_cast(ret); - parseResponseConfig(vars, hsa->getResponseConfig()); + auto responseConfig = parseResponseConfig(vars); checkAllParametersConsumed("HTTPStatusAction", vars); + auto ret = std::shared_ptr(new HTTPStatusAction(status, PacketBuffer(body.begin(), body.end()), contentType ? *contentType : "", responseConfig)); return ret; }); #endif /* HAVE_DNS_OVER_HTTPS */ @@ -2933,6 +2834,7 @@ void setupLuaActions(LuaContext& luaCtx) #endif /* defined(HAVE_LMDB) || defined(HAVE_CDB) */ luaCtx.writeFunction("NegativeAndSOAAction", [](bool nxd, const std::string& zone, uint32_t ttl, const std::string& mname, const std::string& rname, uint32_t serial, uint32_t refresh, uint32_t retry, uint32_t expire, uint32_t minimum, boost::optional vars) { + auto responseConfig = parseResponseConfig(vars); bool soaInAuthoritySection = false; getOptionalValue(vars, "soaInAuthoritySection", soaInAuthoritySection); NegativeAndSOAAction::SOAParams params{ @@ -2941,10 +2843,8 @@ void setupLuaActions(LuaContext& luaCtx) .retry = retry, .expire = expire, .minimum = minimum}; - auto ret = std::shared_ptr(new NegativeAndSOAAction(nxd, DNSName(zone), ttl, DNSName(mname), DNSName(rname), params, soaInAuthoritySection)); - auto action = std::dynamic_pointer_cast(ret); - parseResponseConfig(vars, action->getResponseConfig()); checkAllParametersConsumed("NegativeAndSOAAction", vars); + auto ret = std::shared_ptr(new NegativeAndSOAAction(nxd, DNSName(zone), ttl, DNSName(mname), DNSName(rname), params, soaInAuthoritySection, responseConfig)); return ret; }); diff --git a/pdns/dnsdistdist/dnsdist-lua-bindings-dnsquestion.cc b/pdns/dnsdistdist/dnsdist-lua-bindings-dnsquestion.cc index 8863e0bb5d..8ae0d81704 100644 --- a/pdns/dnsdistdist/dnsdist-lua-bindings-dnsquestion.cc +++ b/pdns/dnsdistdist/dnsdist-lua-bindings-dnsquestion.cc @@ -25,6 +25,7 @@ #include "dnsdist-ecs.hh" #include "dnsdist-internal-queries.hh" #include "dnsdist-lua.hh" +#include "dnsdist-self-answers.hh" #include "dnsdist-snmp.hh" #include "dnsparser.hh" @@ -254,6 +255,7 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx) }); luaCtx.registerFunction, LuaArray>&, boost::optional)>("spoof", [](DNSQuestion& dnsQuestion, const boost::variant, LuaArray>& response, boost::optional typeForAny) { + dnsdist::ResponseConfig responseConfig; if (response.type() == typeid(LuaArray)) { std::vector data; auto responses = boost::get>(response); @@ -261,9 +263,7 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx) for (const auto& resp : responses) { data.push_back(resp.second); } - std::string result; - SpoofAction tempSpoofAction(data); - tempSpoofAction(&dnsQuestion, &result); + dnsdist::self_answers::generateAnswerFromIPAddresses(dnsQuestion, data, responseConfig); return; } if (response.type() == typeid(LuaArray)) { @@ -273,9 +273,7 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx) for (const auto& resp : responses) { data.push_back(resp.second); } - std::string result; - SpoofAction tempSpoofAction(data, typeForAny ? *typeForAny : std::optional()); - tempSpoofAction(&dnsQuestion, &result); + dnsdist::self_answers::generateAnswerFromRDataEntries(dnsQuestion, data, typeForAny ? *typeForAny : std::optional(), responseConfig); return; } }); diff --git a/pdns/dnsdistdist/dnsdist-lua-ffi.cc b/pdns/dnsdistdist/dnsdist-lua-ffi.cc index 4cff7f35be..54886c6b8d 100644 --- a/pdns/dnsdistdist/dnsdist-lua-ffi.cc +++ b/pdns/dnsdistdist/dnsdist-lua-ffi.cc @@ -32,6 +32,7 @@ #include "dnsdist-lua.hh" #include "dnsdist-ecs.hh" #include "dnsdist-rings.hh" +#include "dnsdist-self-answers.hh" #include "dnsdist-svc.hh" #include "dnsdist-snmp.hh" #include "dolog.hh" @@ -644,9 +645,8 @@ void dnsdist_ffi_dnsquestion_send_trap(dnsdist_ffi_dnsquestion_t* dq, const char void dnsdist_ffi_dnsquestion_spoof_packet(dnsdist_ffi_dnsquestion_t* dq, const char* raw, size_t len) { - std::string result; - SpoofAction tempSpoofAction(raw, len); - tempSpoofAction(dq->dq, &result); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + dnsdist::self_answers::generateAnswerFromRawPacket(*dq->dq, PacketBuffer(raw, raw + len)); } void dnsdist_ffi_dnsquestion_spoof_raw(dnsdist_ffi_dnsquestion_t* dq, const dnsdist_ffi_raw_value_t* values, size_t valuesCount) @@ -658,9 +658,8 @@ void dnsdist_ffi_dnsquestion_spoof_raw(dnsdist_ffi_dnsquestion_t* dq, const dnsd data.emplace_back(values[idx].value, values[idx].size); } - std::string result; - SpoofAction tempSpoofAction(data, std::nullopt); - tempSpoofAction(dq->dq, &result); + dnsdist::ResponseConfig config{}; + dnsdist::self_answers::generateAnswerFromRDataEntries(*dq->dq, data, std::nullopt, config); } void dnsdist_ffi_dnsquestion_spoof_addrs(dnsdist_ffi_dnsquestion_t* dq, const dnsdist_ffi_raw_value_t* values, size_t valuesCount) @@ -687,9 +686,8 @@ void dnsdist_ffi_dnsquestion_spoof_addrs(dnsdist_ffi_dnsquestion_t* dq, const dn } } - std::string result; - SpoofAction tempSpoofAction(data); - tempSpoofAction(dq->dq, &result); + dnsdist::ResponseConfig config{}; + dnsdist::self_answers::generateAnswerFromIPAddresses(*dq->dq, data, config); } void dnsdist_ffi_dnsquestion_set_max_returned_ttl(dnsdist_ffi_dnsquestion_t* dq, uint32_t max) diff --git a/pdns/dnsdistdist/dnsdist-lua.hh b/pdns/dnsdistdist/dnsdist-lua.hh index 4fc06767c2..572b8a692e 100644 --- a/pdns/dnsdistdist/dnsdist-lua.hh +++ b/pdns/dnsdistdist/dnsdist-lua.hh @@ -33,75 +33,6 @@ extern RecursiveLockGuarded g_lua; extern std::string g_outputBuffer; // locking for this is ok, as locked by g_luamutex -class SpoofAction : public DNSAction -{ -public: - SpoofAction(const vector& addrs) : - d_addrs(addrs) - { - for (const auto& addr : d_addrs) { - if (addr.isIPv4()) { - d_types.insert(QType::A); - } - else if (addr.isIPv6()) { - d_types.insert(QType::AAAA); - } - } - - if (!d_addrs.empty()) { - d_types.insert(QType::ANY); - } - } - - SpoofAction(const DNSName& cname) : - d_cname(cname) - { - } - - SpoofAction(const char* rawresponse, size_t len) : - d_raw(rawresponse, rawresponse + len) - { - } - - SpoofAction(const vector& raws, std::optional typeForAny) : - d_rawResponses(raws), d_rawTypeForAny(typeForAny) - { - } - - DNSAction::Action operator()(DNSQuestion* dnsquestion, string* ruleresult) const override; - - string toString() const override - { - string ret = "spoof in "; - if (!d_cname.empty()) { - ret += d_cname.toString() + " "; - } - if (d_rawResponses.size() > 0) { - ret += "raw bytes "; - } - else { - for (const auto& a : d_addrs) - ret += a.toString() + " "; - } - return ret; - } - - [[nodiscard]] dnsdist::ResponseConfig& getResponseConfig() - { - return d_responseConfig; - } - -private: - dnsdist::ResponseConfig d_responseConfig; - static thread_local std::default_random_engine t_randomEngine; - std::vector d_addrs; - std::unordered_set d_types; - std::vector d_rawResponses; - PacketBuffer d_raw; - DNSName d_cname; - std::optional d_rawTypeForAny{}; -}; - template using LuaArray = std::vector>; template diff --git a/pdns/dnsdistdist/dnsdist-self-answers.cc b/pdns/dnsdistdist/dnsdist-self-answers.cc new file mode 100644 index 0000000000..dd0ff0b119 --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-self-answers.cc @@ -0,0 +1,243 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include + +#include "dnsdist-self-answers.hh" + +#include "dnsdist-configuration.hh" +#include "dnsdist-ecs.hh" + +namespace dnsdist::self_answers +{ +static thread_local std::default_random_engine t_randomEngine; + +static void addRecordHeader(PacketBuffer& packet, size_t& position, uint16_t qclass, uint32_t ttl, QType qtype, uint16_t rdataLen) +{ + std::array recordstart{ + 0xc0, 0x0c, // compressed name + 0, 0, // QTYPE + 0, 0, // QCLASS + 0, 0, 0, 0, // TTL + 0, 0 // rdata length + }; + ttl = htonl(ttl); + qclass = htons(qclass); + qtype = htons(qtype); + rdataLen = htons(rdataLen); + static_assert(recordstart.size() == 12, "sizeof(recordstart) must be equal to 12, otherwise the above check is invalid"); + memcpy(&recordstart.at(2), &qtype, sizeof(qtype)); + memcpy(&recordstart.at(4), &qclass, sizeof(qclass)); + memcpy(&recordstart.at(6), &ttl, sizeof(ttl)); + memcpy(&recordstart.at(10), &rdataLen, sizeof(rdataLen)); + memcpy(&packet.at(position), recordstart.data(), recordstart.size()); + position += recordstart.size(); +} + +bool generateAnswerFromCNAME(DNSQuestion& dnsQuestion, const DNSName& cname, const dnsdist::ResponseConfig& responseConfig) +{ + QType qtype = QType::CNAME; + unsigned int totrdatalen = cname.getStorage().size(); + size_t numberOfRecords = 1U; + auto qnameWireLength = dnsQuestion.ids.qname.wirelength(); + if (dnsQuestion.getMaximumSize() < (sizeof(dnsheader) + qnameWireLength + 4 + numberOfRecords * 12 /* recordstart */ + totrdatalen)) { + return false; + } + + bool dnssecOK = false; + bool hadEDNS = false; + if (dnsdist::configuration::getCurrentRuntimeConfiguration().d_addEDNSToSelfGeneratedResponses && queryHasEDNS(dnsQuestion)) { + hadEDNS = true; + dnssecOK = ((dnsdist::getEDNSZ(dnsQuestion) & EDNS_HEADER_FLAG_DO) != 0); + } + + auto& data = dnsQuestion.getMutableData(); + data.resize(sizeof(dnsheader) + qnameWireLength + 4 + numberOfRecords * 12 /* recordstart */ + totrdatalen); // there goes your EDNS + size_t position = sizeof(dnsheader) + qnameWireLength + 4; + + dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsQuestion.getMutableData(), [responseConfig](dnsheader& header) { + header.qr = true; // for good measure + setResponseHeadersFromConfig(header, responseConfig); + header.ancount = 0; + header.arcount = 0; // for now, forget about your EDNS, we're marching over it + return true; + }); + + const auto& wireData = cname.getStorage(); // Note! This doesn't do compression! + addRecordHeader(data, position, dnsQuestion.ids.qclass, responseConfig.ttl, qtype, wireData.length()); + memcpy(&data.at(position), wireData.c_str(), wireData.length()); + + dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsQuestion.getMutableData(), [numberOfRecords](dnsheader& header) { + header.ancount = htons(numberOfRecords); + return true; + }); + + if (hadEDNS) { + addEDNS(dnsQuestion.getMutableData(), dnsQuestion.getMaximumSize(), dnssecOK, dnsdist::configuration::getCurrentRuntimeConfiguration().d_payloadSizeSelfGenAnswers, 0); + } + + return true; +} + +bool generateAnswerFromIPAddresses(DNSQuestion& dnsQuestion, const std::vector& addresses, const dnsdist::ResponseConfig& responseConfig) +{ + uint16_t qtype = dnsQuestion.ids.qtype; + std::vector addrs = {}; + unsigned int totrdatalen = 0; + size_t numberOfRecords = 0; + for (const auto& addr : addresses) { + if (qtype != QType::ANY && ((addr.sin4.sin_family == AF_INET && qtype != QType::A) || (addr.sin4.sin_family == AF_INET6 && qtype != QType::AAAA))) { + continue; + } + totrdatalen += addr.sin4.sin_family == AF_INET ? sizeof(addr.sin4.sin_addr.s_addr) : sizeof(addr.sin6.sin6_addr.s6_addr); + addrs.push_back(addr); + ++numberOfRecords; + } + + if (addrs.size() > 1) { + shuffle(addrs.begin(), addrs.end(), t_randomEngine); + } + + unsigned int qnameWireLength = dnsQuestion.ids.qname.wirelength(); + if (dnsQuestion.getMaximumSize() < (sizeof(dnsheader) + qnameWireLength + 4 + numberOfRecords * 12 /* recordstart */ + totrdatalen)) { + return false; + } + + bool dnssecOK = false; + bool hadEDNS = false; + if (dnsdist::configuration::getCurrentRuntimeConfiguration().d_addEDNSToSelfGeneratedResponses && queryHasEDNS(dnsQuestion)) { + hadEDNS = true; + dnssecOK = ((dnsdist::getEDNSZ(dnsQuestion) & EDNS_HEADER_FLAG_DO) != 0); + } + + auto& data = dnsQuestion.getMutableData(); + data.resize(sizeof(dnsheader) + qnameWireLength + 4 + numberOfRecords * 12 /* recordstart */ + totrdatalen); // there goes your EDNS + size_t position = sizeof(dnsheader) + qnameWireLength + 4; + + dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsQuestion.getMutableData(), [responseConfig](dnsheader& header) { + header.qr = true; // for good measure + setResponseHeadersFromConfig(header, responseConfig); + header.ancount = 0; + header.arcount = 0; // for now, forget about your EDNS, we're marching over it + return true; + }); + + for (const auto& addr : addrs) { + uint16_t rdataLen = addr.sin4.sin_family == AF_INET ? sizeof(addr.sin4.sin_addr.s_addr) : sizeof(addr.sin6.sin6_addr.s6_addr); + qtype = addr.sin4.sin_family == AF_INET ? QType::A : QType::AAAA; + + addRecordHeader(data, position, dnsQuestion.ids.qclass, responseConfig.ttl, qtype, rdataLen); + + memcpy(&data.at(position), + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + addr.sin4.sin_family == AF_INET ? reinterpret_cast(&addr.sin4.sin_addr.s_addr) : reinterpret_cast(&addr.sin6.sin6_addr.s6_addr), + addr.sin4.sin_family == AF_INET ? sizeof(addr.sin4.sin_addr.s_addr) : sizeof(addr.sin6.sin6_addr.s6_addr)); + + position += (addr.sin4.sin_family == AF_INET ? sizeof(addr.sin4.sin_addr.s_addr) : sizeof(addr.sin6.sin6_addr.s6_addr)); + } + + auto finalANCount = addrs.size(); + dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsQuestion.getMutableData(), [finalANCount](dnsheader& header) { + header.ancount = htons(finalANCount); + return true; + }); + + if (hadEDNS) { + addEDNS(dnsQuestion.getMutableData(), dnsQuestion.getMaximumSize(), dnssecOK, dnsdist::configuration::getCurrentRuntimeConfiguration().d_payloadSizeSelfGenAnswers, 0); + } + + return true; +} + +bool generateAnswerFromRDataEntries(DNSQuestion& dnsQuestion, const std::vector& entries, std::optional typeForAny, const dnsdist::ResponseConfig& responseConfig) +{ + unsigned int totrdatalen = 0; + size_t numberOfRecords = 0; + auto shuffledEntries = entries; + for (const auto& entry : shuffledEntries) { + totrdatalen += entry.size(); + ++numberOfRecords; + } + if (shuffledEntries.size() > 1) { + shuffle(shuffledEntries.begin(), shuffledEntries.end(), t_randomEngine); + } + + auto qnameWireLength = dnsQuestion.ids.qname.wirelength(); + if (dnsQuestion.getMaximumSize() < (sizeof(dnsheader) + qnameWireLength + 4 + numberOfRecords * 12 /* recordstart */ + totrdatalen)) { + return false; + } + + bool dnssecOK = false; + bool hadEDNS = false; + if (dnsdist::configuration::getCurrentRuntimeConfiguration().d_addEDNSToSelfGeneratedResponses && queryHasEDNS(dnsQuestion)) { + hadEDNS = true; + dnssecOK = ((dnsdist::getEDNSZ(dnsQuestion) & EDNS_HEADER_FLAG_DO) != 0); + } + + auto& data = dnsQuestion.getMutableData(); + data.resize(sizeof(dnsheader) + qnameWireLength + 4 + numberOfRecords * 12 /* recordstart */ + totrdatalen); // there goes your EDNS + size_t position = sizeof(dnsheader) + qnameWireLength + 4; + + dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsQuestion.getMutableData(), [&responseConfig](dnsheader& header) { + header.qr = true; // for good measure + setResponseHeadersFromConfig(header, responseConfig); + header.ancount = 0; + header.arcount = 0; // for now, forget about your EDNS, we're marching over it + return true; + }); + + QType qtype = dnsQuestion.ids.qtype; + if (qtype == QType::ANY && typeForAny) { + qtype = *typeForAny; + } + + for (const auto& entry : shuffledEntries) { + uint16_t rdataLen = entry.size(); + addRecordHeader(data, position, dnsQuestion.ids.qclass, responseConfig.ttl, qtype, rdataLen); + memcpy(&data.at(position), entry.c_str(), entry.size()); + position += entry.size(); + } + + auto finalANCount = shuffledEntries.size(); + dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsQuestion.getMutableData(), [finalANCount](dnsheader& header) { + header.ancount = htons(finalANCount); + return true; + }); + + if (hadEDNS) { + addEDNS(dnsQuestion.getMutableData(), dnsQuestion.getMaximumSize(), dnssecOK, dnsdist::configuration::getCurrentRuntimeConfiguration().d_payloadSizeSelfGenAnswers, 0); + } + + return true; +} + +bool generateAnswerFromRawPacket(DNSQuestion& dnsQuestion, const PacketBuffer& packet) +{ + auto questionId = dnsQuestion.getHeader()->id; + dnsQuestion.getMutableData() = packet; + dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsQuestion.getMutableData(), [questionId](dnsheader& header) { + header.id = questionId; + return true; + }); + return true; +} + +} diff --git a/pdns/dnsdistdist/dnsdist-self-answers.hh b/pdns/dnsdistdist/dnsdist-self-answers.hh new file mode 100644 index 0000000000..5703db4648 --- /dev/null +++ b/pdns/dnsdistdist/dnsdist-self-answers.hh @@ -0,0 +1,32 @@ +/* + * This file is part of PowerDNS or dnsdist. + * Copyright -- PowerDNS.COM B.V. and its contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * In addition, for the avoidance of any doubt, permission is granted to + * link this program with OpenSSL and to (re)distribute the binaries + * produced as the result of such linking. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "dnsdist.hh" +#include "dnsdist-dnsparser.hh" + +namespace dnsdist::self_answers +{ +bool generateAnswerFromCNAME(DNSQuestion& dnsQuestion, const DNSName& cname, const dnsdist::ResponseConfig& responseConfig); +bool generateAnswerFromIPAddresses(DNSQuestion& dnsQuestion, const std::vector& addresses, const ResponseConfig& responseConfig); +bool generateAnswerFromRDataEntries(DNSQuestion& dnsQuestion, const std::vector& entries, std::optional typeForAny, const ResponseConfig& responseConfig); +bool generateAnswerFromRawPacket(DNSQuestion& dnsQuestion, const PacketBuffer& packet); +} diff --git a/pdns/dnsdistdist/dnsdist.cc b/pdns/dnsdistdist/dnsdist.cc index ee4f4d3316..088f8fe46e 100644 --- a/pdns/dnsdistdist/dnsdist.cc +++ b/pdns/dnsdistdist/dnsdist.cc @@ -58,6 +58,7 @@ #include "dnsdist-random.hh" #include "dnsdist-rings.hh" #include "dnsdist-secpoll.hh" +#include "dnsdist-self-answers.hh" #include "dnsdist-snmp.hh" #include "dnsdist-tcp.hh" #include "dnsdist-tcp-downstream.hh" @@ -830,28 +831,28 @@ static void spoofResponseFromString(DNSQuestion& dnsQuestion, const string& spoo string result; if (raw) { + dnsdist::ResponseConfig config; std::vector raws; stringtok(raws, spoofContent, ","); - SpoofAction tempSpoofAction(raws, std::nullopt); - tempSpoofAction(&dnsQuestion, &result); + dnsdist::self_answers::generateAnswerFromRDataEntries(dnsQuestion, raws, std::nullopt, config); } else { std::vector addrs; stringtok(addrs, spoofContent, " ,"); if (addrs.size() == 1) { + dnsdist::ResponseConfig config; try { ComboAddress spoofAddr(spoofContent); - SpoofAction tempSpoofAction({spoofAddr}); - tempSpoofAction(&dnsQuestion, &result); + dnsdist::self_answers::generateAnswerFromIPAddresses(dnsQuestion, {spoofAddr}, config); } catch (const PDNSException& e) { DNSName cname(spoofContent); - SpoofAction tempSpoofAction(cname); // CNAME then - tempSpoofAction(&dnsQuestion, &result); + dnsdist::self_answers::generateAnswerFromCNAME(dnsQuestion, cname, config); } } else { + dnsdist::ResponseConfig config; std::vector cas; for (const auto& addr : addrs) { try { @@ -860,18 +861,15 @@ static void spoofResponseFromString(DNSQuestion& dnsQuestion, const string& spoo catch (...) { } } - SpoofAction tempSpoofAction(cas); - tempSpoofAction(&dnsQuestion, &result); + dnsdist::self_answers::generateAnswerFromIPAddresses(dnsQuestion, cas, config); } } } static void spoofPacketFromString(DNSQuestion& dnsQuestion, const string& spoofContent) { - string result; - - SpoofAction tempSpoofAction(spoofContent.c_str(), spoofContent.size()); - tempSpoofAction(&dnsQuestion, &result); + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + dnsdist::self_answers::generateAnswerFromRawPacket(dnsQuestion, PacketBuffer(spoofContent.data(), spoofContent.data() + spoofContent.size())); } bool processRulesResult(const DNSAction::Action& action, DNSQuestion& dnsQuestion, std::string& ruleresult, bool& drop) diff --git a/pdns/dnsdistdist/test-dnsdist-lua-ffi.cc b/pdns/dnsdistdist/test-dnsdist-lua-ffi.cc index 3de6749da9..014764974a 100644 --- a/pdns/dnsdistdist/test-dnsdist-lua-ffi.cc +++ b/pdns/dnsdistdist/test-dnsdist-lua-ffi.cc @@ -59,6 +59,7 @@ BOOST_AUTO_TEST_CASE(test_Query) DNSQuestion dq(ids, query); dnsdist_ffi_dnsquestion_t lightDQ(&dq); + const auto initialData = dq.getData(); { // dnsdist_ffi_dnsquestion_get_qtype @@ -260,14 +261,15 @@ BOOST_AUTO_TEST_CASE(test_Query) } { -#if 0 - // SpoofAction::operator() is a stub in the test runner - auto oldData = dq.getData(); + dq.getMutableData() = initialData; + const auto oldData = dq.getData(); std::vector values; ComboAddress v4("192.0.2.1"); ComboAddress v6("[2001:db8::42]"); - values.push_back({ reinterpret_cast(&v4.sin4.sin_addr.s_addr), sizeof(v4.sin4.sin_addr.s_addr)}); - values.push_back({ reinterpret_cast(&v6.sin6.sin6_addr.s6_addr), sizeof(v6.sin6.sin6_addr.s6_addr)}); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + values.push_back({reinterpret_cast(&v4.sin4.sin_addr.s_addr), sizeof(v4.sin4.sin_addr.s_addr)}); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + values.push_back({reinterpret_cast(&v6.sin6.sin6_addr.s6_addr), sizeof(v6.sin6.sin6_addr.s6_addr)}); dnsdist_ffi_dnsquestion_spoof_addrs(&lightDQ, values.data(), values.size()); BOOST_CHECK(dq.getData().size() > oldData.size()); @@ -275,20 +277,17 @@ BOOST_AUTO_TEST_CASE(test_Query) MOADNSParser mdp(false, reinterpret_cast(dq.getData().data()), dq.getData().size()); BOOST_CHECK_EQUAL(mdp.d_qname, ids.qname); BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1U); - BOOST_CHECK_EQUAL(mdp.d_header.ancount, values.size()); + /* only the A has been added since the query was not ANY */ + BOOST_CHECK_EQUAL(mdp.d_header.ancount, 1U); BOOST_CHECK_EQUAL(mdp.d_header.nscount, 0U); BOOST_CHECK_EQUAL(mdp.d_header.arcount, 0U); BOOST_REQUIRE_EQUAL(mdp.d_answers.size(), 1U); - BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_type, static_cast(QType::A)); - BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_class, QClass::IN); - BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_name, ids.qname); - BOOST_CHECK_EQUAL(mdp.d_answers.at(1).first.d_type, static_cast(QType::AAAA)); - BOOST_CHECK_EQUAL(mdp.d_answers.at(1).first.d_class, QClass::IN); - BOOST_CHECK_EQUAL(mdp.d_answers.at(1).first.d_name, ids.qname); + BOOST_CHECK_EQUAL(mdp.d_answers.at(0).d_type, static_cast(QType::A)); + BOOST_CHECK_EQUAL(mdp.d_answers.at(0).d_class, QClass::IN); + BOOST_CHECK_EQUAL(mdp.d_answers.at(0).d_name, ids.qname); dq.getMutableData() = oldData; -#endif } { diff --git a/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc b/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc index e641dc6371..9cdaa0b2a6 100644 --- a/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc +++ b/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc @@ -42,11 +42,6 @@ void setLuaNoSideEffect() { } -DNSAction::Action SpoofAction::operator()(DNSQuestion* dnsQuestion, std::string* ruleresult) const -{ - return DNSAction::Action::None; -} - bool setupDoTProtocolNegotiation(std::shared_ptr& tlsCtx) { (void)tlsCtx;