From 2921f65db82e67494cc29437124b427d4938140b Mon Sep 17 00:00:00 2001 From: Otto Date: Mon, 7 Jun 2021 09:19:38 +0200 Subject: [PATCH] rec: Backport of #10426 to rec-4.5.x: When refreshing, do not consider root almost expired --- pdns/recursor_cache.cc | 2 +- pdns/recursordist/Makefile.am | 1 + pdns/recursordist/test-syncres_cc.cc | 4 ++ pdns/recursordist/test-syncres_cc.hh | 3 + pdns/recursordist/test-syncres_cc2.cc | 81 +++++++++++++++++++++++++++ 5 files changed, 90 insertions(+), 1 deletion(-) diff --git a/pdns/recursor_cache.cc b/pdns/recursor_cache.cc index c61076257c..598f226015 100644 --- a/pdns/recursor_cache.cc +++ b/pdns/recursor_cache.cc @@ -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(ttl) <= deadline; - if (almostExpired) { + if (almostExpired && qname != g_rootdnsname) { if (refresh) { return -1; } else { diff --git a/pdns/recursordist/Makefile.am b/pdns/recursordist/Makefile.am index bd39f48fe5..5de055d89a 100644 --- a/pdns/recursordist/Makefile.am +++ b/pdns/recursordist/Makefile.am @@ -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 \ diff --git a/pdns/recursordist/test-syncres_cc.cc b/pdns/recursordist/test-syncres_cc.cc index 385ea09460..8b6137f098 100644 --- a/pdns/recursordist/test-syncres_cc.cc +++ b/pdns/recursordist/test-syncres_cc.cc @@ -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}); } diff --git a/pdns/recursordist/test-syncres_cc.hh b/pdns/recursordist/test-syncres_cc.hh index 73b33d330d..dbd05f7c98 100644 --- a/pdns/recursordist/test-syncres_cc.hh +++ b/pdns/recursordist/test-syncres_cc.hh @@ -28,6 +28,7 @@ #include "syncres.hh" #include "test-common.hh" #include "validate-recursor.hh" +#include "taskqueue.hh" extern GlobalStateHolder 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 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; diff --git a/pdns/recursordist/test-syncres_cc2.cc b/pdns/recursordist/test-syncres_cc2.cc index d5859d845f..a4984df78c 100644 --- a/pdns/recursordist/test-syncres_cc2.cc +++ b/pdns/recursordist/test-syncres_cc2.cc @@ -2,6 +2,7 @@ #include #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(ret[0])->getCA().toStringWithPort(), ComboAddress("192.0.2.2").toStringWithPort()); } +BOOST_AUTO_TEST_CASE(test_cache_almost_expired_ttl) +{ + + std::unique_ptr 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& srcmask, boost::optional 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 records; + std::vector> 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>(), true, g_rootdnsname, boost::optional()); + + /* Same for the NS record */ + std::vector 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>(), false, target, boost::optional()); + + vector 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(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(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(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() -- 2.47.2