]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
rec: Do not chase CNAME during qname minization step 4 9805/head
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 1 Dec 2020 09:52:37 +0000 (10:52 +0100)
committerOtto Moerbeek <otto.moerbeek@open-xchange.com>
Wed, 2 Dec 2020 15:19:23 +0000 (16:19 +0100)
(cherry picked from commit 7373cea835239f1b18a72000821bb17b516d954b)

pdns/syncres.cc
pdns/syncres.hh

index 527d17f1e5b7ce78ac0b6dd42f6653590951b326..6a9d8b7cc42465e1a6bf3ffa921e7d84d270cecb 100644 (file)
@@ -770,9 +770,12 @@ int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector<DNSRecor
 
       // Step 4
       QLOG("Step4 Resolve A for child");
+      bool oldFollowCNAME = d_followCNAME;
+      d_followCNAME = false;
       retq.resize(0);
       StopAtDelegation stopAtDelegation = Stop;
       res = doResolveNoQNameMinimization(child, QType::A, retq, depth, beenthere, state, NULL, &stopAtDelegation);
+      d_followCNAME = oldFollowCNAME;
       QLOG("Step4 Resolve A result is " << RCode::to_s(res) << "/" << retq.size() << "/" << stopAtDelegation);
       if (stopAtDelegation == Stopped) {
         QLOG("Delegation seen, continue at step 1");
@@ -1018,9 +1021,11 @@ vector<ComboAddress> SyncRes::getAddrs(const DNSName &qname, unsigned int depth,
   bool oldCacheOnly = setCacheOnly(cacheOnly);
   bool oldRequireAuthData = d_requireAuthData;
   bool oldValidationRequested = d_DNSSECValidationRequested;
+  bool oldFollowCNAME = d_followCNAME;
   const unsigned int startqueries = d_outqueries;
   d_requireAuthData = false;
   d_DNSSECValidationRequested = false;
+  d_followCNAME = true;
 
   try {
     vState newState = vState::Indeterminate;
@@ -1076,6 +1081,7 @@ vector<ComboAddress> SyncRes::getAddrs(const DNSName &qname, unsigned int depth,
   d_requireAuthData = oldRequireAuthData;
   d_DNSSECValidationRequested = oldValidationRequested;
   setCacheOnly(oldCacheOnly);
+  d_followCNAME = oldFollowCNAME;
 
   /* we need to remove from the nsSpeeds collection the existing IPs
      for this nameserver that are no longer in the set, even if there
@@ -1443,7 +1449,7 @@ bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector
       DNSName newTarget;
       if (foundQT == QType::DNAME) {
         if (qtype == QType::DNAME && qname == foundName) { // client wanted the DNAME, no need to synthesize a CNAME
-          res = 0;
+          res = RCode::NoError;
           return true;
         }
         // Synthesize a CNAME
@@ -1472,12 +1478,12 @@ bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector
       }
 
       if(qtype == QType::CNAME) { // perhaps they really wanted a CNAME!
-        res = 0;
+        res = RCode::NoError;
         return true;
       }
 
       if (qtype == QType::DS || qtype == QType::DNSKEY) {
-        res = 0;
+        res = RCode::NoError;
         return true;
       }
 
@@ -1504,6 +1510,11 @@ bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector
         setQNameMinimization(false);
       }
 
+      if (!d_followCNAME) {
+        res = RCode::NoError;
+        return true;
+      }
+
       // Check to see if we already have seen the new target as a previous target
       if (scanForCNAMELoop(newTarget, ret)) {
         string msg = "got a CNAME referral (from cache) that causes a loop";
@@ -3681,6 +3692,11 @@ void SyncRes::handleNewTarget(const std::string& prefix, const DNSName& qname, c
     return;
   }
 
+  if (!d_followCNAME) {
+    rcode = RCode::NoError;
+    return;
+  }
+
   // Check to see if we already have seen the new target as a previous target
   if (scanForCNAMELoop(newtarget, ret)) {
     LOG(prefix<<qname<<": status=got a CNAME referral that causes a loop, returning SERVFAIL"<<endl);
index 83de8d1ca2d04eac99d60b358123734c1bc66f16..f2e416e971dc53d6e0dd87d7c1df08318c448cf7 100644 (file)
@@ -914,6 +914,7 @@ private:
   bool d_wasVariable{false};
   bool d_qNameMinimization{false};
   bool d_queryReceivedOverTCP{false};
+  bool d_followCNAME{true};
 
   LogMode d_lm;
 };