From 65fdd185f4930f685b87340d29535f40d8b52fb3 Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Fri, 12 May 2017 14:12:10 +0200 Subject: [PATCH] rec: Only check the netmask for subnet specific cache entries We used to check the netmask for all entries for a qname if at least one of them was a subnet specific one. Since an empty `Netmask` doesn't match anything, we would effectively ignore every non subnet specific entries if we had at least one subnet specific one. This caused a very hard to reproduce issue with for example f.root-servers.net that includes an EDNS Client Subnet option in its answer for `NS .` if the query has an EDNS Client Subnet option. This caused the recursor to cache a subnet specific entry for `NS .`. When that entry expired, we retrieved and cached a non subnet specific one, but that new one was ignored as long as the subnet specific was not expunged from the cache. Under certain circumstances that could cause a root refresh loop using a lot of stack memory. --- pdns/recursor_cache.cc | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/pdns/recursor_cache.cc b/pdns/recursor_cache.cc index 9dcfe0c68f..b4995e44ab 100644 --- a/pdns/recursor_cache.cc +++ b/pdns/recursor_cache.cc @@ -50,18 +50,11 @@ int32_t MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, if(res) res->clear(); - bool haveSubnetSpecific=false; if(d_cachecache.first!=d_cachecache.second) { - for(cache_t::const_iterator i=d_cachecache.first; i != d_cachecache.second; ++i) { - if(!i->d_netmask.empty()) { - // cout<<"Had a subnet specific hit: "<d_netmask.toString()<<", query was for "<d_netmask.match(who)<d_ttd > now && ((i->d_qtype == qt.getCode() || qt.getCode()==QType::ANY || (qt.getCode()==QType::ADDR && (i->d_qtype == QType::A || i->d_qtype == QType::AAAA) )) - && (!haveSubnetSpecific || i->d_netmask.match(who))) + && (i->d_netmask.empty() || i->d_netmask.match(who))) ) { ttd = i->d_ttd; -- 2.47.2