]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Add a test and a fix a few things in getRecordCacheRecords/putIntoRecordCache
authorOtto Moerbeek <otto.moerbeek@open-xchange.com>
Mon, 21 Oct 2024 13:55:11 +0000 (15:55 +0200)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Thu, 24 Oct 2024 09:23:06 +0000 (11:23 +0200)
pdns/recursordist/lua-recursor4.cc
pdns/recursordist/recursor_cache.cc
pdns/recursordist/recursor_cache.hh
pdns/recursordist/test-recursorcache_cc.cc

index a3a7eec0e664ebfb9822de8b51d4617befa42026..b89d9ae3b6bc0e1771ba570f05472bd35c45e956 100644 (file)
@@ -19,8 +19,9 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
+#include <unordered_set>
+
 #include "lua-recursor4.hh"
-#include <fstream>
 #include "logger.hh"
 #include "logging.hh"
 #include "dnsparser.hh"
@@ -31,7 +32,6 @@
 #include "ednssubnet.hh"
 #include "filterpo.hh"
 #include "rec-snmp.hh"
-#include <unordered_set>
 #include "rec-main.hh"
 
 boost::optional<dnsheader> RecursorLua4::DNSQuestion::getDH() const
@@ -501,7 +501,7 @@ void RecursorLua4::postPrepareContext() // NOLINT(readability-function-cognitive
   });
 
   d_lw->writeFunction("putIntoRecordCache", [](const string& data) {
-    g_recCache->putRecords(data);
+    return g_recCache->putRecords(data);
   });
 
   d_lw->writeFunction("spawnThread", [](const string& scriptName) {
index 076c49ab975978b185689c5b27c0678027f91182..d3c05c22131ba7940ba6b1a5bf4a69e9ec903793 100644 (file)
@@ -569,7 +569,7 @@ bool MemRecursorCache::CacheEntry::shouldReplace(time_t now, bool auth, vState s
 
 bool MemRecursorCache::replace(CacheEntry&& entry)
 {
-  if (!entry.d_netmask.empty()) {
+  if (!entry.d_netmask.empty() || entry.d_rtag) {
     // We don't handle that yet
     return false;
   }
@@ -973,10 +973,22 @@ static void decodeComboAddress(protozero::pbf_message<T>& reader, ComboAddress&
   else {
     assert(0);
   }
+  constexpr auto inet4size = sizeof(address.sin4.sin_addr);
+  constexpr auto inet6size = sizeof(address.sin6.sin6_addr);
   if (message.next(PBComboAddress::required_bytes_address)) {
     auto data = message.get_bytes();
-    address.sin4.sin_family = data.size() == 4 ? AF_INET : AF_INET6;
-    memcpy(&address.sin4.sin_addr, data.data(), data.size());
+    address.sin4.sin_family = data.size() == inet4size ? AF_INET : AF_INET6;
+    if (data.size() == inet4size) {
+      address.sin4.sin_family = AF_INET;
+      memcpy(&address.sin4.sin_addr, data.data(), data.size());
+    }
+    else if (data.size() == inet6size) {
+      address.sin6.sin6_family = AF_INET6;
+      memcpy(&address.sin6.sin6_addr, data.data(), data.size());
+    }
+    else {
+      assert(0);
+    }
   }
   else {
     assert(0);
@@ -1171,10 +1183,10 @@ bool MemRecursorCache::putRecord(T& message)
       break;
     }
   }
-  return g_recCache->replace(std::move(cacheEntry));
+  return replace(std::move(cacheEntry));
 }
 
-void MemRecursorCache::putRecords(const std::string& pbuf)
+size_t MemRecursorCache::putRecords(const std::string& pbuf)
 {
   auto log = g_slog->withName("recordcache")->withValues("size", Logging::Loggable(pbuf.size()));
   log->info(Logr::Debug, "Processing cache dump");
@@ -1226,6 +1238,7 @@ void MemRecursorCache::putRecords(const std::string& pbuf)
       }
     }
     log->info(Logr::Info, "Processed cache dump", "processed", Logging::Loggable(count), "inserted", Logging::Loggable(inserted));
+    return inserted;
   }
   catch (const std::runtime_error& e) {
     log->error(Logr::Error, e.what(), "Runtime exception processing cache dump");
@@ -1236,6 +1249,7 @@ void MemRecursorCache::putRecords(const std::string& pbuf)
   catch (...) {
     log->error(Logr::Error, "Other exception processing cache dump");
   }
+  return 0;
 }
 
 namespace boost
index da12212f959c91a4a08983406ddb13d6fd3cd9f9..d9f3a94ddfaedec397ac605f679741c390ea3efd 100644 (file)
@@ -64,7 +64,7 @@ public:
   [[nodiscard]] size_t ecsIndexSize();
 
   void getRecords(size_t howmany, size_t maxsize, std::string& ret);
-  void putRecords(const std::string& pbuf);
+  size_t putRecords(const std::string& pbuf);
 
   using OptTag = boost::optional<std::string>;
 
index b2f99e2b9cce99fd5c40357982916a87fccfa9ba..8cdb545f6c8b404d5768ccfef1d3c0806c4ff589 100644 (file)
@@ -1287,4 +1287,100 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheTagged)
   }
 }
 
