]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/syncres.cc
2 PowerDNS Versatile Database Driven Nameserver
3 Copyright (C) 2003 - 2006 PowerDNS.COM BV
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2 as published
7 by the Free Software Foundation
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #include "arguments.hh"
35 #include "recursor_cache.hh"
36 #include "dnsparser.hh"
38 extern MemRecursorCache RC
;
40 SyncRes::negcache_t
SyncRes::s_negcache
;
41 SyncRes::nsspeeds_t
SyncRes::s_nsSpeeds
;
43 unsigned int SyncRes::s_queries
;
44 unsigned int SyncRes::s_outgoingtimeouts
;
45 unsigned int SyncRes::s_outqueries
;
46 unsigned int SyncRes::s_tcpoutqueries
;
47 unsigned int SyncRes::s_throttledqueries
;
48 unsigned int SyncRes::s_nodelegated
;
51 #define LOG if(s_log) L<<Logger::Warning
53 Throttle
<tuple
<uint32_t,string
,uint16_t> > SyncRes::s_throttle
;
55 /** everything begins here - this is the entry point just after receiving a packet */
56 int SyncRes::beginResolve(const string
&qname
, const QType
&qtype
, vector
<DNSResourceRecord
>&ret
)
59 if( (qtype
.getCode()==QType::PTR
&& !strcasecmp(qname
.c_str(), "1.0.0.127.in-addr.arpa.")) ||
60 (qtype
.getCode()==QType::A
&& qname
.length()==10 && !strcasecmp(qname
.c_str(), "localhost."))) {
66 if(qtype
.getCode()==QType::PTR
)
67 rr
.content
="localhost.";
69 rr
.content
="127.0.0.1";
74 set
<GetBestNSAnswer
> beenthere
;
75 int res
=doResolve(qname
, qtype
, ret
,0,beenthere
);
81 int SyncRes::doResolve(const string
&qname
, const QType
&qtype
, vector
<DNSResourceRecord
>&ret
, int depth
, set
<GetBestNSAnswer
>& beenthere
)
86 prefix
.append(depth
, ' ');
90 if(!(d_nocache
&& qtype
.getCode()==QType::NS
&& qname
.empty())) {
91 if(doCNAMECacheCheck(qname
,qtype
,ret
,depth
,res
)) // will reroute us if needed
94 if(doCacheCheck(qname
,qtype
,ret
,depth
,res
)) // we done
101 LOG
<<prefix
<<qname
<<": No cache hit for '"<<qname
<<"|"<<qtype
.getName()<<"', trying to find an appropriate NS record"<<endl
;
103 string
subdomain(qname
);
105 set
<string
, CIStringCompare
> nsset
;
106 for(int tries
=0;tries
<2 && nsset
.empty();++tries
) {
107 subdomain
=getBestNSNamesFromCache(subdomain
,nsset
,depth
, beenthere
); // pass beenthere to both occasions
109 if(nsset
.empty()) { // must've lost root records
110 LOG
<<prefix
<<qname
<<": our root expired, repriming from hints and retrying"<<endl
;
115 if(!(res
=doResolveAt(nsset
,subdomain
,qname
,qtype
,ret
,depth
, beenthere
)))
118 LOG
<<prefix
<<qname
<<": failed"<<endl
;
119 return res
<0 ? RCode::ServFail
: res
;
122 vector
<uint32_t> SyncRes::getAs(const string
&qname
, int depth
, set
<GetBestNSAnswer
>& beenthere
)
124 typedef vector
<DNSResourceRecord
> res_t
;
127 vector
<uint32_t> ret
;
129 if(!doResolve(qname
,QType(QType::A
), res
,depth
+1,beenthere
) && !res
.empty()) {
130 for(res_t::const_iterator i
=res
.begin(); i
!= res
.end(); ++i
) {
131 if(i
->qtype
.getCode()==QType::A
) {
133 if(IpToU32(i
->content
, &ip
))
134 ret
.push_back(ntohl(ip
));
139 random_shuffle(ret
.begin(), ret
.end());
143 void SyncRes::getBestNSFromCache(const string
&qname
, set
<DNSResourceRecord
>&bestns
, int depth
, set
<GetBestNSAnswer
>& beenthere
)
145 string prefix
, subdomain(qname
);
148 prefix
.append(depth
, ' ');
153 LOG
<<prefix
<<qname
<<": Checking if we have NS in cache for '"<<subdomain
<<"'"<<endl
;
154 set
<DNSResourceRecord
> ns
;
155 if(RC
.get(d_now
.tv_sec
, subdomain
, QType(QType::NS
), &ns
) > 0) {
156 for(set
<DNSResourceRecord
>::const_iterator k
=ns
.begin();k
!=ns
.end();++k
) {
157 if(k
->ttl
> (unsigned int)d_now
.tv_sec
) {
158 set
<DNSResourceRecord
>aset
;
160 DNSResourceRecord rr
=*k
;
161 rr
.content
=k
->content
;
162 if(!dottedEndsOn(rr
.content
,subdomain
) || RC
.get(d_now
.tv_sec
, rr
.content
,QType(QType::A
),&aset
) > 5) {
165 LOG
<<prefix
<<qname
<<": NS (with ip, or non-glue) in cache for '"<<subdomain
<<"' -> '"<<rr
.content
<<"'"<<endl
;
166 LOG
<<prefix
<<qname
<<": within bailiwick: "<<dottedEndsOn(rr
.content
, subdomain
);
168 LOG
<<", in cache, ttl="<<(unsigned int)(((time_t)aset
.begin()->ttl
- d_now
.tv_sec
))<<endl
;
171 LOG
<<", not in cache"<<endl
;
175 LOG
<<prefix
<<qname
<<": NS in cache for '"<<subdomain
<<"', but needs glue ("<<k
->content
<<") which we miss or is expired"<<endl
;
178 if(!bestns
.empty()) {
179 GetBestNSAnswer answer
;
180 answer
.qname
=qname
; answer
.bestns
=bestns
;
181 if(beenthere
.count(answer
)) {
182 LOG
<<prefix
<<qname
<<": We have NS in cache for '"<<subdomain
<<"' but part of LOOP! Trying less specific NS"<<endl
;
183 for( set
<GetBestNSAnswer
>::const_iterator j
=beenthere
.begin();j
!=beenthere
.end();++j
)
184 LOG
<<prefix
<<qname
<<": beenthere: "<<j
->qname
<<" ("<<j
->bestns
.size()<<")"<<endl
;
188 beenthere
.insert(answer
);
189 LOG
<<prefix
<<qname
<<": We have NS in cache for '"<<subdomain
<<"'"<<endl
;
194 }while(chopOffDotted(subdomain
));
198 /** doesn't actually do the work, leaves that to getBestNSFromCache */
199 string
SyncRes::getBestNSNamesFromCache(const string
&qname
,set
<string
, CIStringCompare
>& nsset
, int depth
, set
<GetBestNSAnswer
>&beenthere
)
201 string
subdomain(qname
);
203 set
<DNSResourceRecord
> bestns
;
204 getBestNSFromCache(subdomain
, bestns
, depth
, beenthere
);
206 for(set
<DNSResourceRecord
>::const_iterator k
=bestns
.begin();k
!=bestns
.end();++k
) {
207 nsset
.insert(k
->content
);
213 bool SyncRes::doCNAMECacheCheck(const string
&qname
, const QType
&qtype
, vector
<DNSResourceRecord
>&ret
, int depth
, int &res
)
218 prefix
.append(depth
, ' ');
222 LOG
<<prefix
<<qname
<<": CNAME loop too deep, depth="<<depth
<<endl
;
227 LOG
<<prefix
<<qname
<<": Looking for CNAME cache hit of '"<<(qname
+"|CNAME")<<"'"<<endl
;
228 set
<DNSResourceRecord
> cset
;
229 if(RC
.get(d_now
.tv_sec
, qname
,QType(QType::CNAME
),&cset
) > 0) {
231 for(set
<DNSResourceRecord
>::const_iterator j
=cset
.begin();j
!=cset
.end();++j
) {
232 if(j
->ttl
>(unsigned int) d_now
.tv_sec
) {
233 LOG
<<prefix
<<qname
<<": Found cache CNAME hit for '"<< (qname
+"|CNAME") <<"' to '"<<j
->content
<<"'"<<endl
;
234 DNSResourceRecord rr
=*j
;
235 rr
.ttl
-=d_now
.tv_sec
;
237 if(!(qtype
==QType(QType::CNAME
))) { // perhaps they really wanted a CNAME!
238 set
<GetBestNSAnswer
>beenthere
;
239 res
=doResolve(j
->content
, qtype
, ret
, depth
+1, beenthere
);
247 LOG
<<prefix
<<qname
<<": No CNAME cache hit of '"<< (qname
+"|CNAME") <<"' found"<<endl
;
251 bool SyncRes::doCacheCheck(const string
&qname
, const QType
&qtype
, vector
<DNSResourceRecord
>&ret
, int depth
, int &res
)
253 bool giveNegative
=false;
258 prefix
.append(depth
, ' ');
261 string
sqname(qname
);
264 // cout<<"Lookup for '"<<qname<<"|"<<qtype.getName()<<"'\n";
266 pair
<negcache_t::const_iterator
, negcache_t::const_iterator
> range
=s_negcache
.equal_range(tie(qname
));
267 negcache_t::iterator ni
;
268 for(ni
=range
.first
; ni
!= range
.second
; ni
++) {
270 if(ni
->d_qtype
.getCode() == 0 || ni
->d_qtype
== qtype
) {
272 if((uint32_t)d_now
.tv_sec
< ni
->d_ttd
) {
273 sttl
=ni
->d_ttd
- d_now
.tv_sec
;
274 if(ni
->d_qtype
.getCode()) {
275 LOG
<<prefix
<<qname
<<": "<<qtype
.getName()<<" is negatively cached for another "<<sttl
<<" seconds"<<endl
;
276 res
= RCode::NoError
;
279 LOG
<<prefix
<<qname
<<": Entire record '"<<qname
<<"', is negatively cached for another "<<sttl
<<" seconds"<<endl
;
280 res
= RCode::NXDomain
;
288 LOG
<<prefix
<<qname
<<": Entire record '"<<qname
<<"' was negatively cached, but entry expired"<<endl
;
293 set
<DNSResourceRecord
> cset
;
294 bool found
=false, expired
=false;
296 if(RC
.get(d_now
.tv_sec
, sqname
,sqt
, &cset
) > 0) {
297 LOG
<<prefix
<<qname
<<": Found cache hit for "<<sqt
.getName()<<": ";
298 for(set
<DNSResourceRecord
>::const_iterator j
=cset
.begin();j
!=cset
.end();++j
) {
300 if(j
->ttl
>(unsigned int) d_now
.tv_sec
) {
301 DNSResourceRecord rr
=*j
;
302 rr
.ttl
-=d_now
.tv_sec
;
304 rr
.d_place
=DNSResourceRecord::AUTHORITY
;
308 LOG
<<"[ttl="<<rr
.ttl
<<"] ";
318 if(found
&& !expired
) {
323 LOG
<<prefix
<<qname
<<": cache had only stale entries"<<endl
;
329 bool SyncRes::moreSpecificThan(const string
& a
, const string
&b
)
331 static string
dot(".");
332 int counta
=(a
!=dot
), countb
=(b
!=dot
);
334 for(string::size_type n
=0;n
<a
.size();++n
)
337 for(string::size_type n
=0;n
<b
.size();++n
)
340 return counta
>countb
;
345 speedOrder(map
<string
,double> &speeds
) : d_speeds(speeds
) {}
346 bool operator()(const string
&a
, const string
&b
) const
348 return d_speeds
[a
] < d_speeds
[b
];
350 map
<string
,double>& d_speeds
;
353 inline vector
<string
> SyncRes::shuffle(set
<string
, CIStringCompare
> &nameservers
, const string
&prefix
)
355 vector
<string
> rnameservers
;
356 rnameservers
.reserve(nameservers
.size());
357 map
<string
,double> speeds
;
359 for(set
<string
, CIStringCompare
>::const_iterator i
=nameservers
.begin();i
!=nameservers
.end();++i
) {
360 rnameservers
.push_back(*i
);
361 DecayingEwma
& temp
=s_nsSpeeds
[*i
];
362 speeds
[*i
]=temp
.get(&d_now
);
364 random_shuffle(rnameservers
.begin(),rnameservers
.end());
365 stable_sort(rnameservers
.begin(),rnameservers
.end(), speedOrder(speeds
));
368 L
<<Logger::Warning
<<prefix
<<"Nameservers: ";
369 for(vector
<string
>::const_iterator i
=rnameservers
.begin();i
!=rnameservers
.end();++i
) {
370 if(i
!=rnameservers
.begin()) {
372 if(!((i
-rnameservers
.begin())%4))
373 L
<<endl
<<Logger::Warning
<<prefix
<<" ";
375 L
<<*i
<<"(" << (int)(speeds
[*i
]/1000.0) <<"ms)";
384 bool operator()(const pair
<string
, QType
>& a
, const pair
<string
, QType
>& b
) const
386 int cmp
=strcasecmp(a
.first
.c_str(), b
.first
.c_str());
392 return a
.second
< b
.second
;
398 /** returns -1 in case of no results, rcode otherwise */
399 int SyncRes::doResolveAt(set
<string
, CIStringCompare
> nameservers
, string auth
, const string
&qname
, const QType
&qtype
, vector
<DNSResourceRecord
>&ret
,
400 int depth
, set
<GetBestNSAnswer
>&beenthere
)
405 prefix
.append(depth
, ' ');
410 LOG
<<prefix
<<qname
<<": Cache consultations done, have "<<nameservers
.size()<<" NS to contact"<<endl
;
412 for(;;) { // we may get more specific nameservers
415 vector
<string
> rnameservers
=shuffle(nameservers
, s_log
? (prefix
+qname
+": ") : string() );
417 for(vector
<string
>::const_iterator tns
=rnameservers
.begin();;++tns
) {
418 if(tns
==rnameservers
.end()) {
419 LOG
<<prefix
<<qname
<<": Failed to resolve via any of the "<<rnameservers
.size()<<" offered NS"<<endl
;
422 if(qname
==*tns
&& qtype
.getCode()==QType::A
) {
423 LOG
<<prefix
<<qname
<<": Not using NS to resolve itself!"<<endl
;
426 LOG
<<prefix
<<qname
<<": Trying to resolve NS "<<*tns
<<" ("<<1+tns
-rnameservers
.begin()<<"/"<<rnameservers
.size()<<")"<<endl
;
427 typedef vector
<uint32_t> remoteIPs_t
;
428 remoteIPs_t remoteIPs
=getAs(*tns
, depth
+1, beenthere
);
429 if(remoteIPs
.empty()) {
430 LOG
<<prefix
<<qname
<<": Failed to get IP for NS "<<*tns
<<", trying next if available"<<endl
;
433 remoteIPs_t::const_iterator remoteIP
;
435 for(remoteIP
= remoteIPs
.begin(); remoteIP
!= remoteIPs
.end(); ++remoteIP
) {
436 LOG
<<prefix
<<qname
<<": Resolved '"+auth
+"' NS "<<*tns
<<" to "<<U32ToIP(*remoteIP
)<<", asking '"<<qname
<<"|"<<qtype
.getName()<<"'"<<endl
;
438 if(s_throttle
.shouldThrottle(d_now
.tv_sec
, make_tuple(*remoteIP
, qname
, qtype
.getCode()))) {
439 LOG
<<prefix
<<qname
<<": query throttled "<<endl
;
440 s_throttledqueries
++;
441 d_throttledqueries
++;
453 int ret
=d_lwr
.asyncresolve(*remoteIP
, qname
.c_str(), qtype
.getCode(), doTCP
, &d_now
); // <- we go out on the wire!
456 LOG
<<prefix
<<qname
<<": timeout resolving"<<endl
;
458 s_outgoingtimeouts
++;
461 LOG
<<prefix
<<qname
<<": error resolving"<<endl
;
463 s_nsSpeeds
[*tns
].submit(1000000, &d_now
); // 1 sec
465 s_throttle
.throttle(d_now
.tv_sec
, make_tuple(*remoteIP
, qname
, qtype
.getCode()),20,5);
469 break; // it did work!
473 if(remoteIP
== remoteIPs
.end()) // we tried all IP addresses, none worked
476 result
=d_lwr
.result();
481 LOG
<<prefix
<<qname
<<": truncated bit set, retrying via TCP"<<endl
;
484 LOG
<<prefix
<<qname
<<": truncated bit set, over TCP?"<<endl
;
485 return RCode::ServFail
;
488 if(d_lwr
.d_rcode
==RCode::ServFail
) {
489 LOG
<<prefix
<<qname
<<": "<<*tns
<<" returned a ServFail, trying sibling NS"<<endl
;
490 s_throttle
.throttle(d_now
.tv_sec
,make_tuple(*remoteIP
, qname
, qtype
.getCode()),60,3);
493 LOG
<<prefix
<<qname
<<": Got "<<result
.size()<<" answers from "<<*tns
<<" ("<<U32ToIP(*remoteIP
)<<"), rcode="<<d_lwr
.d_rcode
<<", in "<<d_lwr
.d_usec
/1000<<"ms"<<endl
;
494 s_nsSpeeds
[*tns
].submit(d_lwr
.d_usec
, &d_now
);
496 typedef map
<pair
<string
, QType
>, set
<DNSResourceRecord
>, TCacheComp
> tcache_t
;
499 // reap all answers from this packet that are acceptable
500 for(LWRes::res_t::const_iterator i
=result
.begin();i
!=result
.end();++i
) {
501 LOG
<<prefix
<<qname
<<": accept answer '"<<i
->qname
<<"|"<<i
->qtype
.getName()<<"|"<<i
->content
<<"' from '"<<auth
<<"' nameservers? ";
503 if(dottedEndsOn(i
->qname
, auth
)) {
504 if(d_lwr
.d_aabit
&& d_lwr
.d_rcode
==RCode::NoError
&& i
->d_place
==DNSResourceRecord::ANSWER
&& ::arg().contains("delegation-only",auth
)) {
505 LOG
<<"NO! Is from delegation-only zone"<<endl
;
507 return RCode::NXDomain
;
512 DNSResourceRecord rr
=*i
;
513 rr
.d_place
=DNSResourceRecord::ANSWER
;
514 rr
.ttl
+=d_now
.tv_sec
;
515 if(rr
.qtype
.getCode() == QType::NS
) // people fiddle with the case
516 rr
.content
=toLower(rr
.content
); // this must stay!
517 tcache
[make_pair(i
->qname
,i
->qtype
)].insert(rr
);
525 for(tcache_t::const_iterator i
=tcache
.begin();i
!=tcache
.end();++i
) {
526 RC
.replace(i
->first
.first
, i
->first
.second
, i
->second
);
528 set
<string
, CIStringCompare
> nsset
;
529 LOG
<<prefix
<<qname
<<": determining status after receiving this packet"<<endl
;
531 bool done
=false, realreferral
=false, negindic
=false;
532 string newauth
, soaname
, newtarget
;
534 for(LWRes::res_t::const_iterator i
=result
.begin();i
!=result
.end();++i
) {
535 if(i
->d_place
==DNSResourceRecord::AUTHORITY
&& dottedEndsOn(qname
,i
->qname
) && i
->qtype
.getCode()==QType::SOA
&&
536 d_lwr
.d_rcode
==RCode::NXDomain
) {
537 LOG
<<prefix
<<qname
<<": got negative caching indication for RECORD '"<<qname
+"'"<<endl
;
543 ne
.d_ttd
=d_now
.tv_sec
+ min(i
->ttl
, 3600U); // controversial
546 s_negcache
.insert(ne
);
549 else if(i
->d_place
==DNSResourceRecord::ANSWER
&& i
->qname
==qname
&& i
->qtype
.getCode()==QType::CNAME
&& (!(qtype
==QType(QType::CNAME
)))) {
551 newtarget
=i
->content
;
553 // for ANY answers we *must* have an authoritive answer
554 else if(i
->d_place
==DNSResourceRecord::ANSWER
&& !strcasecmp(i
->qname
.c_str(),qname
.c_str()) &&
555 ( (i
->qtype
==qtype
) ||
556 ( qtype
==QType(QType::ANY
) && d_lwr
.d_aabit
))) {
558 LOG
<<prefix
<<qname
<<": answer is in: resolved to '"<< i
->content
<<"|"<<i
->qtype
.getName()<<"'"<<endl
;
564 else if(i
->d_place
==DNSResourceRecord::AUTHORITY
&& dottedEndsOn(qname
,i
->qname
) && i
->qtype
.getCode()==QType::NS
) {
565 if(moreSpecificThan(i
->qname
,auth
)) {
567 LOG
<<prefix
<<qname
<<": got NS record '"<<i
->qname
<<"' -> '"<<i
->content
<<"'"<<endl
;
571 LOG
<<prefix
<<qname
<<": got upwards/level NS record '"<<i
->qname
<<"' -> '"<<i
->content
<<"', had '"<<auth
<<"'"<<endl
;
572 nsset
.insert(i
->content
);
574 else if(i
->d_place
==DNSResourceRecord::AUTHORITY
&& dottedEndsOn(qname
,i
->qname
) && i
->qtype
.getCode()==QType::SOA
&&
575 d_lwr
.d_rcode
==RCode::NoError
) {
576 LOG
<<prefix
<<qname
<<": got negative caching indication for '"<< (qname
+"|"+i
->qtype
.getName()+"'") <<endl
;
581 ne
.d_ttd
=d_now
.tv_sec
+ min(3600U,i
->ttl
);
584 if(qtype
.getCode()) // prevents us from blacking out a whole domain
585 s_negcache
.insert(ne
);
591 LOG
<<prefix
<<qname
<<": status=got results, this level of recursion done"<<endl
;
594 if(d_lwr
.d_rcode
==RCode::NXDomain
) {
595 LOG
<<prefix
<<qname
<<": status=NXDOMAIN, we are done "<<(negindic
? "(have negative SOA)" : "")<<endl
;
596 return RCode::NXDomain
;
598 if(!newtarget
.empty()) {
599 LOG
<<prefix
<<qname
<<": status=got a CNAME referral, starting over with "<<newtarget
<<endl
;
600 set
<GetBestNSAnswer
>beenthere2
;
601 return doResolve(newtarget
, qtype
, ret
,0,beenthere2
);
603 if(nsset
.empty() && !d_lwr
.d_rcode
) {
604 LOG
<<prefix
<<qname
<<": status=noerror, other types may exist, but we are done "<<(negindic
? "(have negative SOA)" : "")<<endl
;
607 else if(realreferral
) {
608 LOG
<<prefix
<<qname
<<": status=did not resolve, got "<<nsset
.size()<<" NS, looping to them"<<endl
;
614 LOG
<<prefix
<<qname
<<": status=NS "<<*tns
<<" is lame for '"<<auth
<<"', trying sibling NS"<<endl
;
615 s_throttle
.throttle(d_now
.tv_sec
, make_tuple(*remoteIP
, qname
, qtype
.getCode()),60,0);
622 void SyncRes::addCruft(const string
&qname
, vector
<DNSResourceRecord
>& ret
)
624 for(vector
<DNSResourceRecord
>::const_iterator k
=ret
.begin();k
!=ret
.end();++k
) // don't add stuff to an NXDOMAIN!
625 if(k
->d_place
==DNSResourceRecord::AUTHORITY
&& k
->qtype
==QType(QType::SOA
))
628 // LOG<<qname<<": Adding best authority records from cache"<<endl;
629 // addAuthorityRecords(qname,ret,0);
630 // LOG<<qname<<": Done adding best authority records."<<endl;
632 LOG
<<d_prefix
<<qname
<<": Starting additional processing"<<endl
;
633 vector
<DNSResourceRecord
> addit
;
634 static optional
<bool> l_doIPv6AP
;
636 l_doIPv6AP
=::arg().mustDo("aaaa-additional-processing");
638 for(vector
<DNSResourceRecord
>::const_iterator k
=ret
.begin();k
!=ret
.end();++k
)
639 if((k
->d_place
==DNSResourceRecord::ANSWER
&& k
->qtype
==QType(QType::MX
)) ||
640 ((k
->d_place
==DNSResourceRecord::AUTHORITY
|| k
->d_place
==DNSResourceRecord::ANSWER
) && k
->qtype
==QType(QType::NS
))) {
641 LOG
<<d_prefix
<<qname
<<": record '"<<k
->content
<<"|"<<k
->qtype
.getName()<<"' needs IP for additional processing"<<endl
;
642 set
<GetBestNSAnswer
>beenthere
;
643 if(k
->qtype
==QType(QType::MX
)) {
644 pair
<string
,string
> prioServer
=splitField(k
->content
,' ');
645 doResolve(prioServer
.second
, QType(QType::A
), addit
, 1, beenthere
);
647 doResolve(prioServer
.second
, QType(QType::AAAA
), addit
, 1, beenthere
);
650 doResolve(k
->content
,QType(QType::A
),addit
,1,beenthere
);
652 doResolve(k
->content
,QType(QType::AAAA
),addit
,1,beenthere
);
656 for(vector
<DNSResourceRecord
>::iterator k
=addit
.begin();k
!=addit
.end();++k
) {
657 if(k
->qtype
.getCode()==QType::A
|| k
->qtype
.getCode()==QType::AAAA
) {
658 k
->d_place
=DNSResourceRecord::ADDITIONAL
;
662 LOG
<<d_prefix
<<qname
<<": Done with additional processing"<<endl
;
665 void SyncRes::addAuthorityRecords(const string
& qname
, vector
<DNSResourceRecord
>& ret
, int depth
)
667 set
<DNSResourceRecord
> bestns
;
668 set
<GetBestNSAnswer
>beenthere
;
669 getBestNSFromCache(qname
, bestns
, depth
,beenthere
);
671 for(set
<DNSResourceRecord
>::const_iterator k
=bestns
.begin();k
!=bestns
.end();++k
) {
672 DNSResourceRecord ns
=*k
;
673 ns
.d_place
=DNSResourceRecord::AUTHORITY
;
674 ns
.ttl
-=d_now
.tv_sec
;