Changeset 1117
- Timestamp:
- 12/29/07 15:38:57 (10 months ago)
- Files:
-
- trunk/pdns/pdns/lwres.cc (modified) (10 diffs)
- trunk/pdns/pdns/lwres.hh (modified) (2 diffs)
- trunk/pdns/pdns/syncres.cc (modified) (20 diffs)
- trunk/pdns/pdns/syncres.hh (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/pdns/pdns/lwres.cc
r923 r1117 1 1 /* 2 2 PowerDNS Versatile Database Driven Nameserver 3 Copyright (C) 2002 - 200 6PowerDNS.COM BV3 Copyright (C) 2002 - 2007 PowerDNS.COM BV 4 4 5 5 This program is free software; you can redistribute it and/or modify … … 37 37 #include "dnsparser.hh" 38 38 #include "logger.hh" 39 40 LWRes::LWRes() 41 { 42 d_sock=-1; 43 d_timeout=500000; 44 d_bufsize=1500; 45 d_buf = 0; 46 } 47 48 LWRes::~LWRes() 49 { 50 if(d_sock>=0) 51 Utility::closesocket(d_sock); 52 delete[] d_buf; 53 } 39 #include <boost/scoped_array.hpp> 54 40 55 41 //! returns -2 for OS limits error, -1 for permanent error that has to do with remote, 0 for timeout, 1 for success 56 42 /** Never throws! */ 57 int LWRes::asyncresolve(const ComboAddress& ip, const string& domain, int type, bool doTCP, struct timeval* now)43 int asyncresolve(const ComboAddress& ip, const string& domain, int type, bool doTCP, struct timeval* now, LWResult *lwr) 58 44 { 59 if(!d_buf) 60 d_buf=new unsigned char[d_bufsize]; 61 62 d_ip=ip; 45 int len; 46 int bufsize=1500; 47 scoped_array<unsigned char> buf(new unsigned char[bufsize]); 63 48 vector<uint8_t> vpacket; 64 49 DNSPacketWriter pw(vpacket, domain, type); … … 66 51 pw.getHeader()->rd=0; 67 52 pw.getHeader()->id=Utility::random(); 68 d_domain=domain; 69 d_type=type; 70 d_inaxfr=false; 71 d_rcode=0; 53 lwr->d_rcode=0; 72 54 73 55 int ret; … … 75 57 DTime dt; 76 58 dt.setTimeval(*now); 77 59 errno=0; 78 60 if(!doTCP) { 79 61 int queryfd; … … 88 70 // sleep until we see an answer to this, interface to mtasker 89 71 90 ret=arecvfrom(reinterpret_cast<char *>( d_buf), d_bufsize-1,0, ip, &d_len, pw.getHeader()->id,72 ret=arecvfrom(reinterpret_cast<char *>(buf.get()), bufsize-1,0, ip, &len, pw.getHeader()->id, 91 73 domain, type, queryfd, now->tv_sec); 92 74 } … … 100 82 s.connect(ie); 101 83 102 uint16_t len=htons(vpacket.size());103 char *lenP=(char*)& len;84 uint16_t tlen=htons(vpacket.size()); 85 char *lenP=(char*)&tlen; 104 86 const char *msgP=(const char*)&*vpacket.begin(); 105 87 string packet=string(lenP, lenP+2)+string(msgP, msgP+vpacket.size()); … … 114 96 return ret; 115 97 116 memcpy(& len, packet.c_str(), 2);117 len=ntohs( len);98 memcpy(&tlen, packet.c_str(), 2); 99 len=ntohs(tlen); // switch to the 'len' shared with the rest of the function 118 100 119 101 ret=arecvtcp(packet, len, &s); … … 121 103 return ret; 122 104 123 if(len > d_bufsize) { 124 // cerr<<"Reallocating to "<<len<<" bytes ("<<packet.size()<<")\n"; 125 d_bufsize=len; 126 delete[] d_buf; 127 d_buf = new unsigned char[d_bufsize]; 105 if(len > bufsize) { 106 bufsize=len; 107 scoped_array<unsigned char> narray(new unsigned char[bufsize]); 108 buf.swap(narray); 128 109 } 129 memcpy( d_buf, packet.c_str(), len);130 d_len=len; 110 memcpy(buf.get(), packet.c_str(), len); 111 131 112 ret=1; 132 113 } … … 136 117 } 137 118 138 d_usec=dt.udiff(); 119 if(ret <= 0) // includes 'timeout' 120 return ret; 121 122 lwr->d_usec=dt.udiff(); 139 123 *now=dt.getTimeval(); 140 return ret; 141 } 142 143 144 LWRes::res_t LWRes::result() 145 { 124 lwr->d_result.clear(); 146 125 try { 147 MOADNSParser mdp((const char*)d_buf, d_len); 148 // if(p.parse((char *)d_buf, d_len)<0) 149 // throw LWResException("resolver: unable to parse packet of "+itoa(d_len)+" bytes"); 150 d_aabit=mdp.d_header.aa; 151 d_tcbit=mdp.d_header.tc; 152 d_rcode=mdp.d_header.rcode; 153 154 if(Utility::strcasecmp(d_domain.c_str(), mdp.d_qname.c_str())) { 155 if(d_domain.find((char)0)==string::npos) {// embedded nulls are too noisy 156 L<<Logger::Notice<<"Packet purporting to come from remote server "<<d_ip.toString()<<" contained wrong answer: '" << d_domain << "' != '" << mdp.d_qname << "'" << endl; 126 MOADNSParser mdp((const char*)buf.get(), len); 127 lwr->d_aabit=mdp.d_header.aa; 128 lwr->d_tcbit=mdp.d_header.tc; 129 lwr->d_rcode=mdp.d_header.rcode; 130 131 if(Utility::strcasecmp(domain.c_str(), mdp.d_qname.c_str())) { 132 if(domain.find((char)0)==string::npos) {// embedded nulls are too noisy 133 L<<Logger::Notice<<"Packet purporting to come from remote server "<<ip.toString()<<" contained wrong answer: '" << domain << "' != '" << mdp.d_qname << "'" << endl; 157 134 g_stats.unexpectedCount++; 158 135 } 159 136 goto out; 160 137 } 161 162 LWRes::res_t ret; 138 163 139 for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) { 164 // cout<<i->first.d_place<<"\t"<<i->first.d_label<<"\tIN\t"<<DNSRecordContent::NumberToType(i->first.d_type);165 // cout<<"\t"<<i->first.d_ttl<<"\t"<< i->first.d_content->getZoneRepresentation()<<endl;166 140 DNSResourceRecord rr; 167 141 rr.qtype=i->first.d_type; … … 170 144 rr.content=i->first.d_content->getZoneRepresentation(); // this should be the serialised form 171 145 rr.d_place=(DNSResourceRecord::Place) i->first.d_place; 172 ret.push_back(rr);146 lwr->d_result.push_back(rr); 173 147 } 174 175 return ret; 176 // return p.getAnswers(); 148 149 return 1; 177 150 } 178 151 catch(exception &mde) { 179 152 if(::arg().mustDo("log-common-errors")) 180 L<<Logger::Notice<<"Unable to parse packet from remote server "<< d_ip.toString()<<": "<<mde.what()<<endl;153 L<<Logger::Notice<<"Unable to parse packet from remote server "<<ip.toString()<<": "<<mde.what()<<endl; 181 154 } 182 155 catch(...) { 183 156 L<<Logger::Notice<<"Unknown error parsing packet from remote server"<<endl; 184 157 } 158 159 g_stats.serverParseError++; 160 161 out: 162 lwr->d_rcode=RCode::ServFail; 185 163 186 g_stats.serverParseError++; 187 188 out: 189 d_rcode=RCode::ServFail; 190 LWRes::res_t empty; 191 return empty; 164 return -1; 192 165 } 193 166 167 trunk/pdns/pdns/lwres.hh
r853 r1117 1 1 /* 2 2 PowerDNS Versatile Database Driven Nameserver 3 Copyright (C) 2002 - 200 5PowerDNS.COM BV3 Copyright (C) 2002 - 2007 PowerDNS.COM BV 4 4 5 5 This program is free software; you can redistribute it and/or modify … … 53 53 54 54 //! LWRes class 55 class LWRes 55 class LWResult 56 56 { 57 57 public: 58 LWRes();59 ~LWRes();60 string i;61 62 58 typedef vector<DNSResourceRecord> res_t; 63 59 64 int asyncresolve(const ComboAddress& ip, const string& domain, int type, bool doTCP, struct timeval* now); 65 vector<DNSResourceRecord> result(); 60 vector<DNSResourceRecord> d_result; 66 61 int d_rcode; 67 62 bool d_aabit, d_tcbit; 68 63 uint32_t d_usec; 69 private:70 int d_sock;71 unsigned char *d_buf;72 int getLength();73 int d_len;74 int d_soacount;75 string d_domain;76 int d_type;77 int d_timeout;78 ComboAddress d_ip;79 bool d_inaxfr;80 int d_bufsize;81 64 }; 82 65 66 int asyncresolve(const ComboAddress& ip, const string& domain, int type, bool doTCP, struct timeval* now, LWResult* res); 67 83 68 #endif // PDNS_LWRES_HH trunk/pdns/pdns/syncres.cc
r923 r1117 1 1 /* 2 2 PowerDNS Versatile Database Driven Nameserver 3 Copyright (C) 2003 - 200 6PowerDNS.COM BV3 Copyright (C) 2003 - 2007 PowerDNS.COM BV 4 4 5 5 This program is free software; you can redistribute it and/or modify … … 198 198 if(!(d_nocache && qtype.getCode()==QType::NS && qname==".")) { 199 199 if(d_cacheonly) { // very limited OOB support 200 LWResult lwr; 200 201 LOG<<prefix<<qname<<": Recursion not requested for '"<<qname<<"|"<<qtype.getName()<<"', peeking at auth/forward zones"<<endl; 201 202 string authname(qname); … … 204 205 string server=iter->second.d_server; 205 206 if(server.empty()) { 206 LWRes::res_t result;207 207 ret.clear(); 208 208 doOOBResolve(qname, qtype, ret, depth, res); … … 212 212 LOG<<prefix<<qname<<": forwarding query to hardcoded nameserver '"<<server<<"' for zone '"<<authname<<"'"<<endl; 213 213 ComboAddress remoteIP(server, 53); 214 res=d_lwr.asyncresolve(remoteIP, qname, qtype.getCode(), false, &d_now); 215 // filter out the good stuff from d_lwr.result()216 LWRes::res_t result=d_lwr.result();217 218 for(LWRes ::res_t::const_iterator i=result.begin();i!=result.end();++i) {214 215 res=asyncresolve(remoteIP, qname, qtype.getCode(), false, &d_now, &lwr); 216 // filter out the good stuff from lwr.result() 217 218 for(LWResult::res_t::const_iterator i=lwr.d_result.begin();i!=lwr.d_result.end();++i) { 219 219 if(i->d_place == DNSResourceRecord::ANSWER) 220 220 ret.push_back(*i); … … 599 599 } 600 600 601 LWRes ::res_t result;601 LWResult::res_t result; 602 602 603 603 LOG<<prefix<<qname<<": Cache consultations done, have "<<(unsigned int)nameservers.size()<<" NS to contact"<<endl; … … 629 629 int resolveret; 630 630 631 LWResult lwr; 631 632 if(tns->empty()) { 632 633 LOG<<prefix<<qname<<": Domain is out-of-band"<<endl; 633 doOOBResolve(qname, qtype, result, depth, d_lwr.d_rcode);634 d_lwr.d_tcbit=false;635 d_lwr.d_aabit=true;634 doOOBResolve(qname, qtype, result, depth, lwr.d_rcode); 635 lwr.d_tcbit=false; 636 lwr.d_aabit=true; 636 637 } 637 638 else { … … 659 660 660 661 } 662 661 663 for(remoteIP = remoteIPs.begin(); remoteIP != remoteIPs.end(); ++remoteIP) { 662 664 LOG<<prefix<<qname<<": Trying IP "<< remoteIP->toString() <<", asking '"<<qname<<"|"<<qtype.getName()<<"'"<<endl; … … 679 681 } 680 682 681 resolveret= d_lwr.asyncresolve(*remoteIP, qname, qtype.getCode(), doTCP, &d_now); // <- we go out on the wire!683 resolveret=asyncresolve(*remoteIP, qname, qtype.getCode(), doTCP, &d_now, &lwr); // <- we go out on the wire! 682 684 if(resolveret != 1) { 683 685 if(resolveret==0) { … … 692 694 else { 693 695 s_unreachables++; d_unreachables++; 694 LOG<<prefix<<qname<<": error resolving "<< (doTCP ? "over TCP" : "")<< endl;696 LOG<<prefix<<qname<<": error resolving"<< (doTCP ? " over TCP" : "") <<", possible error: "<<strerror(errno)<< endl; 695 697 } 696 698 … … 715 717 continue; 716 718 717 result=d_lwr.result(); 718 719 if(d_lwr.d_tcbit) { 719 if(lwr.d_tcbit) { 720 720 if(!doTCP) { 721 721 doTCP=true; … … 727 727 } 728 728 729 if( d_lwr.d_rcode==RCode::ServFail) {729 if(lwr.d_rcode==RCode::ServFail) { 730 730 LOG<<prefix<<qname<<": "<<*tns<<" returned a ServFail, trying sibling IP or NS"<<endl; 731 731 s_throttle.throttle(d_now.tv_sec,make_tuple(*remoteIP, qname, qtype.getCode()),60,3); 732 732 continue; 733 733 } 734 LOG<<prefix<<qname<<": Got "<<(unsigned int) result.size()<<" answers from "<<*tns<<" ("<< remoteIP->toString() <<"), rcode="<<d_lwr.d_rcode<<", in "<<d_lwr.d_usec/1000<<"ms"<<endl;734 LOG<<prefix<<qname<<": Got "<<(unsigned int)lwr.d_result.size()<<" answers from "<<*tns<<" ("<< remoteIP->toString() <<"), rcode="<<lwr.d_rcode<<", in "<<lwr.d_usec/1000<<"ms"<<endl; 735 735 736 736 /* // for you IPv6 fanatics :-) 737 737 if(remoteIP->sin4.sin_family==AF_INET6) 738 d_lwr.d_usec/=3;738 lwr.d_usec/=3; 739 739 */ 740 740 741 s_nsSpeeds[*tns].submit(*remoteIP, d_lwr.d_usec, &d_now);741 s_nsSpeeds[*tns].submit(*remoteIP, lwr.d_usec, &d_now); 742 742 } 743 743 … … 746 746 747 747 // reap all answers from this packet that are acceptable 748 for(LWRes ::res_t::const_iterator i=result.begin();i!=result.end();++i) {748 for(LWResult::res_t::const_iterator i=lwr.d_result.begin();i != lwr.d_result.end();++i) { 749 749 LOG<<prefix<<qname<<": accept answer '"<<i->qname<<"|"<<i->qtype.getName()<<"|"<<i->content<<"' from '"<<auth<<"' nameservers? "; 750 750 if(i->qtype.getCode()==QType::ANY) { … … 754 754 755 755 if(dottedEndsOn(i->qname, auth)) { 756 if( d_lwr.d_aabit && d_lwr.d_rcode==RCode::NoError && i->d_place==DNSResourceRecord::ANSWER && ::arg().contains("delegation-only",auth)) {756 if(lwr.d_aabit && lwr.d_rcode==RCode::NoError && i->d_place==DNSResourceRecord::ANSWER && ::arg().contains("delegation-only",auth)) { 757 757 LOG<<"NO! Is from delegation-only zone"<<endl; 758 758 s_nodelegated++; … … 788 788 } 789 789 790 RC.replace(d_now.tv_sec, i->first.first, i->first.second, i->second, d_lwr.d_aabit);790 RC.replace(d_now.tv_sec, i->first.first, i->first.second, i->second, lwr.d_aabit); 791 791 } 792 792 set<string, CIStringCompare> nsset; … … 796 796 string newauth, soaname, newtarget; 797 797 798 for(LWRes ::res_t::const_iterator i=result.begin();i!=result.end();++i) {798 for(LWResult::res_t::const_iterator i=lwr.d_result.begin();i!=lwr.d_result.end();++i) { 799 799 if(i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA && 800 d_lwr.d_rcode==RCode::NXDomain) {800 lwr.d_rcode==RCode::NXDomain) { 801 801 LOG<<prefix<<qname<<": got negative caching indication for RECORD '"<<qname+"'"<<endl; 802 802 ret.push_back(*i); … … 819 819 else if(i->d_place==DNSResourceRecord::ANSWER && !Utility::strcasecmp(i->qname.c_str(),qname.c_str()) && 820 820 ( (i->qtype==qtype) || 821 ( qtype==QType(QType::ANY) && d_lwr.d_aabit))) {821 ( qtype==QType(QType::ANY) && lwr.d_aabit))) { 822 822 823 823 LOG<<prefix<<qname<<": answer is in: resolved to '"<< i->content<<"|"<<i->qtype.getName()<<"'"<<endl; … … 837 837 } 838 838 else if(!done && i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA && 839 d_lwr.d_rcode==RCode::NoError) {839 lwr.d_rcode==RCode::NoError) { 840 840 LOG<<prefix<<qname<<": got negative caching indication for '"<< (qname+"|"+i->qtype.getName()+"'") <<endl; 841 841 ret.push_back(*i); … … 857 857 return 0; 858 858 } 859 if( d_lwr.d_rcode==RCode::NXDomain) {859 if(lwr.d_rcode==RCode::NXDomain) { 860 860 LOG<<prefix<<qname<<": status=NXDOMAIN, we are done "<<(negindic ? "(have negative SOA)" : "")<<endl; 861 861 return RCode::NXDomain; … … 875 875 return doResolve(newtarget, qtype, ret, depth + 1, beenthere2); 876 876 } 877 if(nsset.empty() && ! d_lwr.d_rcode) {877 if(nsset.empty() && !lwr.d_rcode) { 878 878 LOG<<prefix<<qname<<": status=noerror, other types may exist, but we are done "<<(negindic ? "(have negative SOA)" : "")<<endl; 879 879 return 0; … … 886 886 } 887 887 else if(isCanonical(*tns)) { 888 goto wasLame; ;888 goto wasLame; 889 889 } 890 890 } trunk/pdns/pdns/syncres.hh
r1061 r1117 373 373 bool d_cacheonly; 374 374 bool d_nocache; 375 LWRes d_lwr;376 375 377 376 struct GetBestNSAnswer