From: Remi Gacogne Date: Sat, 2 Jul 2022 10:40:47 +0000 (+0200) Subject: dnsdist: Add a unit test for SetEDNSOptionAction with DO set X-Git-Tag: dnsdist-1.8.0-rc1~290^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3165970b7d2ce72de227bbc2962670cebab288bb;p=thirdparty%2Fpdns.git dnsdist: Add a unit test for SetEDNSOptionAction with DO set --- diff --git a/pdns/dnsdist-ecs.hh b/pdns/dnsdist-ecs.hh index 89e6237963..f64801ef0a 100644 --- a/pdns/dnsdist-ecs.hh +++ b/pdns/dnsdist-ecs.hh @@ -21,6 +21,13 @@ */ #pragma once +#include + +#include "iputils.hh" +#include "noinitvector.hh" + +class DNSQuestion; + // root label (1), type (2), class (2), ttl (4) + rdlen (2) static const size_t optRecordMinimumSize = 11; diff --git a/pdns/dnsdist-lua-actions.cc b/pdns/dnsdist-lua-actions.cc index 167baf36e3..4a7cc226f9 100644 --- a/pdns/dnsdist-lua-actions.cc +++ b/pdns/dnsdist-lua-actions.cc @@ -976,60 +976,42 @@ private: }; -class SetEDNSOptionAction : public DNSAction +DNSAction::Action SetEDNSOptionAction::operator()(DNSQuestion* dq, std::string* ruleresult) const { -public: - // this action does not stop the processing - SetEDNSOptionAction(uint16_t code, const std::string& data) : d_code(code), d_data(data) - { - } + std::string optRData; + generateEDNSOption(d_code, d_data, optRData); - DNSAction::Action operator()(DNSQuestion* dq, std::string* ruleresult) const override - { - std::string optRData; - generateEDNSOption(d_code, d_data, optRData); + if (dq->getHeader()->arcount) { + bool ednsAdded = false; + bool optionAdded = false; + PacketBuffer newContent; + newContent.reserve(dq->getData().size()); - if (dq->getHeader()->arcount) { - bool ednsAdded = false; - bool optionAdded = false; - PacketBuffer newContent; - newContent.reserve(dq->getData().size()); - - if (!slowRewriteEDNSOptionInQueryWithRecords(dq->getData(), newContent, ednsAdded, d_code, optionAdded, true, optRData)) { - return Action::None; - } - - if (newContent.size() > dq->getMaximumSize()) { - return Action::None; - } - - dq->getMutableData() = std::move(newContent); - if (!dq->ednsAdded && ednsAdded) { - dq->ednsAdded = true; - } + if (!slowRewriteEDNSOptionInQueryWithRecords(dq->getData(), newContent, ednsAdded, d_code, optionAdded, true, optRData)) { + return Action::None; + } + if (newContent.size() > dq->getMaximumSize()) { return Action::None; } - auto& data = dq->getMutableData(); - if (generateOptRR(optRData, data, dq->getMaximumSize(), g_EdnsUDPPayloadSize, 0, false)) { - dq->getHeader()->arcount = htons(1); - // make sure that any EDNS sent by the backend is removed before forwarding the response to the client + dq->getMutableData() = std::move(newContent); + if (!dq->ednsAdded && ednsAdded) { dq->ednsAdded = true; } return Action::None; } - std::string toString() const override - { - return "add EDNS Option (code=" + std::to_string(d_code) + ")"; + auto& data = dq->getMutableData(); + if (generateOptRR(optRData, data, dq->getMaximumSize(), g_EdnsUDPPayloadSize, 0, false)) { + dq->getHeader()->arcount = htons(1); + // make sure that any EDNS sent by the backend is removed before forwarding the response to the client + dq->ednsAdded = true; } -private: - uint16_t d_code; - std::string d_data; -}; + return Action::None; +} class SetNoRecurseAction : public DNSAction { diff --git a/pdns/dnsdist-lua.hh b/pdns/dnsdist-lua.hh index cf22e9163a..772e442483 100644 --- a/pdns/dnsdist-lua.hh +++ b/pdns/dnsdist-lua.hh @@ -21,6 +21,7 @@ */ #pragma once +#include "dnsdist.hh" #include "dnsparser.hh" #include @@ -129,6 +130,26 @@ private: uint32_t d_max{std::numeric_limits::max()}; }; +class SetEDNSOptionAction : public DNSAction +{ +public: + // this action does not stop the processing + SetEDNSOptionAction(uint16_t code, const std::string& data) : d_code(code), d_data(data) + { + } + + DNSAction::Action operator()(DNSQuestion* dq, std::string* ruleresult) const override; + + std::string toString() const override + { + return "add EDNS Option (code=" + std::to_string(d_code) + ")"; + } + +private: + uint16_t d_code; + std::string d_data; +}; + template using LuaArray = std::vector>; template using LuaAssociativeTable = std::unordered_map; template using LuaTypeOrArrayOf = boost::variant>; diff --git a/pdns/dnsdistdist/Makefile.am b/pdns/dnsdistdist/Makefile.am index 28b9d58707..504ed81e0e 100644 --- a/pdns/dnsdistdist/Makefile.am +++ b/pdns/dnsdistdist/Makefile.am @@ -245,6 +245,7 @@ testrunner_SOURCES = \ dnsdist-idstate.cc dnsdist-idstate.hh \ dnsdist-kvs.cc dnsdist-kvs.hh \ dnsdist-lbpolicies.cc dnsdist-lbpolicies.hh \ + dnsdist-lua-actions.cc \ dnsdist-lua-bindings-dnsquestion.cc \ dnsdist-lua-bindings-kvs.cc \ dnsdist-lua-bindings.cc \ @@ -294,6 +295,7 @@ testrunner_SOURCES = \ test-dnscrypt_cc.cc \ test-dnsdist-connections-cache.cc \ test-dnsdist_cc.cc \ + test-dnsdistactions_cc.cc \ test-dnsdistdynblocks_hh.cc \ test-dnsdistkvs_cc.cc \ test-dnsdistlbpolicies_cc.cc \ diff --git a/pdns/dnsdistdist/test-dnsdistactions_cc.cc b/pdns/dnsdistdist/test-dnsdistactions_cc.cc new file mode 100644 index 0000000000..f3184f9aa6 --- /dev/null +++ b/pdns/dnsdistdist/test-dnsdistactions_cc.cc @@ -0,0 +1,89 @@ +/* + * 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. + */ +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_NO_MAIN + +#include +#include + +#include "dnsdist-ecs.hh" +#include "dnsdist-lua.hh" +#include "dnswriter.hh" +#include "ednscookies.hh" + +BOOST_AUTO_TEST_SUITE(dnsdistluaaction_cc) + +BOOST_AUTO_TEST_CASE(test_SetEDNSOptionAction) { + DNSName qname("powerdns.com."); + uint16_t qtype = QType::A; + uint16_t qclass = QClass::IN; + ComboAddress lc("127.0.0.1:53"); + ComboAddress rem("192.0.2.1:42"); + auto proto = dnsdist::Protocol::DoUDP; + struct timespec queryRealTime; + gettime(&queryRealTime, true); + struct timespec expiredTime; + /* the internal QPS limiter does not use the real time */ + gettime(&expiredTime); + + PacketBuffer packet; + GenericDNSPacketWriter pw(packet, qname, qtype, qclass, 0); + pw.addOpt(4096, 0, EDNS_HEADER_FLAG_DO); + pw.commit(); + + DNSQuestion dq(&qname, qtype, qclass, &lc, &rem, packet, proto, &queryRealTime); + + std::string result; + EDNSCookiesOpt cookiesOpt("deadbeefdeadbeef"); + string cookiesOptionStr = cookiesOpt.makeOptString(); + + SetEDNSOptionAction seoa(EDNSOptionCode::COOKIE, cookiesOptionStr); + seoa(&dq, &result); + + const auto& data = dq.getData(); + MOADNSParser mdp(true, reinterpret_cast(data.data()), data.size()); + + BOOST_CHECK_EQUAL(mdp.d_qname.toString(), qname.toString()); + BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1U); + BOOST_CHECK_EQUAL(mdp.d_header.ancount, 0U); + BOOST_CHECK_EQUAL(mdp.d_header.nscount, 0U); + BOOST_CHECK_EQUAL(mdp.d_header.arcount, 1U); + BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_type, static_cast(QType::OPT)); + BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_name, g_rootdnsname); + + EDNS0Record edns0; + BOOST_REQUIRE(getEDNS0Record(dq, edns0)); + BOOST_CHECK_EQUAL(edns0.version, 0U); + BOOST_CHECK_EQUAL(edns0.extRCode, 0U); + BOOST_CHECK_EQUAL(edns0.extFlags, EDNS_HEADER_FLAG_DO); + + BOOST_REQUIRE(parseEDNSOptions(dq)); + BOOST_REQUIRE(dq.ednsOptions != nullptr); + BOOST_CHECK_EQUAL(dq.ednsOptions->size(), 1U); + const auto& ecsOption = dq.ednsOptions->find(EDNSOptionCode::COOKIE); + BOOST_REQUIRE(ecsOption != dq.ednsOptions->cend()); + + BOOST_REQUIRE_EQUAL(ecsOption->second.values.size(), 1U); + BOOST_CHECK_EQUAL(cookiesOptionStr, std::string(ecsOption->second.values.at(0).content, ecsOption->second.values.at(0).size)); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc b/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc index 9eee1cca51..83e79a0285 100644 --- a/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc +++ b/pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc @@ -88,11 +88,6 @@ void setLuaNoSideEffect() { } -DNSAction::Action SpoofAction::operator()(DNSQuestion* dq, std::string* ruleresult) const -{ - return DNSAction::Action::None; -} - bool setupDoTProtocolNegotiation(std::shared_ptr&) { return true;