[Pdns-dev] Recursion Desired in pdns_recursor

Robert Bartl robert at edv-bartl.at
Fri Jan 16 23:30:14 CET 2009


Hello,

In our monitoring setup we need to forward DNS Queries to a number of 
backend Servers and also to a Server running dnscache, which doesnt like 
to be queried without the Recursion Desired Bit (the authoritative 
Server is not directly reachable).
I've changed the behaviour of the recursor to send queries with the rd 
bit set if configured, below is the patch.

It can be configured in forward-zones and forward-zones-file by 
prefixing the domainname with a "+" sign.

bye, robert.

------------------
Index: syncres.cc
===================================================================
--- syncres.cc  (revision 1324)
+++ syncres.cc  (working copy)
@@ -190,6 +190,7 @@
 int SyncRes::doResolve(const string &qname, const QType &qtype, 
vector<DNSResourceRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere)
 {
   string prefix;
+  int rd = 0;
   if(s_log) {
     prefix=d_prefix;
     prefix.append(depth, ' ');
@@ -242,7 +243,7 @@
   set<string, CIStringCompare> nsset;
   bool flawedNSSet=false;
   for(int tries=0;tries<2 && nsset.empty();++tries) {
-    subdomain=getBestNSNamesFromCache(subdomain, nsset, &flawedNSSet, 
depth, beenthere); //  pass beenthere to both occasions
+    subdomain=getBestNSNamesFromCache(subdomain, nsset, &flawedNSSet, 
depth, beenthere,rd); //  pass beenthere to both occasions

     if(nsset.empty()) { // must've lost root records
       LOG<<prefix<<qname<<": our root expired, repriming from hints and 
retrying"<<endl;
@@ -250,7 +251,7 @@
     }
   }

-  if(!(res=doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, 
ret, depth, beenthere)))
+  if(!(res=doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, 
ret, depth, beenthere,rd)))
     return 0;

   LOG<<prefix<<qname<<": failed (res="<<res<<")"<<endl;
@@ -368,7 +369,7 @@
 }

 /** doesn't actually do the work, leaves that to getBestNSFromCache */
