From c4eb230a4b34af459e9380bf7ffd49639ada4c41 Mon Sep 17 00:00:00 2001 From: Otto Date: Wed, 7 Apr 2021 14:36:18 +0200 Subject: [PATCH] First check the cache for NS name to address contents for both v4 and v6 before going out This fixes #10263 here, but needs thorough reviewing and testing. --- pdns/recursordist/test-syncres_cc2.cc | 2 +- pdns/syncres.cc | 74 ++++++++++++++++++--------- 2 files changed, 50 insertions(+), 26 deletions(-) diff --git a/pdns/recursordist/test-syncres_cc2.cc b/pdns/recursordist/test-syncres_cc2.cc index d5859d845f..efa71b0848 100644 --- a/pdns/recursordist/test-syncres_cc2.cc +++ b/pdns/recursordist/test-syncres_cc2.cc @@ -56,7 +56,7 @@ static void do_test_referral_depth(bool limited) if (limited) { /* Set the maximum depth low */ - SyncRes::s_maxdepth = 4; + SyncRes::s_maxdepth = 3; try { vector ret; sr->beginResolve(target, QType(QType::A), QClass::IN, ret); diff --git a/pdns/syncres.cc b/pdns/syncres.cc index a2272726db..87329f9ac9 100644 --- a/pdns/syncres.cc +++ b/pdns/syncres.cc @@ -1074,40 +1074,64 @@ vector SyncRes::getAddrs(const DNSName &qname, unsigned int depth, d_followCNAME = true; try { - vState newState = vState::Indeterminate; - res_t resv4; - // If IPv4 ever becomes second class, we should revisit this - if (s_doIPv4 && doResolve(qname, QType::A, resv4, depth+1, beenthere, newState) == 0) { // this consults cache, OR goes out - for (auto const &i : resv4) { - if (i.d_type == QType::A) { + // First look for both A and AAAA in the cache and be satisfied if we find anything + res_t cset; + if (s_doIPv4 && g_recCache->get(d_now.tv_sec, qname, QType::A, false, &cset, d_cacheRemote, d_refresh, d_routingTag) > 0) { + for (const auto &i : cset) { + if (i.d_ttl > (unsigned int)d_now.tv_sec ) { if (auto rec = getRR(i)) { ret.push_back(rec->getCA(53)); } } } } - if (s_doIPv6) { // s_doIPv6 **IMPLIES** pdns::isQueryLocalAddressFamilyEnabled(AF_INET6) returned true - if (ret.empty()) { - // We did not find IPv4 addresses, try to get IPv6 ones - newState = vState::Indeterminate; - res_t resv6; - if (doResolve(qname, QType::AAAA, resv6, depth+1, beenthere, newState) == 0) { // this consults cache, OR goes out - for (const auto &i : resv6) { - if (i.d_type == QType::AAAA) { - if (auto rec = getRR(i)) - ret.push_back(rec->getCA(53)); + if (s_doIPv6 && g_recCache->get(d_now.tv_sec, qname, QType::AAAA, false, &cset, d_cacheRemote, d_refresh, d_routingTag) > 0) { + for (const auto &i : cset) { + if (i.d_ttl > (unsigned int)d_now.tv_sec ) { + if (auto rec = getRR(i)) { + ret.push_back(rec->getCA(53)); + } + } + } + } + if (ret.empty()) { + // Nothing in the cache... + vState newState = vState::Indeterminate; + cset.clear(); + // If IPv4 ever becomes second class, we should revisit this + if (s_doIPv4 && doResolve(qname, QType::A, cset, depth+1, beenthere, newState) == 0) { // this consults cache, OR goes out + for (auto const &i : cset) { + if (i.d_type == QType::A) { + if (auto rec = getRR(i)) { + ret.push_back(rec->getCA(53)); } } } - } else { - // We have some IPv4 records, don't bother with going out to get IPv6, but do consult the cache - // Once IPv6 adoption matters, this needs to be revisited - res_t cset; - if (g_recCache->get(d_now.tv_sec, qname, QType::AAAA, false, &cset, d_cacheRemote, d_refresh, d_routingTag) > 0) { - for (const auto &i : cset) { - if (i.d_ttl > (unsigned int)d_now.tv_sec ) { - if (auto rec = getRR(i)) { - ret.push_back(rec->getCA(53)); + } + if (s_doIPv6) { // s_doIPv6 **IMPLIES** pdns::isQueryLocalAddressFamilyEnabled(AF_INET6) returned true + if (ret.empty()) { + // We did not find IPv4 addresses, try to get IPv6 ones + newState = vState::Indeterminate; + cset.clear(); + if (doResolve(qname, QType::AAAA, cset, depth+1, beenthere, newState) == 0) { // this consults cache, OR goes out + for (const auto &i : cset) { + if (i.d_type == QType::AAAA) { + if (auto rec = getRR(i)) + ret.push_back(rec->getCA(53)); + } + } + } + } else { + // We have some IPv4 records, don't bother with going out to get IPv6, but do consult the cache, we might have + // encountered some v6 glue + // Once IPv6 adoption matters, this needs to be revisited + cset.clear(); + if (g_recCache->get(d_now.tv_sec, qname, QType::AAAA, false, &cset, d_cacheRemote, d_refresh, d_routingTag) > 0) { + for (const auto &i : cset) { + if (i.d_ttl > (unsigned int)d_now.tv_sec ) { + if (auto rec = getRR(i)) { + ret.push_back(rec->getCA(53)); + } } } } -- 2.47.2