+BOOST_AUTO_TEST_CASE(test_RecursorCacheDumpAndRestore)
+{
+  MemRecursorCache::resetStaticsForTests();
+  MemRecursorCache MRC;
+
+  const DNSName authZone(".");
+  std::vector<std::shared_ptr<DNSRecord>> authRecords;
+  DNSRecord dr;
+  dr.d_place = DNSResourceRecord::ANSWER;
+  dr.d_name = DNSName("hi");
+  dr.d_type = QType::AAAA;
+  dr.d_ttl = 3600;
+  dr.setContent(std::make_shared<ARecordContent>(ComboAddress("1::2:3:4")));
+  authRecords.emplace_back(std::make_shared<DNSRecord>(dr));
+
+  std::vector<std::shared_ptr<const RRSIGRecordContent>> signatures;
+  signatures.emplace_back(std::dynamic_pointer_cast<RRSIGRecordContent>(RRSIGRecordContent::make("DNSKEY 8 0 172800 20241111000000 20241021000000 20326 . alCFgDZS+0l5zcpQ/7R+5OFeCrk9KGkNP2F9ynXIXG6QigPj/9qjm0xx ItRJUUim+SrJywAmLKe+48oTUeSRyDKVVg3LGDekLKcIVz0EBqTL2y44 usDlUlxqx5O0LQVHy4h/hm9+dCXFiSBWoV0LcAplV9OYWhxi+CxmxZU5 8vK6eVAde8E2JHdeDuy23WF5lxYEg1q7ehEt5EdRvZ7hZzfawEFR3Qv3 WMootO2eBAAneIe94daJP/i1iwQJ4p+bGVCZ4sJk+Pk9J7lwEQq6Ghkd SpLsRxArUhvoVgtnh0LkAV7TsajYk8K2JRt7wHNDbBV6+Vdq2bh7ZPGv LiGkIQ==")));
+
+  time_t now = time(nullptr);
+  time_t ttd = now + 30;
+
+  DNSName power("powerdns.com.");
+  DNSRecord dr0;
+  ComboAddress dr0Content("192.0.2.40");
+  dr0.d_name = power;
+  dr0.d_type = QType::A;
+  dr0.d_class = QClass::IN;
+  dr0.setContent(std::make_shared<ARecordContent>(dr0Content));
+  dr0.d_ttl = static_cast<uint32_t>(ttd);
+  dr0.d_place = DNSResourceRecord::ANSWER;
+  std::vector<DNSRecord> rset0;
+  rset0.push_back(dr0);
+
+  const ComboAddress nobody;
+  const ComboAddress somebody("::1");
+  const time_t ttl_time = 90;
+
+  auto checker = [&] {
+    const size_t expected = 100;
+
+    for (size_t counter = 0; counter < expected; ++counter) {
+      DNSName a = DNSName("hello ") + DNSName(std::to_string(counter));
+      BOOST_CHECK_EQUAL(DNSName(a.toString()), a);
+
+      MRC.replace(now, a, QType(QType::A), rset0, signatures, authRecords, true, authZone, boost::none, boost::none, vState::Insecure, somebody, false, ttl_time);
+    }
+
+    BOOST_CHECK_EQUAL(MRC.size(), expected);
+
+    size_t matches = 0;
+
+    for (size_t counter = 0; counter < expected + 10; counter++) {
+      std::vector<DNSRecord> retrieved;
+      std::vector<std::shared_ptr<DNSRecord>> authRecs;
+      std::vector<std::shared_ptr<const RRSIGRecordContent>> sigs;
+      bool variable = false;
+      vState state = vState::Indeterminate;
+      bool wasAuth = false;
+      DNSName fromZone;
+      ComboAddress from;
+      if (MRC.get(now, DNSName("hello ") + DNSName(std::to_string(counter)), QType(QType::A), MemRecursorCache::None, &retrieved, somebody, boost::none, &sigs, &authRecs, &variable, &state, &wasAuth, &fromZone, &from) > 0) {
+        matches++;
+        BOOST_CHECK_EQUAL(retrieved.size(), rset0.size());
+        BOOST_CHECK_EQUAL(getRR<ARecordContent>(retrieved.at(0))->getCA().toString(), dr0Content.toString());
+        BOOST_CHECK_EQUAL(sigs.size(), 1U);
+        BOOST_CHECK_EQUAL(sigs.at(0)->getZoneRepresentation(), signatures.at(0)->getZoneRepresentation());
+        BOOST_CHECK_EQUAL(authRecs.size(), 1U);
+
+        BOOST_CHECK_EQUAL(authRecs.at(0)->toString(), authRecords.at(0)->toString());
+        BOOST_CHECK_EQUAL(state, vState::Insecure);
+        BOOST_CHECK_EQUAL(wasAuth, true);
+        BOOST_CHECK_EQUAL(fromZone, authZone);
+        BOOST_CHECK_EQUAL(from.toString(), somebody.toString());
+      }
+    }
+    BOOST_CHECK_EQUAL(matches, expected);
+  };
+  try {
+    checker();
+
+    std::string dump;
+    MRC.getRecords(std::numeric_limits<size_t>::max(), std::numeric_limits<size_t>::max(), dump);
+    MRC.doWipeCache(DNSName("."), true);
+    BOOST_CHECK_EQUAL(MRC.size(), 0U);
+    size_t inserted = MRC.putRecords(dump);
+    BOOST_CHECK_EQUAL(inserted, 100U);
+    BOOST_CHECK_EQUAL(MRC.size(), 100U);
+
+    checker();
+  }
+  catch (const PDNSException& e) {
+    cerr << "Had error: " << e.reason << endl;
+    throw;
+  }
+}
+
 BOOST_AUTO_TEST_SUITE_END()