]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec: Backport of #10426 to rec-4.5.x: When refreshing, do not consider root almost... 10475/head
authorOtto <otto.moerbeek@open-xchange.com>
Mon, 7 Jun 2021 07:19:38 +0000 (09:19 +0200)
committerOtto <otto.moerbeek@open-xchange.com>
Mon, 7 Jun 2021 07:19:38 +0000 (09:19 +0200)
pdns/recursor_cache.cc
pdns/recursordist/Makefile.am
pdns/recursordist/test-syncres_cc.cc
pdns/recursordist/test-syncres_cc.hh
pdns/recursordist/test-syncres_cc2.cc

index c61076257c39602343cffd296cba1751ba28b00c..598f2260154a9fe47a07dcff6490ebca7a26cab7 100644 (file)
@@ -256,7 +256,7 @@ time_t MemRecursorCache::fakeTTD(MemRecursorCache::OrderedTagIterator_t& entry,
   if (ttl > 0 && SyncRes::s_refresh_ttlperc > 0) {
     const uint32_t deadline = origTTL * SyncRes::s_refresh_ttlperc / 100;
     const bool almostExpired = static_cast<uint32_t>(ttl) <= deadline;
-    if (almostExpired) {
+    if (almostExpired && qname != g_rootdnsname) {
       if (refresh) {
         return -1;
       } else {
index bd39f48fe504c7ced04192f7fc81430bda8be5fc..5de055d89abd2d8704c881d0bcb5b48ac3068ad5 100644 (file)
@@ -279,6 +279,7 @@ testrunner_SOURCES = \
        stable-bloom.hh \
        svc-records.cc svc-records.hh \
        syncres.cc syncres.hh \
+       taskqueue.cc taskqueue.hh \
        test-aggressive_nsec_cc.cc \
        test-arguments_cc.cc \
        test-base32_cc.cc \
index 385ea0946046b8019f9a691ed6d91ceb4dae3d44..8b6137f09896726b4ac56124dfbf6ed14250a3d3 100644 (file)
@@ -178,6 +178,7 @@ void initSR(bool debug)
   SyncRes::s_qnameminimization = false;
   SyncRes::s_nonresolvingnsmaxfails = 0;
   SyncRes::s_nonresolvingnsthrottletime = 0;
+  SyncRes::s_refresh_ttlperc = 0;
 
   SyncRes::clearNSSpeeds();
   BOOST_CHECK_EQUAL(SyncRes::getNSSpeedsSize(), 0U);
@@ -539,6 +540,9 @@ LWResult::Result basicRecordsForQnameMinimization(LWResult* res, const DNSName&
   return LWResult::Result::Timeout;
 }
 
+pdns::TaskQueue g_test_tasks;
+
 void pushTask(const DNSName& qname, uint16_t qtype, time_t deadline)
 {
+  g_test_tasks.push({qname, qtype, deadline, true});
 }
index 73b33d330d0d4078ef804bb3b7cf17967ed3964d..dbd05f7c9863c3a652f3ac7cdfe8a6b001df1b16 100644 (file)
@@ -28,6 +28,7 @@
 #include "syncres.hh"
 #include "test-common.hh"
 #include "validate-recursor.hh"
+#include "taskqueue.hh"
 
 extern GlobalStateHolder<LuaConfigItems> g_luaconfs;
 
@@ -69,3 +70,5 @@ void generateKeyMaterial(const DNSName& name, unsigned int algo, uint8_t digest,
 LWResult::Result genericDSAndDNSKEYHandler(LWResult* res, const DNSName& domain, DNSName auth, int type, const testkeysset_t& keys, bool proveCut = true, boost::optional<time_t> now = boost::none, bool nsec3 = false, bool optOut = false);
 
 LWResult::Result basicRecordsForQnameMinimization(LWResult* res, const DNSName& domain, int type);
+
+extern pdns::TaskQueue g_test_tasks;
index d5859d845fc290e28fd416460f0e61c745c15fe2..a4984df78cf2bf68a706c42d0308122d7d5bcf09 100644 (file)
@@ -2,6 +2,7 @@
 #include <boost/test/unit_test.hpp>
 
 #include "test-syncres_cc.hh"
+#include "rec-taskqueue.hh"
 
 BOOST_AUTO_TEST_SUITE(syncres_cc2)
 
@@ -1769,4 +1770,84 @@ BOOST_AUTO_TEST_CASE(test_cache_expired_ttl)
   BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toStringWithPort(), ComboAddress("192.0.2.2").toStringWithPort());
 }
 
+BOOST_AUTO_TEST_CASE(test_cache_almost_expired_ttl)
+{
+
+  std::unique_ptr<SyncRes> sr;
+  initSR(sr);
+  SyncRes::s_refresh_ttlperc = 50;
+  primeHints();
+
+  const DNSName target("powerdns.com.");
+
+  auto cb = [target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+    if (isRootServer(ip)) {
+      setLWResult(res, 0, false, false, true);
+      addRecordToLW(res, domain, QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
+
+      addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
+
+      return LWResult::Result::Success;
+    }
+    else if (ip == ComboAddress("192.0.2.1:53")) {
+      setLWResult(res, 0, true, false, true);
+      addRecordToLW(res, domain, QType::A, "192.0.2.2");
+      return LWResult::Result::Success;
+    }
+
+    return LWResult::Result::Timeout;
+  };
+  sr->setAsyncCallback(cb);
+
+  /* we populate the cache with an 60s TTL entry that is 31s old*/
+  const time_t now = sr->getNow().tv_sec;
+
+  std::vector<DNSRecord> records;
+  std::vector<shared_ptr<RRSIGRecordContent>> sigs;
+  addRecordToList(records, target, QType::A, "192.0.2.2", DNSResourceRecord::ANSWER, now + 29);
+
+  g_recCache->replace(now - 30, target, QType(QType::A), records, sigs, vector<std::shared_ptr<DNSRecord>>(), true, g_rootdnsname, boost::optional<Netmask>());
+
+  /* Same for the NS record */
+  std::vector<DNSRecord> ns;
+  addRecordToList(ns, target, QType::NS, "pdns-public-ns1.powerdns.com", DNSResourceRecord::ANSWER, now + 29);
+  g_recCache->replace(now - 30, target, QType::NS, ns, sigs, vector<std::shared_ptr<DNSRecord>>(), false, target, boost::optional<Netmask>());
+
+  vector<DNSRecord> ret;
+  int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+  BOOST_CHECK_EQUAL(res, RCode::NoError);
+  BOOST_REQUIRE_EQUAL(ret.size(), 1U);
+  BOOST_REQUIRE(ret[0].d_type == QType::A);
+  BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toStringWithPort(), ComboAddress("192.0.2.2").toStringWithPort());
+  auto ttl = ret[0].d_ttl;
+  BOOST_CHECK_EQUAL(ttl, 29U);
+
+  // One task should be submitted
+  BOOST_CHECK_EQUAL(g_test_tasks.size(), 1U);
+
+  auto task = g_test_tasks.pop();
+
+  // Refresh the almost expired record, its NS records also gets updated
+  sr->setRefreshAlmostExpired(task.d_refreshMode);
+  ret.clear();
+  res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
+  BOOST_CHECK_EQUAL(res, RCode::NoError);
+  BOOST_REQUIRE_EQUAL(ret.size(), 1U);
+  BOOST_REQUIRE(ret[0].d_type == QType::A);
+  BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toStringWithPort(), ComboAddress("192.0.2.2").toStringWithPort());
+  ttl = ret[0].d_ttl;
+  BOOST_CHECK_EQUAL(ttl, 60U);
+
+  // Also check if NS record was updated
+  ret.clear();
+  BOOST_REQUIRE_GT(g_recCache->get(now, target, QType(QType::NS), false, &ret, ComboAddress()), 0);
+  BOOST_REQUIRE_EQUAL(ret.size(), 1U);
+  BOOST_REQUIRE(ret[0].d_type == QType::NS);
+  BOOST_CHECK_EQUAL(getRR<NSRecordContent>(ret[0])->getNS(), DNSName("pdns-public-ns1.powerdns.com."));
+  ttl = ret[0].d_ttl - now;
+  BOOST_CHECK_EQUAL(ttl, std::min(SyncRes::s_maxcachettl, 172800U));
+
+  // ATM we are not testing the almost expiry of root infra records, it would require quite some cache massage...
+}
+
 BOOST_AUTO_TEST_SUITE_END()