From afbe2787da5b1e290d5ecbc2a15aa90246775108 Mon Sep 17 00:00:00 2001 From: Bert Hubert Date: Sun, 5 Jan 2003 22:09:24 +0000 Subject: [PATCH] recursorrr git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@117 d19b8d6e-7fed-0310-83ef-9ca221ded41b --- pdns/communicator.cc | 2 +- pdns/docs/pdns.sgml | 13 +- pdns/dynhandler.cc | 2 - pdns/recns.cc | 22 ++- pdns/syncres.cc | 313 ++++++++++++++++++++++++++++++++----------- 5 files changed, 251 insertions(+), 101 deletions(-) diff --git a/pdns/communicator.cc b/pdns/communicator.cc index 518fa8643..4ee1caf70 100644 --- a/pdns/communicator.cc +++ b/pdns/communicator.cc @@ -258,7 +258,7 @@ void CommunicatorClass::slaveRefresh(PacketHandler *P) } } catch(ResolverException &re) { - L<zone+"': "+re.reason<zone+"': "+re.reason< - - - PowerDNS manual @@ -11,11 +8,10 @@
pdns@powerdns.com
-
- v2.1 $Date: 2003/01/03 18:00:12 $ + v2.1 $Date: 2003/01/05 22:09:24 $ @@ -3793,13 +3789,10 @@ local0.err /var/log/pdns.err Can only answer queries for types and classes it knows about - it is not transparent as it should be. - Has a broken algorithm. - - - Can get into a loop when resolving. + Does not expire entries from its cache - Does not cache enough due to blatantly paranoid 'trust-rules', or more exactly 'no-trust' rules. + Fakes the TTL of NS records in the additional section Only compiles on Linux and possibly Solaris. FreeBSD decided not to support the POSIX get/set/swapcontext functions. diff --git a/pdns/dynhandler.cc b/pdns/dynhandler.cc index cafa51ae8..71f1e11ff 100644 --- a/pdns/dynhandler.cc +++ b/pdns/dynhandler.cc @@ -173,10 +173,8 @@ string DLSettingsHandler(const vector&parts, Utility::pid_t ppid) } - string DLVersionHandler(const vector&parts, Utility::pid_t ppid) { - return VERSION; } diff --git a/pdns/recns.cc b/pdns/recns.cc index 7e35a5d9a..a25a25587 100644 --- a/pdns/recns.cc +++ b/pdns/recns.cc @@ -99,28 +99,26 @@ int arecvfrom(char *data, int len, int flags, struct sockaddr *toaddr, socklen_t extern void init(void); -string doResolve(const string &qname, int depth=0); -string doResolve(vector nameservers, const string &qname, int depth=0); +bool beginResolve(const string &qname, const QType &qtype, vector&ret); void startDoResolve(void *p) { try { - cout<<"Passed: "<ret; DNSPacket *R=P.replyPacket(); - DNSResourceRecord rr; - rr.qname=P.qdomain; - rr.qtype=QType::A; - rr.content=ip; - rr.ttl=3600; - R->addRecord(rr); + if(!beginResolve(P.qdomain, P.qtype, ret)) + R->setRcode(RCode::ServFail); + else + for(vector::const_iterator i=ret.begin();i!=ret.end();++i) + R->addRecord(*i); + const char *buffer=R->getData(); sendto(d_sock,buffer,R->len,0,(struct sockaddr *)(R->remote),R->d_socklen); + delete R; } catch(AhuException &ae) { cerr<<"startDoResolve timeout: "< #include #include +#include #include #include @@ -29,29 +30,178 @@ #include "arguments.hh" #include "lwres.hh" -typedef pair,vector > CacheVal; -typedef multimap cache_t; +typedef map > nscache_t; +nscache_t nscache; + +typedef map > cache_t; cache_t cache; vectorrootservers; -map hints; -string doResolve(vector nameservers, const string &qname, int depth=0); -string doResolve(const string &qname, int depth=0) +bool doResolve(set nameservers, string auth, const string &qname, const QType &qtype, vector&ret,int depth=0); +bool doResolve(const string &qname, const QType &qtype, vector&ret, int depth=0); + +string getA(const string &qname, int depth=0) +{ + vector res; + string ret; + + if(doResolve(qname,QType(QType::A), res,depth+1)) + ret=res[0].content; + + return ret; +} + +void getBestNSFromCache(const string &qname, vector&ret, int depth=0) { - if(hints.find(toLower(qname))!=hints.end()) { - string prefix; - prefix.assign(3*depth, ' '); + string prefix; + prefix.assign(3*depth, ' '); - cerr<parts; + stringtok(parts,qname,"."); // www.us.powerdns.com -> 'www' 'us' 'powerdns' 'com' + + unsigned int spos=0; + string subdomain; + + while(spos<=parts.size()) { + if(spos us.powerdns.com -> powerdns.com -> com -> + subdomain=parts[spos++]; + for(unsigned int i=spos;ifirst==toLower(subdomain)) { + cout<::const_iterator k=j->second.begin();k!=j->second.end();++k) { + DNSResourceRecord rr; + rr.qname=subdomain; + rr.content=*k; + rr.ttl=1234; + rr.qtype=QType(QType::NS); + rr.d_place=DNSResourceRecord::AUTHORITY; + ret.push_back(rr); + } + return; + } } +} + + + +void addCruft(const string &qname, vector& ret) +{ + getBestNSFromCache(qname,ret); + + cout< addit; + for(vector::const_iterator k=ret.begin();k!=ret.end();++k) + if((k->d_place==DNSResourceRecord::ANSWER && k->qtype==QType(QType::MX)) || + (k->d_place==DNSResourceRecord::AUTHORITY && k->qtype==QType(QType::NS))) { + cout<content<<"|"<qtype.getCode()<<"' needs an IP address"<content,QType(QType::A),addit,1); + } + - return doResolve(rootservers, qname,depth); + for(vector::iterator k=addit.begin();k!=addit.end();++k) { + k->d_place=DNSResourceRecord::ADDITIONAL; + ret.push_back(*k); + } +} + +bool beginResolve(const string &qname, const QType &qtype, vector&ret) +{ + bool res=doResolve(qname, qtype, ret,0); + if(res) + addCruft(qname, ret); + return res; } -string doResolve(vector nameservers, const string &qname, int depth) + +bool doResolve(const string &qname, const QType &qtype, vector&ret, int depth) +{ + string prefix; + prefix.assign(3*depth, ' '); + + // see if we have a CNAME hit + string tuple=toLower(qname)+"|CNAME"; + cout<first==tuple) { // found it + cout<second.begin()->content<<"'"<::const_iterator j=i->second.begin();j!=i->second.end();++j) + ret.push_back(*j); + return doResolve(i->second.begin()->content, qtype, ret, depth); + } + + tuple=toLower(qname)+"|"+qtype.getName(); + cout<first==tuple) { // found it + cout<::const_iterator j=i->second.begin();j!=i->second.end();++j) { + cout<content<<" "; + ret.push_back(*j); + } + cout<parts; + stringtok(parts,qname,"."); // www.us.powerdns.com -> 'www' 'us' 'powerdns' 'com' + + unsigned int spos=0; + string subdomain; + + while(spos<=parts.size()) { + if(spos us.powerdns.com -> powerdns.com -> com -> + subdomain=parts[spos++]; + for(unsigned int i=spos;ifirst==toLower(subdomain)) { + cout<second,subdomain,qname,qtype,ret,depth); + if(!hasResults) + continue; // perhaps less specific nameservers can help us + + return true; + } + } + return false; +} + +bool endsOn(const string &domain, const string &suffix) +{ + if(domain==suffix || suffix.empty()) + return true; + if(domain.size() nameservers, string auth, const string &qname, const QType &qtype, vector&ret, int depth) { string prefix; prefix.assign(3*depth, ' '); @@ -59,89 +209,96 @@ string doResolve(vector nameservers, const string &qname, int depth) LWRes r; LWRes::res_t result; vectorusefulrrs; - vector nsset; - cerr< nsset; + cout<first==qname;++i) { - cerr<rnameservers; + for(set::const_iterator i=nameservers.begin();i!=nameservers.end();++i) + rnameservers.push_back(*i); - sort(nameservers.begin(),nameservers.end()); - if(nameservers==i->second.first) { - cerr<second.second.size()<<" records"<second.second; + random_shuffle(rnameservers.begin(),rnameservers.end()); + for(vector::const_iterator i=rnameservers.begin();;++i){ + if(i==rnameservers.end()) { + cout<::const_iterator i=nameservers.begin();;++i){ - if(i==nameservers.end()) { - cerr<d_place==DNSResourceRecord::ANSWER || (i->d_place==DNSResourceRecord::AUTHORITY && i->qtype.getCode()==QType::NS)) - usefulrrs.push_back(*i); - - if(!usefulrrs.empty()) { - CacheVal cv; - sort(nameservers.begin(),nameservers.end()); - cv.first=nameservers; - cv.second=usefulrrs; - cache.insert(make_pair(qname,cv)); + + cache_t tcache; + // reap all answers from this packet that are acceptable + for(LWRes::res_t::const_iterator i=result.begin();i!=result.end();++i) { + cout<qname<<"|"<qtype.getName()<<"|"<content<<"' from '"<qname, auth)) { + cout<<"YES!"<qtype.getCode()==QType::NS) + nscache[toLower(i->qname)].insert(toLower(i->content)); + DNSResourceRecord rr=*i; + rr.d_place=DNSResourceRecord::ANSWER; + tcache[toLower(i->qname)+"|"+i->qtype.getName()].push_back(rr); } - } + else + cout<<"NO!"<first]=i->second; + nsset.clear(); + for(LWRes::res_t::const_iterator i=result.begin();i!=result.end();++i) { - // cerr<d_place<<" "<qname<<" "<qtype.getName()<<" "<content<d_place==DNSResourceRecord::ANSWER && i->qname==qname && i->qtype.getCode()==QType::CNAME) { - cerr<content<content, 0); + cout<content<content, qtype, ret,0); } - if(i->d_place==DNSResourceRecord::ANSWER && i->qname==qname && i->qtype.getCode()==QType::A) { - cerr<content<content; + if(i->d_place==DNSResourceRecord::ANSWER && i->qname==qname && i->qtype==qtype) { + cout<content<d_place==DNSResourceRecord::AUTHORITY && i->qtype.getCode()==QType::NS) { - cerr<content<content); + if(i->d_place==DNSResourceRecord::AUTHORITY && i->qtype.getCode()==QType::NS) { // XXX FIXME check if suffix! + auth=i->qname; + cout<content<content)); } } + if(!ret.empty()){ + cout<