Changeset 1426 for trunk/pdns/pdns/pdns_recursor.cc
- Timestamp:
- 10/11/09 10:33:55 (4 years ago)
- Files:
-
- 1 modified
-
trunk/pdns/pdns/pdns_recursor.cc (modified) (16 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/pdns/pdns/pdns_recursor.cc
r1416 r1426 25 25 #endif // WIN32 26 26 27 #include <boost/foreach.hpp> 27 28 #include "utility.hh" 28 29 #include "dns_random.hh" 30 #include "md5.hh" 29 31 #include <iostream> 30 32 #include <errno.h> … … 72 74 bool g_logCommonErrors; 73 75 shared_ptr<PowerDNSLua> g_pdl; 74 using namespace boost; 76 #include "namespaces.hh" 75 77 76 78 #ifdef __FreeBSD__ // see cvstrac ticket #26 … … 78 80 #include <semaphore.h> 79 81 #endif 82 map<string, string> g_packetCache; 80 83 81 84 MemRecursorCache RC; … … 92 95 map<int, ComboAddress> g_listenSocketsAddresses; // is shared across all threads right now 93 96 struct DNSComboWriter { 94 DNSComboWriter(const char* data, uint16_t len, const struct timeval& now) : d_mdp(data, len), d_now(now), d_tcp(false), d_socket(-1) 97 DNSComboWriter(const char* data, uint16_t len, const std::string& hash, const struct timeval& now) : d_mdp(data, len), d_now(now), 98 d_hash(hash), d_tcp(false), d_socket(-1) 95 99 {} 96 100 MOADNSParser d_mdp; … … 112 116 struct timeval d_now; 113 117 ComboAddress d_remote; 118 string d_hash; 114 119 bool d_tcp; 115 120 int d_socket; … … 173 178 } 174 179 180 vector<ComboAddress> g_localQueryAddresses4, g_localQueryAddresses6; 181 ComboAddress g_local4("0.0.0.0"), g_local6("::"); 182 ComboAddress getQueryLocalAddress(int family) 183 { 184 if(family==AF_INET) { 185 if(g_localQueryAddresses4.empty()) 186 return g_local4; 187 return g_localQueryAddresses4[dns_random(g_localQueryAddresses4.size())]; 188 } 189 else { 190 if(g_localQueryAddresses6.empty()) 191 return g_local6; 192 return g_localQueryAddresses6[dns_random(g_localQueryAddresses6.size())]; 193 } 194 195 } 175 196 176 197 void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t&); … … 253 274 if(ret<0) 254 275 throw AhuException("Making a socket for resolver: "+stringerror()); 255 256 static optional<ComboAddress> sin4; 257 if(!sin4) { 258 sin4=ComboAddress(::arg()["query-local-address"]); 259 } 260 static optional<ComboAddress> sin6; 261 if(!sin6) { 262 if(!::arg()["query-local-address6"].empty()) 263 sin6=ComboAddress(::arg()["query-local-address6"]); 264 } 276 265 277 266 278 int tries=10; … … 269 281 if(tries==1) // fall back to kernel 'random' 270 282 port=0; 271 272 if(family==AF_INET) { 273 sin4->sin4.sin_port = htons(port); 274 275 if (::bind(ret, (struct sockaddr *)&*sin4, sin4->getSocklen()) >= 0) 276 break; 277 } 278 else { 279 if(!sin6) 280 break; 281 sin6->sin6.sin6_port = htons(port); 282 283 if (::bind(ret, (struct sockaddr *)&*sin6, sin6->getSocklen()) >= 0) 284 break; 285 } 283 284 ComboAddress sin=getQueryLocalAddress(family); 285 if (::bind(ret, (struct sockaddr *)&sin, sin.getSocklen()) >= 0) 286 break; 286 287 } 287 288 if(!tries) … … 602 603 } 603 604 } 604 605 605 if(res<0) { 606 606 pw.getHeader()->rcode=RCode::ServFail; … … 651 651 if(!dc->d_tcp) { 652 652 sendto(dc->d_socket, (const char*)&*packet.begin(), packet.size(), 0, (struct sockaddr *)(&dc->d_remote), dc->d_remote.getSocklen()); 653 if(pw.getHeader()->rcode==RCode::NoError || pw.getHeader()->rcode==RCode::NXDomain ) 654 g_packetCache[dc->d_hash]=string((const char*)&*packet.begin(), packet.size()); 655 else 656 ; // cerr<<"rcode:" <<(int)pw.getHeader()->rcode<<endl; 653 657 } 654 658 else { … … 796 800 DNSComboWriter* dc=0; 797 801 try { 798 dc=new DNSComboWriter(tconn.data, tconn.qlen, g_now);802 dc=new DNSComboWriter(tconn.data, tconn.qlen, string(), g_now); 799 803 } 800 804 catch(MOADNSException &mde) { … … 901 905 } 902 906 907 903 908 void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var) 904 909 { … … 931 936 else { 932 937 ++g_stats.qcounter; 933 #if 0 934 uint16_t type; 935 char qname[256]; 936 try { 937 questionExpand(data, len, qname, sizeof(qname), type); 938 } 939 catch(std::exception &e) 940 { 941 throw MOADNSException(e.what()); 942 } 938 uint16_t tmp = dh->id; 939 dh->id=0; 943 940 944 // must all be same length answers right now! 945 if((type==QType::A || type==QType::AAAA) && dh->arcount==0 && dh->ancount==0 && dh->nscount ==0 && ntohs(dh->qdcount)==1 ) { 946 char *record[10]; 947 uint16_t rlen[10]; 948 uint32_t ttd[10]; 949 int count; 950 if((count=RC.getDirect(g_now.tv_sec, qname, QType(type), ttd, record, rlen))) { 951 if(len + count*(sizeof(dnsrecordheader) + 2 + rlen[0]) > 512) 952 goto slow; 953 954 random_shuffle(record, &record[count]); 955 dh->qr=1; 956 dh->ra=1; 957 dh->ancount=ntohs(count); 958 for(int n=0; n < count ; ++n) { 959 memcpy(data+len, "\xc0\x0c", 2); // answer label pointer 960 len+=2; 961 struct dnsrecordheader drh; 962 drh.d_type=htons(type); 963 drh.d_class=htons(1); 964 drh.d_ttl=htonl(ttd[n] - g_now.tv_sec); 965 drh.d_clen=htons(rlen[n]); 966 memcpy(data+len, &drh, sizeof(drh)); 967 len+=sizeof(drh); 968 memcpy(data+len, record[n], rlen[n]); 969 len+=rlen[n]; 970 } 971 RDTSC(tsc2); 972 g_stats.shunted++; 973 sendto(fd, data, len, 0, (struct sockaddr *)(&fromaddr), fromaddr.getSocklen()); 974 // cerr<<"shunted: " << (tsc2-tsc1) / 3000.0 << endl; 975 return; 976 } 941 MD5Summer md5s; 942 md5s.feed(data, len); 943 string hash = md5s.get(); 944 // cerr<<"hash: "<<makeHexDump(hash)<<endl; 945 dh->id=tmp; 946 947 if(g_packetCache.count(hash)) { 948 g_stats.packetCacheHits++; 949 SyncRes::s_queries++; 950 string reply=g_packetCache[hash]; 951 ((struct dnsheader*)reply.c_str())->id=tmp; 952 sendto(fd, reply.c_str(), reply.length(), 0, (struct sockaddr*) &fromaddr, fromaddr.getSocklen()); 953 return; 977 954 } 978 else { 979 if(type!=QType::A && type!=QType::AAAA) 980 g_stats.noShuntWrongType++; 981 else 982 g_stats.noShuntWrongQuestion++; 983 } 984 slow: 985 #endif 986 DNSComboWriter* dc = new DNSComboWriter(data, len, g_now); 955 956 DNSComboWriter* dc = new DNSComboWriter(data, len, hash, g_now); 987 957 dc->setSocket(fd); 988 958 dc->setRemote(&fromaddr); … … 1160 1130 if(g_stats.qcounter && (RC.cacheHits + RC.cacheMisses) && SyncRes::s_queries && SyncRes::s_outqueries) { 1161 1131 //L<<Logger::Warning<<"stats: "<<g_stats.qcounter<<" questions, "<<RC.size()<<" cache entries, "<<SyncRes::s_negcache.size()<<" negative entries, " 1162 L<<Logger::Warning<< (int)((RC.cacheHits*100.0)/(RC.cacheHits+RC.cacheMisses))<<"% cache hits"<<endl;1132 L<<Logger::Warning<<"stats: " <<(int)((RC.cacheHits*100.0)/(RC.cacheHits+RC.cacheMisses))<<"% cache hits"<<endl; 1163 1133 // L<<Logger::Warning<<"stats: throttle map: "<<SyncRes::s_throttle.size()<<", ns speeds: " 1164 1134 // <<endl; // <<SyncRes::s_nsSpeeds.size()<<endl; // ", bytes: "<<RC.bytes()<<endl; … … 1170 1140 L<<Logger::Warning<<"stats: "<<g_stats.ednsPingMatches<<" ping matches, "<<g_stats.ednsPingMismatches<<" mismatches, "<< 1171 1141 g_stats.noPingOutQueries<<" outqueries w/o ping, "<< g_stats.noEdnsOutQueries<<" w/o EDNS"<<endl; 1142 L<<Logger::Warning<<"stats: "<<g_stats.packetCacheHits<<" packet cache hits ("<<(int)(100.0*g_stats.packetCacheHits/SyncRes::s_queries) << "%)"<<endl; 1172 1143 } 1173 1144 else if(statsWanted) … … 1855 1826 RC.d_followRFC2181=::arg().mustDo("auth-can-lower-ttl"); 1856 1827 1857 if(!::arg()["query-local-address6"].empty()) { 1858 SyncRes::s_doIPv6=true; 1859 L<<Logger::Error<<"Enabling IPv6 transport for outgoing queries"<<endl; 1828 try { 1829 vector<string> addrs; 1830 if(!::arg()["query-local-address6"].empty()) { 1831 SyncRes::s_doIPv6=true; 1832 L<<Logger::Error<<"Enabling IPv6 transport for outgoing queries"<<endl; 1833 1834 stringtok(addrs, ::arg()["query-local-address6"], ", ;"); 1835 BOOST_FOREACH(const string& addr, addrs) { 1836 g_localQueryAddresses6.push_back(ComboAddress(addr)); 1837 } 1838 } 1839 addrs.clear(); 1840 stringtok(addrs, ::arg()["query-local-address"], ", ;"); 1841 BOOST_FOREACH(const string& addr, addrs) { 1842 g_localQueryAddresses4.push_back(ComboAddress(addr)); 1843 } 1844 } 1845 catch(std::exception& e) { 1846 L<<Logger::Error<<"Assigning local query addresses: "<<e.what(); 1847 exit(99); 1860 1848 } 1861 1849