From a49442e929269883ef6582638c4af88734ec9566 Mon Sep 17 00:00:00 2001 From: Otto Moerbeek Date: Mon, 27 Oct 2025 12:21:16 +0100 Subject: [PATCH] Combine a few args to get() and replace() into struct Signed-off-by: Otto Moerbeek --- pdns/recursordist/recursor_cache.cc | 35 ++++++++++++---------- pdns/recursordist/recursor_cache.hh | 12 ++++++-- pdns/recursordist/reczones-helpers.cc | 6 ++-- pdns/recursordist/reczones.cc | 2 +- pdns/recursordist/syncres.cc | 16 ++++++---- pdns/recursordist/test-recursorcache_cc.cc | 18 ++++++----- 6 files changed, 55 insertions(+), 34 deletions(-) diff --git a/pdns/recursordist/recursor_cache.cc b/pdns/recursordist/recursor_cache.cc index 517cbba56b..5e2f5d7466 100644 --- a/pdns/recursordist/recursor_cache.cc +++ b/pdns/recursordist/recursor_cache.cc @@ -207,7 +207,7 @@ static void ptrAssign(T* ptr, const T& value) } } -time_t MemRecursorCache::handleHit(time_t now, MapCombo::LockedContent& content, OrderedTagIterator_t& entry, const DNSName& qname, uint32_t& origTTL, vector* res, SigRecs* signatures, AuthRecs* authorityRecs, bool* variable, boost::optional& state, bool* wasAuth, DNSName* fromAuthZone, ComboAddress* fromAuthIP, bool* tcp) +time_t MemRecursorCache::handleHit(time_t now, MapCombo::LockedContent& content, OrderedTagIterator_t& entry, const DNSName& qname, uint32_t& origTTL, vector* res, SigRecs* signatures, AuthRecs* authorityRecs, bool* variable, boost::optional& state, bool* wasAuth, DNSName* fromAuthZone, Extra* extra) { // MUTEX SHOULD BE ACQUIRED (as indicated by the reference to the content which is protected by a lock) if (entry->d_tooBig) { @@ -269,8 +269,10 @@ time_t MemRecursorCache::handleHit(time_t now, MapCombo::LockedContent& content, *wasAuth = *wasAuth && entry->d_auth; } ptrAssign(fromAuthZone, entry->d_authZone); - ptrAssign(fromAuthIP, entry->d_from); - ptrAssign(tcp, entry->d_tcp); + if (extra != nullptr) { + extra->d_address = entry->d_from; + extra->d_tcp = entry->d_tcp; + } moveCacheItemToBack(content.d_map, entry); @@ -428,7 +430,7 @@ time_t MemRecursorCache::fakeTTD(MemRecursorCache::OrderedTagIterator_t& entry, } // returns -1 for no hits -time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qtype, Flags flags, vector* res, const ComboAddress& who, const OptTag& routingTag, SigRecs* signatures, AuthRecs* authorityRecs, bool* variable, vState* state, bool* wasAuth, DNSName* fromAuthZone, ComboAddress* fromAuthIP, bool* tcp) // NOLINT(readability-function-cognitive-complexity) +time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qtype, Flags flags, vector* res, const ComboAddress& who, const OptTag& routingTag, SigRecs* signatures, AuthRecs* authorityRecs, bool* variable, vState* state, bool* wasAuth, DNSName* fromAuthZone, Extra* extra) // NOLINT(readability-function-cognitive-complexity) { bool requireAuth = (flags & RequireAuth) != 0; bool refresh = (flags & Refresh) != 0; @@ -456,11 +458,11 @@ time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qtype auto entryA = getEntryUsingECSIndex(*lockedShard, now, qname, QType::A, requireAuth, who, serveStale); if (entryA != lockedShard->d_map.end()) { - ret = handleHit(now, *lockedShard, entryA, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP, tcp); + ret = handleHit(now, *lockedShard, entryA, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, extra); } auto entryAAAA = getEntryUsingECSIndex(*lockedShard, now, qname, QType::AAAA, requireAuth, who, serveStale); if (entryAAAA != lockedShard->d_map.end()) { - time_t ttdAAAA = handleHit(now, *lockedShard, entryAAAA, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP, tcp); + time_t ttdAAAA = handleHit(now, *lockedShard, entryAAAA, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, extra); if (ret > 0) { ret = std::min(ret, ttdAAAA); } @@ -477,7 +479,7 @@ time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qtype } auto entry = getEntryUsingECSIndex(*lockedShard, now, qname, qtype, requireAuth, who, serveStale); if (entry != lockedShard->d_map.end()) { - time_t ret = handleHit(now, *lockedShard, entry, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP, tcp); + time_t ret = handleHit(now, *lockedShard, entry, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, extra); if (cachedState && ret > now) { ptrAssign(state, *cachedState); } @@ -509,7 +511,7 @@ time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qtype handleServeStaleBookkeeping(now, serveStale, firstIndexIterator); - ttd = handleHit(now, *lockedShard, firstIndexIterator, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP, tcp); + ttd = handleHit(now, *lockedShard, firstIndexIterator, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, extra); if (qtype == QType::ADDR && found == 2) { break; @@ -551,7 +553,7 @@ time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qtype handleServeStaleBookkeeping(now, serveStale, firstIndexIterator); - ttd = handleHit(now, *lockedShard, firstIndexIterator, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP, tcp); + ttd = handleHit(now, *lockedShard, firstIndexIterator, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, extra); if (qtype == QType::ADDR && found == 2) { break; @@ -631,14 +633,16 @@ bool MemRecursorCache::replace(CacheEntry&& entry) return false; } -void MemRecursorCache::replace(time_t now, const DNSName& qname, const QType qtype, const vector& content, const SigRecsVec& signatures, const AuthRecsVec& authorityRecs, bool auth, const DNSName& authZone, boost::optional ednsmask, const OptTag& routingTag, vState state, boost::optional from, bool overTCP, bool refresh, time_t ttl_time) +void MemRecursorCache::replace(time_t now, const DNSName& qname, const QType qtype, const vector& content, const SigRecsVec& signatures, const AuthRecsVec& authorityRecs, bool auth, const DNSName& authZone, const boost::optional& ednsmaskArg, const OptTag& routingTag, vState state, const boost::optional& extra, bool refresh, time_t ttl_time) { auto& shard = getMap(qname); auto lockedShard = shard.lock(); lockedShard->d_cachecachevalid = false; - if (ednsmask) { - ednsmask = ednsmask->getNormalized(); + + boost::optional ednsmask; + if (ednsmaskArg) { + ednsmask = ednsmaskArg->getNormalized(); } // We only store with a tag if we have an ednsmask and the tag is available @@ -705,11 +709,13 @@ void MemRecursorCache::replace(time_t now, const DNSName& qname, const QType qty } cacheEntry.d_records.clear(); cacheEntry.d_authZone = authZone; - if (from) { - cacheEntry.d_from = *from; + if (extra) { + cacheEntry.d_from = extra->d_address; + cacheEntry.d_tcp = extra->d_tcp; } else { cacheEntry.d_from = ComboAddress(); + cacheEntry.d_tcp = false; } size_t toStore = content.size(); @@ -745,7 +751,6 @@ void MemRecursorCache::replace(time_t now, const DNSName& qname, const QType qty } cacheEntry.d_submitted = false; cacheEntry.d_servedStale = 0; - cacheEntry.d_tcp = overTCP; lockedShard->d_map.replace(stored, cacheEntry); } diff --git a/pdns/recursordist/recursor_cache.hh b/pdns/recursordist/recursor_cache.hh index cd3a3f0621..595b8cde10 100644 --- a/pdns/recursordist/recursor_cache.hh +++ b/pdns/recursordist/recursor_cache.hh @@ -96,9 +96,15 @@ public: using SigRecs = std::shared_ptr; // Also const as it is shared const static SigRecs s_emptySigRecs; - [[nodiscard]] time_t get(time_t, const DNSName& qname, QType qtype, Flags flags, vector* res, const ComboAddress& who, const OptTag& routingTag = boost::none, SigRecs* signatures = nullptr, AuthRecs* authorityRecs = nullptr, bool* variable = nullptr, vState* state = nullptr, bool* wasAuth = nullptr, DNSName* fromAuthZone = nullptr, ComboAddress* fromAuthIP = nullptr, bool *tcp = nullptr); + struct Extra + { + ComboAddress d_address; + bool d_tcp{false}; + }; + + [[nodiscard]] time_t get(time_t, const DNSName& qname, QType qtype, Flags flags, vector* res, const ComboAddress& who, const OptTag& routingTag = boost::none, SigRecs* signatures = nullptr, AuthRecs* authorityRecs = nullptr, bool* variable = nullptr, vState* state = nullptr, bool* wasAuth = nullptr, DNSName* fromAuthZone = nullptr, Extra* extra = nullptr); - void replace(time_t, const DNSName& qname, QType qtype, const vector& content, const SigRecsVec& signatures, const AuthRecsVec& authorityRecs, bool auth, const DNSName& authZone, boost::optional ednsmask = boost::none, const OptTag& routingTag = boost::none, vState state = vState::Indeterminate, boost::optional from = boost::none, bool overTCP = false, bool refresh = false, time_t ttl_time = time(nullptr)); + void replace(time_t, const DNSName& qname, QType qtype, const vector& content, const SigRecsVec& signatures, const AuthRecsVec& authorityRecs, bool auth, const DNSName& authZone, const boost::optional& ednsmask = boost::none, const OptTag& routingTag = boost::none, vState state = vState::Indeterminate, const boost::optional& extra = boost::none, bool refresh = false, time_t ttl_time = time(nullptr)); void doPrune(time_t now, size_t keep); uint64_t doDump(int fileDesc, size_t maxCacheEntries); @@ -379,7 +385,7 @@ private: static Entries getEntries(MapCombo::LockedContent& map, const DNSName& qname, QType qtype, const OptTag& rtag); static cache_t::const_iterator getEntryUsingECSIndex(MapCombo::LockedContent& map, time_t now, const DNSName& qname, QType qtype, bool requireAuth, const ComboAddress& who, bool serveStale); - static time_t handleHit(time_t now, MapCombo::LockedContent& content, OrderedTagIterator_t& entry, const DNSName& qname, uint32_t& origTTL, vector* res, SigRecs* signatures, AuthRecs* authorityRecs, bool* variable, boost::optional& state, bool* wasAuth, DNSName* authZone, ComboAddress* fromAuthIP, bool* tcp); + static time_t handleHit(time_t now, MapCombo::LockedContent& content, OrderedTagIterator_t& entry, const DNSName& qname, uint32_t& origTTL, vector* res, SigRecs* signatures, AuthRecs* authorityRecs, bool* variable, boost::optional& state, bool* wasAuth, DNSName* authZone, Extra* extra); static void updateStaleEntry(time_t now, OrderedTagIterator_t& entry); static void handleServeStaleBookkeeping(time_t, bool, OrderedTagIterator_t&); }; diff --git a/pdns/recursordist/reczones-helpers.cc b/pdns/recursordist/reczones-helpers.cc index a0d61d8b7b..147d32f55f 100644 --- a/pdns/recursordist/reczones-helpers.cc +++ b/pdns/recursordist/reczones-helpers.cc @@ -41,7 +41,7 @@ static void putIntoCache(time_t now, QType qtype, vState state, const ComboAddre // Put non-default root hints into cache as authoritative. As argued below in // putDefaultHintsIntoCache, this is actually wrong, but people might depend on it by having // root-hints that refer to servers that aren't actually capable or willing to serve root data. - g_recCache->replace(now, name, qtype, aset, {}, {}, true, g_rootdnsname, boost::none, boost::none, state, from); + g_recCache->replace(now, name, qtype, aset, {}, {}, true, g_rootdnsname, boost::none, boost::none, state, MemRecursorCache::Extra{from, false}); } } @@ -158,11 +158,11 @@ void putDefaultHintsIntoCache(time_t now, std::vector& nsvec) * auth and will expire at the same time. A re-prime is then triggered, as before, when the * records were inserted with the auth bit set and the TTD comes. */ - g_recCache->replace(now, DNSName(templ), QType::A, {arr}, {}, {}, false, g_rootdnsname, boost::none, boost::none, vState::Insecure, from); + g_recCache->replace(now, DNSName(templ), QType::A, {arr}, {}, {}, false, g_rootdnsname, boost::none, boost::none, vState::Insecure, MemRecursorCache::Extra{from, false}); } if (!rootIps6.at(letter).empty()) { aaaarr.setContent(std::make_shared(ComboAddress(rootIps6.at(letter)))); - g_recCache->replace(now, DNSName(templ), QType::AAAA, {aaaarr}, {}, {}, false, g_rootdnsname, boost::none, boost::none, vState::Insecure, from); + g_recCache->replace(now, DNSName(templ), QType::AAAA, {aaaarr}, {}, {}, false, g_rootdnsname, boost::none, boost::none, vState::Insecure, MemRecursorCache::Extra{from, false}); } } } diff --git a/pdns/recursordist/reczones.cc b/pdns/recursordist/reczones.cc index dba5c5dcdd..745cad67b5 100644 --- a/pdns/recursordist/reczones.cc +++ b/pdns/recursordist/reczones.cc @@ -56,7 +56,7 @@ bool primeHints(time_t now) } g_recCache->doWipeCache(g_rootdnsname, false, QType::NS); - g_recCache->replace(now, g_rootdnsname, QType::NS, nsvec, {}, {}, false, g_rootdnsname, boost::none, boost::none, vState::Insecure, ComboAddress("255.255.255.255")); // and stuff in the cache + g_recCache->replace(now, g_rootdnsname, QType::NS, nsvec, {}, {}, false, g_rootdnsname, boost::none, boost::none, vState::Insecure, MemRecursorCache::Extra{ComboAddress("255.255.255.255"), false}); // and stuff in the cache return ret; } diff --git a/pdns/recursordist/syncres.cc b/pdns/recursordist/syncres.cc index a16317bb85..377ca68bee 100644 --- a/pdns/recursordist/syncres.cc +++ b/pdns/recursordist/syncres.cc @@ -2498,9 +2498,11 @@ bool SyncRes::doCNAMECacheCheck(const DNSName& qname, const QType qtype, vector< if (d_serveStale) { flags |= MemRecursorCache::ServeStale; } - if (g_recCache->get(d_now.tv_sec, qname, QType::CNAME, flags, &cset, d_cacheRemote, d_routingTag, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &context.state, &wasAuth, &authZone, &d_fromAuthIP) > 0) { + MemRecursorCache::Extra extra; + if (g_recCache->get(d_now.tv_sec, qname, QType::CNAME, flags, &cset, d_cacheRemote, d_routingTag, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &context.state, &wasAuth, &authZone, &extra) > 0) { foundName = qname; foundQT = QType::CNAME; + d_fromAuthIP = extra.d_address; } if (foundName.empty() && qname != g_rootdnsname) { @@ -2514,9 +2516,10 @@ bool SyncRes::doCNAMECacheCheck(const DNSName& qname, const QType qtype, vector< if (dnameName == qname && qtype != QType::DNAME) { // The client does not want a DNAME, but we've reached the QNAME already. So there is no match break; } - if (g_recCache->get(d_now.tv_sec, dnameName, QType::DNAME, flags, &cset, d_cacheRemote, d_routingTag, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &context.state, &wasAuth, &authZone, &d_fromAuthIP) > 0) { + if (g_recCache->get(d_now.tv_sec, dnameName, QType::DNAME, flags, &cset, d_cacheRemote, d_routingTag, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &context.state, &wasAuth, &authZone, &extra) > 0) { foundName = std::move(dnameName); foundQT = QType::DNAME; + d_fromAuthIP = extra.d_address; break; } } while (!labels.empty()); @@ -2938,7 +2941,10 @@ bool SyncRes::doCacheCheck(const DNSName& qname, const DNSName& authname, bool w if (d_refresh) { flags |= MemRecursorCache::Refresh; } - if (g_recCache->get(d_now.tv_sec, sqname, sqt, flags, &cset, d_cacheRemote, d_routingTag, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &cachedState, &wasCachedAuth, nullptr, &d_fromAuthIP) > 0) { + + MemRecursorCache::Extra extra; + if (g_recCache->get(d_now.tv_sec, sqname, sqt, flags, &cset, d_cacheRemote, d_routingTag, d_doDNSSEC ? &signatures : nullptr, d_doDNSSEC ? &authorityRecs : nullptr, &d_wasVariable, &cachedState, &wasCachedAuth, nullptr, &extra) > 0) { + d_fromAuthIP = extra.d_address; LOG(prefix << sqname << ": Found cache hit for " << sqt.toString() << ": "); @@ -4821,7 +4827,7 @@ RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, const string& thisRRNeedsWildcardProof = true; } } - g_recCache->replace(d_now.tv_sec, tCacheEntry->first.name, tCacheEntry->first.type, tCacheEntry->second.records, tCacheEntry->second.signatures, thisRRNeedsWildcardProof ? authorityRecs : *MemRecursorCache::s_emptyAuthRecs, tCacheEntry->first.type == QType::DS ? true : isAA, auth, tCacheEntry->first.place == DNSResourceRecord::ANSWER ? ednsmask : boost::none, d_routingTag, recordState, remoteIP, overTCP, d_refresh, tCacheEntry->second.d_ttl_time); + g_recCache->replace(d_now.tv_sec, tCacheEntry->first.name, tCacheEntry->first.type, tCacheEntry->second.records, tCacheEntry->second.signatures, thisRRNeedsWildcardProof ? authorityRecs : *MemRecursorCache::s_emptyAuthRecs, tCacheEntry->first.type == QType::DS ? true : isAA, auth, tCacheEntry->first.place == DNSResourceRecord::ANSWER ? ednsmask : boost::none, d_routingTag, recordState, MemRecursorCache::Extra{remoteIP, overTCP}, d_refresh, tCacheEntry->second.d_ttl_time); // Delete potential negcache entry. When a record recovers with serve-stale the negcache entry can cause the wrong entry to // be served, as negcache entries are checked before record cache entries @@ -4846,7 +4852,7 @@ RCode::rcodes_ SyncRes::updateCacheFromRecords(unsigned int depth, const string& content.push_back(std::move(nonExpandedRecord)); } - g_recCache->replace(d_now.tv_sec, realOwner, QType(tCacheEntry->first.type), content, tCacheEntry->second.signatures, /* no additional records in that case */ {}, tCacheEntry->first.type == QType::DS ? true : isAA, auth, boost::none, boost::none, recordState, remoteIP, overTCP, d_refresh, tCacheEntry->second.d_ttl_time); + g_recCache->replace(d_now.tv_sec, realOwner, QType(tCacheEntry->first.type), content, tCacheEntry->second.signatures, /* no additional records in that case */ {}, tCacheEntry->first.type == QType::DS ? true : isAA, auth, boost::none, boost::none, recordState, MemRecursorCache::Extra{remoteIP, overTCP}, d_refresh, tCacheEntry->second.d_ttl_time); } } } diff --git a/pdns/recursordist/test-recursorcache_cc.cc b/pdns/recursordist/test-recursorcache_cc.cc index 3c4ebf0fad..073beac613 100644 --- a/pdns/recursordist/test-recursorcache_cc.cc +++ b/pdns/recursordist/test-recursorcache_cc.cc @@ -1323,6 +1323,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheDumpAndRestore) const ComboAddress nobody; const ComboAddress somebody("::1"); + const MemRecursorCache::Extra authAddress{ComboAddress{"::2"}, true}; const time_t ttl_time = 90; auto checker = [&] { @@ -1332,7 +1333,7 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheDumpAndRestore) 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); + MRC.replace(now, a, QType(QType::A), rset0, signatures, authRecords, true, authZone, boost::none, boost::none, vState::Insecure, authAddress, false, ttl_time); } BOOST_CHECK_EQUAL(MRC.size(), expected); @@ -1347,8 +1348,8 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheDumpAndRestore) 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) { + MemRecursorCache::Extra extra; + 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, &extra) > 0) { matches++; BOOST_CHECK_EQUAL(retrieved.size(), rset0.size()); BOOST_CHECK_EQUAL(getRR(retrieved.at(0))->getCA().toString(), dr0Content.toString()); @@ -1360,7 +1361,8 @@ BOOST_AUTO_TEST_CASE(test_RecursorCacheDumpAndRestore) 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(extra.d_address.toString(), authAddress.d_address.toString()); + BOOST_CHECK(extra.d_tcp); } } BOOST_CHECK_EQUAL(matches, expected); @@ -1480,7 +1482,7 @@ struct RecordsSpeedTest 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); + MRC.replace(now, a, QType(QType::A), rset0, signatures, authRecords, true, authZone, boost::none, boost::none, vState::Insecure, MemRecursorCache::Extra{somebody, false}, false, ttl_time); } BOOST_CHECK_EQUAL(MRC.size(), expected); @@ -1497,8 +1499,10 @@ struct RecordsSpeedTest 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) { + MemRecursorCache::Extra extra; + 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, &extra) > 0) { + BOOST_CHECK_EQUAL(somebody.toString(), extra.d_address.toString()); + BOOST_CHECK(!extra.d_tcp); matches++; } } -- 2.47.3