From: Otto Moerbeek Date: Mon, 21 Oct 2024 13:55:11 +0000 (+0200) Subject: Add a test and a fix a few things in getRecordCacheRecords/putIntoRecordCache X-Git-Tag: rec-5.2.0-alpha1~12^2~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=df950c20c8afacd23c823a677526f6dfbd002c04;p=thirdparty%2Fpdns.git Add a test and a fix a few things in getRecordCacheRecords/putIntoRecordCache --- diff --git a/pdns/recursordist/lua-recursor4.cc b/pdns/recursordist/lua-recursor4.cc index a3a7eec0e6..b89d9ae3b6 100644 --- a/pdns/recursordist/lua-recursor4.cc +++ b/pdns/recursordist/lua-recursor4.cc @@ -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 + #include "lua-recursor4.hh" -#include #include "logger.hh" #include "logging.hh" #include "dnsparser.hh" @@ -31,7 +32,6 @@ #include "ednssubnet.hh" #include "filterpo.hh" #include "rec-snmp.hh" -#include #include "rec-main.hh" boost::optional 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) { diff --git a/pdns/recursordist/recursor_cache.cc b/pdns/recursordist/recursor_cache.cc index 076c49ab97..d3c05c2213 100644 --- a/pdns/recursordist/recursor_cache.cc +++ b/pdns/recursordist/recursor_cache.cc @@ -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& 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 diff --git a/pdns/recursordist/recursor_cache.hh b/pdns/recursordist/recursor_cache.hh index da12212f95..d9f3a94ddf 100644 --- a/pdns/recursordist/recursor_cache.hh +++ b/pdns/recursordist/recursor_cache.hh @@ -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; diff --git a/pdns/recursordist/test-recursorcache_cc.cc b/pdns/recursordist/test-recursorcache_cc.cc index b2f99e2b9c..8cdb545f6c 100644 --- a/pdns/recursordist/test-recursorcache_cc.cc +++ b/pdns/recursordist/test-recursorcache_cc.cc @@ -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> 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(ComboAddress("1::2:3:4"))); + authRecords.emplace_back(std::make_shared(dr)); + + std::vector> signatures; + signatures.emplace_back(std::dynamic_pointer_cast(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(dr0Content)); + dr0.d_ttl = static_cast(ttd); + dr0.d_place = DNSResourceRecord::ANSWER; + std::vector 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 retrieved; + std::vector> authRecs; + std::vector> 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(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::max(), std::numeric_limits::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()