-string SyncRes::getBestNSNamesFromCache(const string &qname, 
set<string, CIStringCompare>& nsset, bool* flawedNSSet, int depth, 
set<GetBestNSAnswer>&beenthere)
+string SyncRes::getBestNSNamesFromCache(const string &qname, 
set<string, CIStringCompare>& nsset, bool* flawedNSSet, int depth, 
set<GetBestNSAnswer>&beenthere, int &rd)
 {
   string subdomain(qname);
   string authdomain(qname);
@@ -379,7 +380,10 @@
       nsset.insert(string()); // this gets picked up in doResolveAt, if 
empty it means "we are auth", otherwise it denotes a forward
     else {
       for(vector<ComboAddress>::const_iterator 
server=iter->second.d_servers.begin(); server != 
iter->second.d_servers.end(); ++server)
-       nsset.insert(server->toStringWithPort());
+      {
+        if (iter->second.rd!=0) rd = 1;
+        nsset.insert(server->toStringWithPort());
+      }
     }

     return authdomain;
@@ -590,7 +594,7 @@
 /** returns -1 in case of no results, rcode otherwise */
 int SyncRes::doResolveAt(set<string, CIStringCompare> nameservers, 
string auth, bool flawedNSSet, const string &qname, const QType &qtype,
                         vector<DNSResourceRecord>&ret,
-                        int depth, set<GetBestNSAnswer>&beenthere)
+                        int depth, set<GetBestNSAnswer>&beenthere,int rd)
 {
   string prefix;
   if(s_log) {
@@ -688,7 +692,7 @@

            resolveret=asyncresolve(*remoteIP, qname,
                                    (qtype.getCode() == QType::ADDR ? 
QType::ANY : qtype.getCode()),
-                                   doTCP, d_doEDNS0, &d_now, &lwr);    
// <- we go out on the wire!
+                                   doTCP, d_doEDNS0, &d_now, 
&lwr,rd);    // <- we go out on the wire!
            if(resolveret != 1) {
              if(resolveret==0) {
                LOG<<prefix<<qname<<": timeout resolving "<< (doTCP ? 
"over TCP" : "")<<endl;
Index: syncres.hh
===================================================================
--- syncres.hh  (revision 1324)
+++ syncres.hh  (working copy)
@@ -327,6 +327,7 @@
   struct AuthDomain
   {
     vector<ComboAddress> d_servers;
+    int rd;
     typedef multi_index_container <
       DNSResourceRecord,
       indexed_by <
@@ -354,7 +355,7 @@
 private:
   struct GetBestNSAnswer;
   int doResolveAt(set<string, CIStringCompare> nameservers, string 
auth, bool flawedNSSet, const string &qname, const QType &qtype, 
vector<DNSResourceRecord>&ret,
-                 int depth, set<GetBestNSAnswer>&beenthere);
+                 int depth, set<GetBestNSAnswer>&beenthere,int rd=0);
   int doResolve(const string &qname, const QType &qtype, 
vector<DNSResourceRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere);
   bool doOOBResolve(const string &qname, const QType &qtype, 
vector<DNSResourceRecord>&ret, int depth, int &res);
   domainmap_t::const_iterator getBestAuthZone(string* qname);
@@ -362,7 +363,7 @@
   bool doCacheCheck(const string &qname, const QType &qtype, 
vector<DNSResourceRecord>&ret, int depth, int &res);
   void getBestNSFromCache(const string &qname, 
set<DNSResourceRecord>&bestns, bool* flawedNSSet, int depth, 
set<GetBestNSAnswer>& beenthere);
   void addCruft(const string &qname, vector<DNSResourceRecord>& ret);
-  string getBestNSNamesFromCache(const string &qname,set<string, 
CIStringCompare>& nsset, bool* flawedNSSet, int depth, 
set<GetBestNSAnswer>&beenthere);
+  string getBestNSNamesFromCache(const string &qname,set<string, 
CIStringCompare>& nsset, bool* flawedNSSet, int depth, 
set<GetBestNSAnswer>&beenthere, int &rd);
   void addAuthorityRecords(const string& qname, 
vector<DNSResourceRecord>& ret, int depth);

   inline vector<string> shuffleInSpeedOrder(set<string, 
CIStringCompare> &nameservers, const string &prefix);
Index: pdns_recursor.cc
===================================================================
--- pdns_recursor.cc    (revision 1324)
+++ pdns_recursor.cc    (working copy)
@@ -1515,6 +1515,12 @@
       pair<string,string> headers=splitField(*iter, '=');
       trim(headers.first);
       trim(headers.second);
+
+      if (headers.first[0] == '+')
+      {
+        headers.first = headers.first.substr(1);
+        ad.rd = 1;
+      }
       headers.first=toCanonic("", headers.first);
       if(n==0) {
        L<<Logger::Error<<"Parsing authoritative data for zone 
'"<<headers.first<<"' from file '"<<headers.second<<"'"<<endl;
@@ -1563,7 +1569,11 @@
       tie(domain, instructions)=splitField(line, '=');
       trim(domain);
       trim(instructions);
-
+      if (domain[0] == '+')
+      {
+       domain = domain.substr(1);
+       ad.rd = 1;
+      }
       if(domain.empty())
        throw AhuException("Error parsing line 
"+lexical_cast<string>(linenum)+" of " +::arg()["forward-zones-file"]);

Index: lwres.cc
===================================================================
--- lwres.cc    (revision 1324)
+++ lwres.cc    (working copy)
@@ -54,7 +54,7 @@

 //! returns -2 for OS limits error, -1 for permanent error that has to 
do with remote, 0 for timeout, 1 for success
 /** Never throws! */
-int asyncresolve(const ComboAddress& ip, const string& domain, int 
type, bool doTCP, bool doEDNS0, struct timeval* now, LWResult *lwr)
+int asyncresolve(const ComboAddress& ip, const string& domain, int 
type, bool doTCP, bool doEDNS0, struct timeval* now, LWResult *lwr, int rd)
 {
   int len;
   int bufsize=1500;
@@ -63,7 +63,7 @@
   //  string mapped0x20=dns0x20(domain);
   DNSPacketWriter pw(vpacket, domain, type);

-  pw.getHeader()->rd=0;
+  pw.getHeader()->rd=rd;
   pw.getHeader()->id=dns_random(0xffff);

   if(doEDNS0 && !doTCP) {



More information about the Pdns-dev mailing list