]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec: Only check the netmask for subnet specific cache entries
authorRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 12 May 2017 12:12:10 +0000 (14:12 +0200)
committerPieter Lexis <pieter.lexis@powerdns.com>
Wed, 17 May 2017 08:10:41 +0000 (10:10 +0200)
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.

(cherry picked from commit 65fdd185f4930f685b87340d29535f40d8b52fb3)

pdns/recursor_cache.cc

index 08b6f61ed4d3d210779efa9626e91a2bdf08a504..d50dfd45b49f20589eee7621825361199bb006d1 100644 (file)
@@ -47,18 +47,11 @@ int MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, vec
   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: "<<i->d_netmask.toString()<<", query was for "<<who.toString()<<": match "<<i->d_netmask.match(who)<<endl;
-       haveSubnetSpecific=true;
-      }
-    }
     for(cache_t::const_iterator i=d_cachecache.first; i != d_cachecache.second; ++i)
       if(i->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;