]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Extract the logic in SetEDNSOptionAction into a separate function 11729/head
authorRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 10 Aug 2022 16:07:28 +0000 (18:07 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 10 Aug 2022 16:07:28 +0000 (18:07 +0200)
So that we can reuse and test it without linking issues.

pdns/dnsdist-ecs.cc
pdns/dnsdist-ecs.hh
pdns/dnsdist-lua-actions.cc
pdns/dnsdist-lua-bindings-dnsquestion.cc
pdns/dnsdist-lua.hh
pdns/dnsdistdist/Makefile.am
pdns/dnsdistdist/test-dnsdistactions_cc.cc [deleted file]
pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc
pdns/test-dnsdist_cc.cc
regression-tests.dnsdist/test_RulesActions.py

index 6fec7240c6f79b034ba920693b1102117b976fe5..b72ad197a0b26011092f038feb16058dc1307889 100644 (file)
@@ -1070,3 +1070,40 @@ bool getEDNS0Record(const DNSQuestion& dq, EDNS0Record& edns0)
   memcpy(&edns0, &packet.at(optStart + 5), sizeof edns0);
   return true;
 }
+
+bool setEDNSOption(DNSQuestion& dq, uint16_t ednsCode, const std::string& ednsData)
+{
+  std::string optRData;
+  generateEDNSOption(ednsCode, ednsData, optRData);
+
+  if (dq.getHeader()->arcount) {
+    bool ednsAdded = false;
+    bool optionAdded = false;
+    PacketBuffer newContent;
+    newContent.reserve(dq.getData().size());
+
+    if (!slowRewriteEDNSOptionInQueryWithRecords(dq.getData(), newContent, ednsAdded, ednsCode, optionAdded, true, optRData)) {
+      return false;
+    }
+
+    if (newContent.size() > dq.getMaximumSize()) {
+      return false;
+    }
+
+    dq.getMutableData() = std::move(newContent);
+    if (!dq.ednsAdded && ednsAdded) {
+      dq.ednsAdded = true;
+    }
+
+    return true;
+  }
+
+  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;
+  }
+
+  return true;
+}
index 707b25e4a7ff0613cc180f5842a76dbb50badb36..278536910d7e59b85cf575d98f174160f40ec61e 100644 (file)
@@ -55,3 +55,5 @@ bool parseEDNSOptions(const DNSQuestion& dq);
 int getEDNSZ(const DNSQuestion& dq);
 bool queryHasEDNS(const DNSQuestion& dq);
 bool getEDNS0Record(const DNSQuestion& dq, EDNS0Record& edns0);
+
+bool setEDNSOption(DNSQuestion& dq, uint16_t ednsCode, const std::string& data);
index 4a7cc226f9309bbe67b180350a49b5692bf09c02..4d3c3c62282a267194a7f19648471e0bec38f782 100644 (file)
@@ -975,43 +975,29 @@ private:
   uint16_t d_code{3};
 };
 
-
-DNSAction::Action SetEDNSOptionAction::operator()(DNSQuestion* dq, std::string* ruleresult) const
+class SetEDNSOptionAction : public DNSAction
 {
-  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 (!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;
-    }
+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
+  {
+    setEDNSOption(*dq, d_code, d_data);
     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->ednsAdded = true;
+  std::string toString() const override
+  {
+    return "add EDNS Option (code=" + std::to_string(d_code) + ")";
   }
 
-  return Action::None;
-}
+private:
+  uint16_t d_code;
+  std::string d_data;
+};
 
 class SetNoRecurseAction : public DNSAction
 {
index 18cb03d4eb5e446da024fba029a30cb86c88b225..d8c68ccaacab50a1194bd55edfd1ee34f3b32bf8 100644 (file)
@@ -181,9 +181,7 @@ void setupLuaBindingsDNSQuestion(LuaContext& luaCtx)
   });
 
   luaCtx.registerFunction<void(DNSQuestion::*)(uint16_t code, const std::string&)>("setEDNSOption", [](DNSQuestion& dq, uint16_t code, const std::string& data) {
-    std::string result;
-    SetEDNSOptionAction seoa(code, data);
-    seoa(&dq, &result);
+    setEDNSOption(dq, code, data);
   });
 
   /* LuaWrapper doesn't support inheritance */
index 772e4424834774a3f9a7a219c4c53f6d486b73ae..db344b0b272abeaf16adfa546f638cf63906594c 100644 (file)
@@ -130,26 +130,6 @@ private:
   uint32_t d_max{std::numeric_limits<uint32_t>::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 <class T> using LuaArray = std::vector<std::pair<int, T>>;
 template <class T> using LuaAssociativeTable = std::unordered_map<std::string, T>;
 template <class T> using LuaTypeOrArrayOf = boost::variant<T, LuaArray<T>>;
index 504ed81e0eef5881b6af7870ef11752a3ea4766d..28b9d587073e75e75ec4e030c7d2479f260d4076 100644 (file)
@@ -245,7 +245,6 @@ 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 \
@@ -295,7 +294,6 @@ 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
deleted file mode 100644 (file)
index aa3c29d..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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 <thread>
-#include <boost/test/unit_test.hpp>
-
-#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<PacketBuffer> 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<const char*>(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<uint16_t>(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()
index 83e79a0285cacdcd12dd0cf60d2a6977f227e7bf..9eee1cca51b26699897f438f8a6f2c3f40ab7608 100644 (file)
@@ -88,6 +88,11 @@ void setLuaNoSideEffect()
 {
 }
 
+DNSAction::Action SpoofAction::operator()(DNSQuestion* dq, std::string* ruleresult) const
+{
+  return DNSAction::Action::None;
+}
+
 bool setupDoTProtocolNegotiation(std::shared_ptr<TLSCtx>&)
 {
   return true;
index 8bf0e99b26c5960e6de3c5b7473fd7a2537293df..1b89fd1f27e4297bf5ad104f2ef088d4eeb460f3 100644 (file)
@@ -2080,4 +2080,58 @@ BOOST_AUTO_TEST_CASE(getEDNSOptionsWithoutEDNS) {
   }
 }
 
+BOOST_AUTO_TEST_CASE(test_setEDNSOption)
+{
+  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<PacketBuffer> 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();
+
+  BOOST_REQUIRE(setEDNSOption(dq, EDNSOptionCode::COOKIE, cookiesOptionStr));
+
+  const auto& data = dq.getData();
+  MOADNSParser mdp(true, reinterpret_cast<const char*>(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<uint16_t>(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();
index cbe2e42aede74fb78d595e172bb855d718b5520c..423089db3442bb77f229c1c9ef9a054b92004717 100644 (file)
@@ -1591,7 +1591,7 @@ class TestAdvancedSetEDNSOptionAction(DNSDistTest):
             self.assertTrue(receivedResponse)
             receivedQuery.id = expectedQuery.id
             self.assertEqual(expectedQuery, receivedQuery)
-            self.checkResponseNoEDNS(response, receivedResponse)
+            self.checkResponseEDNSWithoutECS(response, receivedResponse)
             self.checkQueryEDNS(expectedQuery, receivedQuery)
 
 class TestAdvancedLuaGetContent(DNSDistTest):