]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Add a unit test for SetEDNSOptionAction with DO set
authorRemi Gacogne <remi.gacogne@powerdns.com>
Sat, 2 Jul 2022 10:40:47 +0000 (12:40 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Sat, 2 Jul 2022 12:17:54 +0000 (14:17 +0200)
pdns/dnsdist-ecs.hh
pdns/dnsdist-lua-actions.cc
pdns/dnsdist-lua.hh
pdns/dnsdistdist/Makefile.am
pdns/dnsdistdist/test-dnsdistactions_cc.cc [new file with mode: 0644]
pdns/dnsdistdist/test-dnsdistlbpolicies_cc.cc

index 89e6237963f81091bd4f74f19e5f440f337a93c8..f64801ef0a5aae9b42f199e1bb176855cd3ac32b 100644 (file)
  */
 #pragma once
 
+#include <string>
+
+#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;
 
index 167baf36e3dc774f68d601eb04aca7eb72aaeaea..4a7cc226f9309bbe67b180350a49b5692bf09c02 100644 (file)
@@ -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
 {
index cf22e9163aabb458193deee7d58972d3267c7dd4..772e4424834774a3f9a7a219c4c53f6d486b73ae 100644 (file)
@@ -21,6 +21,7 @@
  */
 #pragma once
 
+#include "dnsdist.hh"
 #include "dnsparser.hh"
 #include <random>
 
@@ -129,6 +130,26 @@ 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 28b9d587073e75e75ec4e030c7d2479f260d4076..504ed81e0eef5881b6af7870ef11752a3ea4766d 100644 (file)
@@ -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 (file)
index 0000000..f3184f9
--- /dev/null
@@ -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 <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 9eee1cca51b26699897f438f8a6f2c3f40ab7608..83e79a0285cacdcd12dd0cf60d2a6977f227e7bf 100644 (file)
@@ -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<TLSCtx>&)
 {
   return true;