Changeset 117

Show
Ignore:
Timestamp:
01/05/03 23:09:24 (10 years ago)
Author:
ahu
Message:

recursorrr

Location:
trunk/pdns/pdns
Files:
5 modified

Legend:

Unmodified
Added
Removed
  • trunk/pdns/pdns/communicator.cc

    r115 r117  
    259259    } 
    260260    catch(ResolverException &re) { 
    261       L<<Logger::Error<<"Trying to retrieve/refresh '"+i->zone+"': "+re.reason<<endl; 
     261      L<<Logger::Error<<"Error trying to retrieve/refresh '"+i->zone+"': "+re.reason<<endl; 
    262262    } 
    263263  } 
  • trunk/pdns/pdns/docs/pdns.sgml

    r113 r117  
    11<!DOCTYPE Book PUBLIC "-//OASIS//DTD DocBook V4.1//EN"> 
    2  
    32<Book> 
    4    
    53  <BookInfo> 
    6      
    74    <Title>PowerDNS manual</Title> 
    85    <AUTHOR> 
     
    129          <email>pdns@powerdns.com</email> 
    1310        </address> 
    14          
    1511      </affiliation> 
    1612    </author> 
    1713     
    18     <PubDate>v2.1 $Date: 2003/01/03 18:00:12 $</PubDate> 
     14    <PubDate>v2.1 $Date: 2003/01/05 22:09:24 $</PubDate> 
    1915     
    2016    <Abstract> 
     
    37943790            </para></listitem> 
    37953791          <listitem><para> 
    3796               Has a broken algorithm. 
     3792              Does not expire entries from its cache 
    37973793            </para></listitem> 
    37983794          <listitem><para> 
    3799               Can get into a loop when resolving. 
    3800             </para></listitem> 
    3801           <listitem><para> 
    3802               Does not cache enough due to blatantly paranoid 'trust-rules', or more exactly 'no-trust' rules. 
     3795              Fakes the TTL of NS records in the additional section 
    38033796            </para></listitem> 
    38043797          <listitem><para> 
  • trunk/pdns/pdns/dynhandler.cc

    r93 r117  
    174174} 
    175175 
    176  
    177176string DLVersionHandler(const vector<string>&parts, Utility::pid_t ppid) 
    178177{ 
    179  
    180178  return VERSION; 
    181179} 
  • trunk/pdns/pdns/recns.cc

    r111 r117  
    100100 
    101101extern void init(void); 
    102 string doResolve(const string &qname, int depth=0); 
    103 string doResolve(vector<string> nameservers, const string &qname, int depth=0); 
    104  
     102 
     103bool beginResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret); 
    105104 
    106105void startDoResolve(void *p) 
    107106{ 
    108107  try { 
    109     cout<<"Passed: "<<p<<endl; 
    110108    DNSPacket P=*(DNSPacket *)p; 
    111109    delete (DNSPacket *)p; 
    112110     
    113     string ip=doResolve(P.qdomain); 
    114     cout<<"done: "<<ip<<endl; 
     111    vector<DNSResourceRecord>ret; 
    115112    DNSPacket *R=P.replyPacket(); 
    116     DNSResourceRecord rr; 
    117     rr.qname=P.qdomain; 
    118     rr.qtype=QType::A; 
    119     rr.content=ip; 
    120     rr.ttl=3600; 
    121     R->addRecord(rr); 
     113    if(!beginResolve(P.qdomain, P.qtype, ret)) 
     114      R->setRcode(RCode::ServFail); 
     115    else 
     116      for(vector<DNSResourceRecord>::const_iterator i=ret.begin();i!=ret.end();++i) 
     117        R->addRecord(*i); 
     118 
    122119    const char *buffer=R->getData(); 
    123120    sendto(d_sock,buffer,R->len,0,(struct sockaddr *)(R->remote),R->d_socklen); 
     121    delete R; 
    124122  } 
    125123  catch(AhuException &ae) { 
     
    202200      } 
    203201      else { 
    204         cout<<"new question for '"<<P.qdomain<<"'"<<endl; 
     202        cout<<"new question arrived for '"<<P.qdomain<<"|"<<P.qtype.getName()<<"'"<<endl; 
    205203        MT.makeThread(startDoResolve,(void*)new DNSPacket(P)); 
    206204      } 
  • trunk/pdns/pdns/syncres.cc

    r111 r117  
    2020#include <map> 
    2121#include <algorithm> 
     22#include <set> 
    2223 
    2324#include <cerrno> 
     
    3031#include "lwres.hh" 
    3132 
    32 typedef pair<vector<string>,vector<DNSResourceRecord> > CacheVal; 
    33 typedef multimap<string,CacheVal> cache_t; 
     33typedef map<string, set<string> > nscache_t; 
     34nscache_t nscache; 
     35 
     36typedef map<string,vector<DNSResourceRecord> > cache_t; 
    3437cache_t cache; 
    3538 
    3639vector<string>rootservers; 
    37 map<string,string> hints; 
    38  
    39 string doResolve(vector<string> nameservers, const string &qname, int depth=0); 
    40  
    41 string doResolve(const string &qname, int depth=0) 
    42 { 
    43   if(hints.find(toLower(qname))!=hints.end()) { 
    44     string prefix; 
    45     prefix.assign(3*depth, ' '); 
    46  
    47     cerr<<prefix<<qname<<": resolved via hint cache to "<<hints[toLower(qname)]<<endl; 
    48     return hints[toLower(qname)]; 
    49   } 
    50    
    51   return doResolve(rootservers, qname,depth); 
    52 } 
    53  
    54 string doResolve(vector<string> nameservers, const string &qname, int depth) 
     40 
     41 
     42bool doResolve(set<string> nameservers, string auth, const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret,int depth=0); 
     43bool doResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth=0); 
     44 
     45string getA(const string &qname, int depth=0) 
     46{ 
     47  vector<DNSResourceRecord> res; 
     48  string ret; 
     49 
     50  if(doResolve(qname,QType(QType::A), res,depth+1))  
     51    ret=res[0].content; 
     52 
     53  return ret; 
     54} 
     55 
     56void getBestNSFromCache(const string &qname, vector<DNSResourceRecord>&ret, int depth=0) 
     57{ 
     58  string prefix; 
     59  prefix.assign(3*depth, ' '); 
     60 
     61  vector<string>parts; 
     62  stringtok(parts,qname,".");  // www.us.powerdns.com -> 'www' 'us' 'powerdns' 'com' 
     63   
     64  unsigned int spos=0; 
     65  string subdomain; 
     66 
     67  while(spos<=parts.size()) { 
     68    if(spos<parts.size()) { // www.us.powerdns.com -> us.powerdns.com -> powerdns.com -> com -> 
     69      subdomain=parts[spos++]; 
     70      for(unsigned int i=spos;i<parts.size();++i) { 
     71        subdomain+="."; 
     72        subdomain+=parts[i]; 
     73      } 
     74    } 
     75    else { 
     76      subdomain=""; // ROOT! 
     77      spos++; 
     78    } 
     79    cout<<prefix<<qname<<": Checking if we have NS for '"<<subdomain<<"'"<<endl; 
     80    nscache_t::const_iterator j=nscache.find(toLower(subdomain)); 
     81    if(j!=nscache.end() && j->first==toLower(subdomain)) { 
     82      cout<<prefix<<qname<<": Adding authority records for '"<<subdomain<<"'"<<endl; 
     83      for(set<string>::const_iterator k=j->second.begin();k!=j->second.end();++k) { 
     84        DNSResourceRecord rr; 
     85        rr.qname=subdomain; 
     86        rr.content=*k; 
     87        rr.ttl=1234; 
     88        rr.qtype=QType(QType::NS); 
     89        rr.d_place=DNSResourceRecord::AUTHORITY; 
     90        ret.push_back(rr); 
     91      } 
     92      return; 
     93    } 
     94  } 
     95} 
     96 
     97 
     98 
     99void addCruft(const string &qname, vector<DNSResourceRecord>& ret) 
     100{ 
     101  getBestNSFromCache(qname,ret); 
     102   
     103  cout<<qname<<": Additional processing"<<endl; 
     104  vector<DNSResourceRecord> addit; 
     105  for(vector<DNSResourceRecord>::const_iterator k=ret.begin();k!=ret.end();++k)  
     106    if((k->d_place==DNSResourceRecord::ANSWER && k->qtype==QType(QType::MX)) ||  
     107       (k->d_place==DNSResourceRecord::AUTHORITY && k->qtype==QType(QType::NS))) { 
     108      cout<<qname<<": record '"<<k->content<<"|"<<k->qtype.getCode()<<"' needs an IP address"<<endl; 
     109      doResolve(k->content,QType(QType::A),addit,1); 
     110    } 
     111 
     112   
     113  for(vector<DNSResourceRecord>::iterator k=addit.begin();k!=addit.end();++k) { 
     114    k->d_place=DNSResourceRecord::ADDITIONAL; 
     115    ret.push_back(*k); 
     116  } 
     117} 
     118 
     119bool beginResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret) 
     120{ 
     121  bool res=doResolve(qname, qtype, ret,0); 
     122  if(res) 
     123    addCruft(qname, ret); 
     124  return res; 
     125} 
     126 
     127 
     128bool doResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth) 
     129{ 
     130  string prefix; 
     131  prefix.assign(3*depth, ' '); 
     132   
     133  // see if we have a CNAME hit 
     134  string tuple=toLower(qname)+"|CNAME"; 
     135  cout<<prefix<<"Looking for CNAME cache hit of '"<<tuple<<"'"<<endl; 
     136 
     137  cache_t::const_iterator i=cache.find(tuple); 
     138  if(i!=cache.end() && i->first==tuple) { // found it 
     139    cout<<prefix<<"Found cache CNAME hit for '"<<tuple<<"' to '"<<i->second.begin()->content<<"'"<<endl;     
     140    for(vector<DNSResourceRecord>::const_iterator j=i->second.begin();j!=i->second.end();++j) 
     141      ret.push_back(*j); 
     142    return doResolve(i->second.begin()->content, qtype, ret, depth); 
     143  } 
     144 
     145  tuple=toLower(qname)+"|"+qtype.getName(); 
     146  cout<<prefix<<"Looking for direct cache hit of '"<<tuple<<"'"<<endl; 
     147 
     148  i=cache.find(tuple); 
     149  if(i!=cache.end() && i->first==tuple) { // found it 
     150    cout<<prefix<<"Found cache hit for '"<<tuple<<"': "; 
     151    for(vector<DNSResourceRecord>::const_iterator j=i->second.begin();j!=i->second.end();++j) { 
     152      cout<<j->content<<" "; 
     153      ret.push_back(*j); 
     154    } 
     155    cout<<endl; 
     156    return true; 
     157  } 
     158 
     159   
     160  cout<<prefix<<"No cache hit for '"<<tuple<<"', trying to find an appropriate NS record"<<endl; 
     161  // bummer, get the best NS record then 
     162 
     163  vector<string>parts; 
     164  stringtok(parts,qname,".");  // www.us.powerdns.com -> 'www' 'us' 'powerdns' 'com' 
     165   
     166  unsigned int spos=0; 
     167  string subdomain; 
     168 
     169  while(spos<=parts.size()) { 
     170    if(spos<parts.size()) { // www.us.powerdns.com -> us.powerdns.com -> powerdns.com -> com -> 
     171      subdomain=parts[spos++]; 
     172      for(unsigned int i=spos;i<parts.size();++i) { 
     173        subdomain+="."; 
     174        subdomain+=parts[i]; 
     175      } 
     176    } 
     177    else { 
     178      subdomain=""; // ROOT! 
     179      spos++; 
     180    } 
     181    cout<<prefix<<qname<<": Checking if we have NS for '"<<subdomain<<"'"<<endl; 
     182    nscache_t::const_iterator j=nscache.find(toLower(subdomain)); 
     183    if(j!=nscache.end() && j->first==toLower(subdomain)) { 
     184      cout<<prefix<<"Found NS for '"<<subdomain<<"', heading there for further questions"<<endl; 
     185      bool hasResults=doResolve(j->second,subdomain,qname,qtype,ret,depth); 
     186      if(!hasResults) 
     187        continue; // perhaps less specific nameservers can help us 
     188 
     189      return true; 
     190    } 
     191  } 
     192  return false; 
     193} 
     194 
     195bool endsOn(const string &domain, const string &suffix)  
     196{ 
     197  if(domain==suffix || suffix.empty()) 
     198    return true; 
     199  if(domain.size()<suffix.size()) 
     200    return false; 
     201  return (domain.substr(domain.size()-suffix.size()-1,suffix.size()+1)=="."+suffix); 
     202} 
     203 
     204bool doResolve(set<string> nameservers, string auth, const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth) 
    55205{ 
    56206  string prefix; 
     
    60210  LWRes::res_t result; 
    61211  vector<DNSResourceRecord>usefulrrs; 
    62   vector<string> nsset;   
    63   cerr<<prefix<<qname<<": start of recursion!"<<endl; 
    64  
    65   for(;;) { 
     212  set<string> nsset;   
     213  cout<<prefix<<qname<<": start of recursion!"<<endl; 
     214 
     215 
     216  for(;;) { // we may get more specific nameservers 
    66217    result.clear(); 
    67218 
    68     for(cache_t::const_iterator i=cache.find(qname);i!=cache.end() && i->first==qname;++i) { 
    69       cerr<<prefix<<qname<<": potential cache hit!"<<endl; 
    70  
    71       sort(nameservers.begin(),nameservers.end()); 
    72       if(nameservers==i->second.first) { 
    73         cerr<<prefix<<qname<<": REAL cache hit, "<<i->second.second.size()<<" records"<<endl; 
    74         result=i->second.second; 
    75  
     219    vector<string>rnameservers; 
     220    for(set<string>::const_iterator i=nameservers.begin();i!=nameservers.end();++i) 
     221      rnameservers.push_back(*i); 
     222 
     223    random_shuffle(rnameservers.begin(),rnameservers.end()); 
     224    for(vector<string>::const_iterator i=rnameservers.begin();;++i){  
     225      if(i==rnameservers.end()) { 
     226        cout<<prefix<<qname<<": failed to resolve via any of the "<<rnameservers.size()<<" offered nameservers"<<endl; 
     227        return false; 
     228      } 
     229      cout<<prefix<<qname<<": trying to resolve nameserver "<<*i<<endl; 
     230      string remoteIP=getA(*i, depth+1); 
     231      if(remoteIP.empty()) { 
     232        cout<<prefix<<qname<<": failed to resolve nameserver "<<*i<<", trying next if available"<<endl; 
     233        continue; 
     234      } 
     235      cout<<prefix<<qname<<": resolved nameserver "<<*i<<" to "<<remoteIP<<endl; 
     236 
     237      if(r.asyncresolve(remoteIP,qname.c_str(),qtype.getCode())!=1) { // <- shouldn't this be internal? 
     238        cout<<prefix<<qname<<": error resolving"<<endl; 
     239      } 
     240      else { 
     241        result=r.result(); 
     242         
     243        cout<<prefix<<qname<<": got "<<result.size()<<" answers from "<<*i<<" ("<<remoteIP<<")"<<endl; 
    76244        break; 
    77245      } 
    78246    } 
    79     if(result.empty()) { 
    80  
    81       cerr<<prefix<<qname<<": no cache hit"<<endl; 
    82    
    83       random_shuffle(nameservers.begin(),nameservers.end()); 
    84       for(vector<string>::const_iterator i=nameservers.begin();;++i){  
    85         if(i==nameservers.end()) { 
    86           cerr<<prefix<<qname<<": failed to resolve via any of the "<<nameservers.size()<<" offered nameservers"<<endl; 
    87           return ""; 
    88         } 
    89         cerr<<prefix<<qname<<": trying to resolve nameserver "<<*i<<endl; 
    90         string remoteIP=doResolve(*i,depth+1); 
    91         if(remoteIP.empty()) { 
    92           cerr<<prefix<<qname<<": failed to resolve nameserver "<<*i<<", trying next if available"<<endl; 
    93           continue; 
    94         } 
    95         cerr<<prefix<<qname<<": resolved nameserver "<<*i<<" to "<<remoteIP<<endl; 
    96  
    97         if(r.asyncresolve(remoteIP,qname.c_str(),QType::A)!=1) { 
    98           cerr<<prefix<<qname<<": error resolving"<<endl; 
    99         } 
    100         else { 
    101           result=r.result(); 
    102            
    103           cerr<<prefix<<qname<<": got "<<result.size()<<" answers from "<<*i<<" ("<<remoteIP<<")"<<endl; 
    104           break; 
    105         } 
    106       } 
    107       usefulrrs.clear(); 
    108       for(LWRes::res_t::const_iterator i=result.begin();i!=result.end();++i)  
    109         if(i->d_place==DNSResourceRecord::ANSWER || (i->d_place==DNSResourceRecord::AUTHORITY && i->qtype.getCode()==QType::NS)) 
    110           usefulrrs.push_back(*i); 
     247 
     248 
     249    cache_t tcache; 
     250    // reap all answers from this packet that are acceptable 
     251    for(LWRes::res_t::const_iterator i=result.begin();i!=result.end();++i) { 
     252      cout<<prefix<<qname<<": accept answer '"<<i->qname<<"|"<<i->qtype.getName()<<"|"<<i->content<<"' from '"<<auth<<"' nameservers? "; 
     253      if(endsOn(i->qname, auth)) { 
     254        cout<<"YES!"<<endl; 
     255 
     256        if(i->qtype.getCode()==QType::NS) 
     257          nscache[toLower(i->qname)].insert(toLower(i->content)); 
     258        DNSResourceRecord rr=*i; 
     259        rr.d_place=DNSResourceRecord::ANSWER; 
     260        tcache[toLower(i->qname)+"|"+i->qtype.getName()].push_back(rr); 
     261      } 
     262      else 
     263        cout<<"NO!"<<endl; 
     264 
     265    } 
     266   
     267    for(cache_t::const_iterator i=tcache.begin();i!=tcache.end();++i) 
     268      cache[i->first]=i->second; 
     269     
     270    nsset.clear(); 
     271 
     272    for(LWRes::res_t::const_iterator i=result.begin();i!=result.end();++i) { 
    111273       
    112       if(!usefulrrs.empty()) { 
    113         CacheVal cv; 
    114         sort(nameservers.begin(),nameservers.end()); 
    115         cv.first=nameservers; 
    116         cv.second=usefulrrs; 
    117         cache.insert(make_pair(qname,cv)); 
    118       } 
    119     } 
    120  
    121     nsset.clear(); 
    122     for(LWRes::res_t::const_iterator i=result.begin();i!=result.end();++i) { 
    123       //    cerr<<prefix<<(int)i->d_place<<" "<<i->qname<<" "<<i->qtype.getName()<<" "<<i->content<<endl; 
    124274      if(i->d_place==DNSResourceRecord::ANSWER && i->qname==qname && i->qtype.getCode()==QType::CNAME) { 
    125         cerr<<prefix<<qname<<": got a CNAME referral, starting over with "<<i->content<<endl<<endl; 
    126         return doResolve(i->content, 0); 
    127       } 
    128       if(i->d_place==DNSResourceRecord::ANSWER && i->qname==qname && i->qtype.getCode()==QType::A) { 
    129         cerr<<prefix<<qname<<": resolved to "<<i->content<<endl; 
    130         return i->content; 
    131       } 
    132       if(i->d_place==DNSResourceRecord::AUTHORITY && i->qtype.getCode()==QType::NS) { 
    133         cerr<<prefix<<qname<<": got NS record "<<i->content<<endl; 
    134         nsset.push_back(i->content); 
    135       } 
     275        cout<<prefix<<qname<<": got a CNAME referral, starting over with "<<i->content<<endl<<endl; 
     276        ret.push_back(*i); 
     277        return doResolve(i->content, qtype, ret,0); 
     278      } 
     279      if(i->d_place==DNSResourceRecord::ANSWER && i->qname==qname && i->qtype==qtype) { 
     280        cout<<prefix<<qname<<": resolved to "<<i->content<<endl; 
     281        ret.push_back(*i); 
     282      } 
     283      if(i->d_place==DNSResourceRecord::AUTHORITY && i->qtype.getCode()==QType::NS) { // XXX FIXME check if suffix! 
     284        auth=i->qname; 
     285        cout<<prefix<<qname<<": got NS record "<<i->content<<endl; 
     286        nsset.insert(toLower(i->content)); 
     287      } 
     288    } 
     289    if(!ret.empty()){  
     290      cout<<prefix<<qname<<": got results, returning"<<endl; 
     291      return true; 
    136292    } 
    137293    if(nsset.empty()) { 
    138       cerr<<prefix<<qname<<": did not resolve "<<qname<<", did not get referral"<<endl; 
    139       return ""; 
    140     } 
    141  
    142     cerr<<prefix<<qname<<": did not resolve "<<qname<<", did get "<<nsset.size()<<" nameservers, looping to them"<<endl; 
     294      cout<<prefix<<qname<<": did not resolve "<<qname<<", did not get referral"<<endl; 
     295      return false; 
     296    } 
     297     
     298    cout<<prefix<<qname<<": did not resolve "<<qname<<", did get "<<nsset.size()<<" nameservers, looping to them"<<endl; 
    143299    nameservers=nsset; 
    144300  } 
     301  return false; 
    145302} 
    146303 
     
    151308                     "192.5.5.241", "192.112.36.4", "128.63.2.53", "192.36.148.17", 
    152309                     "198.41.0.10", "193.0.14.129", "198.32.64.12", "202.12.27.33"}; 
    153  
     310  DNSResourceRecord rr; 
     311  rr.qtype=QType::A; 
     312  rr.ttl=86400; 
    154313  for(char c='a';c<='m';++c) { 
    155314    static char templ[40]; 
    156315    strncpy(templ,"a.root-servers.net", sizeof(templ) - 1); 
    157316    *templ=c; 
    158     rootservers.push_back(templ); 
    159     hints[templ]=ips[c-'a']; 
    160   } 
    161 } 
     317    nscache[""].insert(string(templ)); 
     318    rr.qname=templ; 
     319    rr.content=ips[c-'a']; 
     320    cache[string(templ)+"|A"].push_back(rr); 
     321  } 
     322}