root/trunk/pdns/pdns/syncres.cc @ 228

Revision 228, 18.9 KB (checked in by ahu, 9 years ago)

b.root
pdns_recursor speedups
mysql support for ports again
valgrind fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to author date id revision
Line 
1/*
2    PowerDNS Versatile Database Driven Nameserver
3    Copyright (C) 2003  PowerDNS.COM BV
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18*/
19
20#include "utility.hh"
21#include "syncres.hh"
22#include <iostream>
23#include <map>
24#include <algorithm>
25#include <set>
26#include <cerrno>
27#include <cstdio>
28#include <cstdlib>
29#include <utility>
30#include <deque>
31#include "logger.hh"
32#include "misc.hh"
33#include "arguments.hh"
34#include "lwres.hh"
35#include "recursor_cache.hh"
36
37extern MemRecursorCache RC;
38
39map<string,NegCacheEntry> SyncRes::s_negcache;   
40unsigned int SyncRes::s_queries;
41unsigned int SyncRes::s_outqueries;
42unsigned int SyncRes::s_throttledqueries;
43unsigned int SyncRes::s_nodelegated;
44bool SyncRes::s_log;
45
46#define LOG if(s_log)L<<Logger::Warning
47
48Throttle<string> SyncRes::s_throttle;
49
50/** everything begins here - this is the entry point just after receiving a packet */
51int SyncRes::beginResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret)
52{
53  set<GetBestNSAnswer> beenthere;
54  s_queries++;
55  int res=doResolve(qname, qtype, ret,0,beenthere);
56  if(!res)
57    addCruft(qname, ret);
58  return res;
59}
60
61int SyncRes::doResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere)
62{
63  string prefix(d_prefix);
64  prefix.append(depth, ' ');
65 
66  int res;
67  if(!(d_nocache && qtype.getCode()==QType::NS && qname.empty())) {
68    if(doCNAMECacheCheck(qname,qtype,ret,depth,res)) // will reroute us if needed
69      return res;
70   
71    if(doCacheCheck(qname,qtype,ret,depth,res)) // we done
72      return res;
73  }
74
75  if(d_cacheonly)
76    return 0;
77
78  LOG<<prefix<<qname<<": No cache hit for '"<<qname<<"|"<<qtype.getName()<<"', trying to find an appropriate NS record"<<endl;
79
80  string subdomain(qname);
81
82  set<string> nsset;
83  for(int tries=0;tries<2 && nsset.empty();++tries) {
84    subdomain=getBestNSNamesFromCache(subdomain,nsset,depth, beenthere); //  pass beenthere to both occasions
85
86    if(nsset.empty()) { // must've lost root records
87      LOG<<prefix<<qname<<": our root expired, repriming from hints and retrying"<<endl;
88      primeHints();
89    }
90  }
91
92
93  if(!(res=doResolveAt(nsset,subdomain,qname,qtype,ret,depth, beenthere)))
94    return 0;
95 
96  LOG<<prefix<<qname<<": failed"<<endl;
97  return res<0 ? RCode::ServFail : res;
98}
99
100string SyncRes::getA(const string &qname, int depth, set<GetBestNSAnswer>& beenthere)
101{
102  vector<DNSResourceRecord> res;
103  string ret;
104
105  if(!doResolve(qname,QType(QType::A), res,depth+1,beenthere) && !res.empty()) 
106    ret=res[res.size()-1].content; // last entry, in case of CNAME in between
107
108  return ret;
109}
110
111void SyncRes::getBestNSFromCache(const string &qname, set<DNSResourceRecord>&bestns, int depth, set<GetBestNSAnswer>& beenthere)
112{
113  string prefix(d_prefix), subdomain(qname);
114  prefix.append(depth, ' ');
115  bestns.clear();
116
117  do {
118    LOG<<prefix<<qname<<": Checking if we have NS in cache for '"<<subdomain<<"'"<<endl;
119    set<DNSResourceRecord>ns;
120    if(RC.get(subdomain,QType(QType::NS),&ns)>0) {
121      for(set<DNSResourceRecord>::const_iterator k=ns.begin();k!=ns.end();++k) {
122        if(k->ttl>(unsigned int)time(0)) { 
123          set<DNSResourceRecord>aset;
124          if(!endsOn(k->content,subdomain) || RC.get(k->content,QType(QType::A),&aset) > 5) {
125            bestns.insert(*k);
126            LOG<<prefix<<qname<<": NS (with ip, or non-glue) in cache for '"<<subdomain<<"' -> '"<<k->content<<"'"<<endl;
127            LOG<<prefix<<qname<<": within bailiwick: "<<endsOn(k->content,subdomain);
128            if(!aset.empty())
129              L<<", in cache, ttl="<<((time_t)aset.begin()->ttl-time(0))<<endl;
130            else
131              L<<", not in cache"<<endl;
132          }
133          else
134            LOG<<prefix<<qname<<": NS in cache for '"<<subdomain<<"', but needs glue ("<<k->content<<") which we miss or is expired"<<endl;
135        }
136      }
137      if(!bestns.empty()) {
138        GetBestNSAnswer answer;
139        answer.qname=toLower(qname); answer.bestns=bestns;
140        if(beenthere.count(answer)) {
141          LOG<<prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' but part of LOOP! Trying less specific NS"<<endl;
142          for( set<GetBestNSAnswer>::const_iterator j=beenthere.begin();j!=beenthere.end();++j)
143            LOG<<prefix<<qname<<": beenthere: "<<j->qname<<" ("<<j->bestns.size()<<")"<<endl;
144          bestns.clear();
145        }
146        else {
147          beenthere.insert(answer);
148          LOG<<prefix<<qname<<": We have NS in cache for '"<<subdomain<<"'"<<endl;
149          return;
150        }
151      }
152    }
153  }while(chopOff(subdomain));
154}
155
156
157/** doesn't actually do the work, leaves that to getBestNSFromCache */
158string SyncRes::getBestNSNamesFromCache(const string &qname,set<string>& nsset, int depth, set<GetBestNSAnswer>&beenthere)
159{
160  string subdomain(qname);
161
162  set<DNSResourceRecord> bestns;
163  getBestNSFromCache(subdomain, bestns, depth, beenthere);
164
165  for(set<DNSResourceRecord>::const_iterator k=bestns.begin();k!=bestns.end();++k) {
166    nsset.insert(k->content);
167    subdomain=k->qname;
168  }
169  return subdomain;
170}
171
172bool SyncRes::doCNAMECacheCheck(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res)
173{
174  string prefix(d_prefix), tuple=toLower(qname)+"|CNAME";
175  prefix.append(depth, ' ');
176
177  if(depth>10) {
178    LOG<<prefix<<qname<<": CNAME loop too deep, depth="<<depth<<endl;
179    res=RCode::ServFail;
180    return true;
181  }
182 
183  LOG<<prefix<<qname<<": Looking for CNAME cache hit of '"<<tuple<<"'"<<endl;
184  set<DNSResourceRecord> cset;
185  if(RC.get(qname,QType(QType::CNAME),&cset) > 0) {
186    for(set<DNSResourceRecord>::const_iterator j=cset.begin();j!=cset.end();++j) {
187      if(j->ttl>(unsigned int)time(0)) {
188        LOG<<prefix<<qname<<": Found cache CNAME hit for '"<<tuple<<"' to '"<<j->content<<"'"<<endl;   
189        DNSResourceRecord rr=*j;
190        rr.ttl-=time(0);
191        ret.push_back(rr);
192        if(!(qtype==QType(QType::CNAME))) {// perhaps they really wanted a CNAME!
193          set<GetBestNSAnswer>beenthere;
194          res=doResolve(j->content, qtype, ret, depth+1, beenthere);
195        }
196        return true;
197      }
198    }
199  }
200  LOG<<prefix<<qname<<": No CNAME cache hit of '"<<tuple<<"' found"<<endl;
201  return false;
202}
203
204
205
206
207bool SyncRes::doCacheCheck(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res)
208{
209  bool giveNegative=false;
210  string prefix(d_prefix), tuple;
211  prefix.append(depth, ' ');
212
213  string sqname(qname);
214  QType sqt(qtype);
215  u_int32_t sttl=0;
216
217  if(s_negcache.count(toLower(qname))) {
218    res=0;
219    map<string,NegCacheEntry>::const_iterator ni=s_negcache.find(toLower(qname));
220    if(time(0) < ni->second.ttd) {
221      sttl=ni->second.ttd-time(0);
222      LOG<<prefix<<qname<<": Entire record '"<<toLower(qname)<<"', is negatively cached for another "<<sttl<<" seconds"<<endl;
223      res=RCode::NXDomain; 
224      giveNegative=true;
225      sqname=ni->second.name;
226      sqt="SOA";
227
228    }
229    else {
230      LOG<<prefix<<qname<<": Entire record '"<<toLower(qname)<<"' was negatively cached, but entry expired"<<endl;
231      s_negcache.erase(toLower(qname));
232    }
233  }
234
235  if(!giveNegative) { // let's try some more
236    tuple=toLower(qname)+"|"+qtype.getName();
237    LOG<<prefix<<qname<<": Looking for direct cache hit of '"<<tuple<<"', negative cached: "<<s_negcache.count(tuple)<<endl;
238
239    res=0;
240    map<string,NegCacheEntry>::const_iterator ni=s_negcache.find(tuple);
241    if(ni!=s_negcache.end()) {
242      if(time(0) < ni->second.ttd) {
243        sttl=ni->second.ttd-time(0);
244        LOG<<prefix<<qname<<": "<<qtype.getName()<<" is negatively cached for another "<<sttl<<" seconds"<<endl;
245        res=RCode::NoError; // only this record doesn't exist
246        giveNegative=true;
247        sqname=ni->second.name;
248        sqt="SOA";
249      }
250      else {
251        LOG<<prefix<<qname<<": "<<qtype.getName()<<" was negatively cached, but entry expired"<<endl;
252        s_negcache.erase(toLower(tuple));
253      }
254    }
255  }
256
257  set<DNSResourceRecord> cset;
258  bool found=false, expired=false;
259  if(RC.get(sqname,sqt,&cset)>0) {
260    LOG<<prefix<<qname<<": Found cache hit for "<<sqt.getName()<<": ";
261    for(set<DNSResourceRecord>::const_iterator j=cset.begin();j!=cset.end();++j) {
262      LOG<<j->content;
263      if(j->ttl>(unsigned int)time(0)) {
264        DNSResourceRecord rr=*j;
265        rr.ttl-=time(0);
266        if(giveNegative) {
267          rr.d_place=DNSResourceRecord::AUTHORITY;
268          rr.ttl=sttl;
269        }
270        ret.push_back(rr);
271        LOG<<"[ttl="<<rr.ttl<<"] ";
272        found=true;
273      }
274      else {
275        LOG<<"[expired] ";
276        expired=true;
277      }
278    }
279 
280    LOG<<endl;
281    if(found && !expired) 
282      return true;
283    else
284      LOG<<prefix<<qname<<": cache had only stale entries"<<endl;
285  }
286  return false;
287}
288
289bool SyncRes::moreSpecificThan(const string& a, const string &b)
290{
291  int counta=!a.empty(), countb=!b.empty();
292 
293  for(string::size_type n=0;n<a.size();++n)
294    if(a[n]=='.')
295      counta++;
296  for(string::size_type n=0;n<b.size();++n)
297    if(b[n]=='.')
298      countb++;
299  return counta>countb;
300}
301
302static map<string,DecayingEwma> nsSpeeds;
303
304struct speedOrder
305{
306  speedOrder(map<string,double> &speeds) : d_speeds(speeds) {}
307  bool operator()(const string &a, const string &b) const
308  {
309    return d_speeds[a] < d_speeds[b];
310  }
311  map<string,double>& d_speeds;
312};
313
314inline vector<string> SyncRes::shuffle(set<string> &nameservers, const string &prefix)
315{
316  vector<string> rnameservers;
317  rnameservers.reserve(nameservers.size());
318  map<string,double> speeds;
319
320  for(set<string>::const_iterator i=nameservers.begin();i!=nameservers.end();++i) {
321    rnameservers.push_back(*i);
322    speeds[*i]=nsSpeeds[toLower(*i)].get();
323  }
324  random_shuffle(rnameservers.begin(),rnameservers.end());
325  stable_sort(rnameservers.begin(),rnameservers.end(),speedOrder(speeds));
326 
327  if(s_log) {
328    L<<Logger::Warning<<prefix<<"Nameservers: ";
329    for(vector<string>::const_iterator i=rnameservers.begin();i!=rnameservers.end();++i) {
330      if(i!=rnameservers.begin()) {
331        L<<", ";
332        if(!((i-rnameservers.begin())%4))
333          L<<endl<<Logger::Warning<<prefix<<"             ";
334      }
335      L<<*i<<"(" << (int)(speeds[*i]/1000.0) <<"ms)";
336    }
337    L<<endl;
338  }
339 
340     
341
342  return rnameservers;
343}
344
345/** returns -1 in case of no results, rcode otherwise */
346int SyncRes::doResolveAt(set<string> nameservers, string auth, const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, 
347                int depth, set<GetBestNSAnswer>&beenthere)
348{
349  string prefix(d_prefix);
350  prefix.append(depth, ' ');
351 
352  LWRes::res_t result;
353
354  LOG<<prefix<<qname<<": Cache consultations done, have "<<nameservers.size()<<" NS to contact"<<endl;
355
356  for(;;) { // we may get more specific nameservers
357    result.clear();
358
359    vector<string> rnameservers=shuffle(nameservers, prefix+qname+": ");
360
361    for(vector<string>::const_iterator tns=rnameservers.begin();;++tns) { 
362      if(tns==rnameservers.end()) {
363        LOG<<prefix<<qname<<": Failed to resolve via any of the "<<rnameservers.size()<<" offered NS"<<endl;
364        return -1;
365      }
366      if(qname==*tns && qtype.getCode()==QType::A) {
367        LOG<<prefix<<qname<<": Not using NS to resolve itself!"<<endl;
368        continue;
369      }
370      LOG<<prefix<<qname<<": Trying to resolve NS "<<*tns<<" ("<<1+tns-rnameservers.begin()<<"/"<<rnameservers.size()<<")"<<endl;
371      string remoteIP=getA(*tns, depth+1,beenthere);
372      if(remoteIP.empty()) {
373        LOG<<prefix<<qname<<": Failed to get IP for NS "<<*tns<<", trying next if available"<<endl;
374        continue;
375      }
376      LOG<<prefix<<qname<<": Resolved '"+auth+"' NS "<<*tns<<" to "<<remoteIP<<", asking '"<<qname<<"|"<<qtype.getName()<<"'"<<endl;
377
378      if(s_throttle.shouldThrottle(remoteIP+"|"+qname+"|"+qtype.getName())) {
379        LOG<<prefix<<qname<<": query throttled "<<endl;
380        s_throttledqueries++;
381        d_throttledqueries++;
382        continue;
383      }
384      else {
385        s_outqueries++;
386        d_outqueries++;
387        if(d_lwr.asyncresolve(remoteIP,qname.c_str(),qtype.getCode())!=1) { // <- we go out on the wire!
388          LOG<<prefix<<qname<<": error resolving (perhaps timeout?)"<<endl;
389          nsSpeeds[toLower(*tns)].submit(1000000); // 1 sec
390          s_throttle.throttle(remoteIP+"|"+qname+"|"+qtype.getName(),20,5);
391          continue;
392        }
393      }
394
395      result=d_lwr.result();
396      if(d_lwr.d_rcode==RCode::ServFail) {
397        LOG<<prefix<<qname<<": "<<*tns<<" returned a ServFail, trying sibling NS"<<endl;
398        s_throttle.throttle(remoteIP+"|"+qname+"|"+qtype.getName(),60,3);
399        continue;
400      }
401      LOG<<prefix<<qname<<": Got "<<result.size()<<" answers from "<<*tns<<" ("<<remoteIP<<"), rcode="<<d_lwr.d_rcode<<", in "<<d_lwr.d_usec/1000<<"ms"<<endl;
402      nsSpeeds[toLower(*tns)].submit(d_lwr.d_usec);
403
404      map<string,set<DNSResourceRecord> > tcache;
405      // reap all answers from this packet that are acceptable
406      for(LWRes::res_t::const_iterator i=result.begin();i!=result.end();++i) {
407        LOG<<prefix<<qname<<": accept answer '"<<i->qname<<"|"<<i->qtype.getName()<<"|"<<i->content<<"' from '"<<auth<<"' nameservers? ";
408
409
410        if(endsOn(i->qname, auth)) {
411          if(d_lwr.d_aabit && d_lwr.d_rcode==RCode::NoError && i->d_place==DNSResourceRecord::ANSWER && arg().contains("delegation-only",auth)) {
412            LOG<<"NO! Is from delegation-only zone"<<endl;
413            s_nodelegated++;
414            return RCode::NXDomain;
415          }
416          else {
417            LOG<<"YES!"<<endl;
418           
419            DNSResourceRecord rr=*i;
420            rr.d_place=DNSResourceRecord::ANSWER;
421            rr.ttl+=time(0);
422            //    rr.ttl=time(0)+10+10*rr.qtype.getCode();
423            tcache[toLower(i->qname)+"|"+i->qtype.getName()].insert(rr);
424          }
425        }         
426        else
427          LOG<<"NO!"<<endl;
428      }
429   
430      // supplant
431      for(map<string,set<DNSResourceRecord> >::const_iterator i=tcache.begin();i!=tcache.end();++i) {
432        vector<string>parts;
433        stringtok(parts,i->first,"|");
434        QType qt;
435        if(parts.size()==2) {
436          qt=parts[1];
437          RC.replace(parts[0],qt,i->second);
438        }
439        else {
440          qt=parts[0];
441          RC.replace("",qt,i->second);
442        }
443      }
444      set<string> nsset; 
445      LOG<<prefix<<qname<<": determining status after receiving this packet"<<endl;
446
447      bool done=false, realreferral=false, negindic=false;
448      string newauth, soaname, newtarget;
449
450      for(LWRes::res_t::const_iterator i=result.begin();i!=result.end();++i) {
451        if(i->d_place==DNSResourceRecord::AUTHORITY && endsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA && 
452           d_lwr.d_rcode==RCode::NXDomain) {
453          LOG<<prefix<<qname<<": got negative caching indication for RECORD '"<<toLower(qname)+"'"<<endl;
454          ret.push_back(*i);
455
456          NegCacheEntry ne;
457          ne.name=i->qname;
458          ne.ttd=time(0)+i->ttl;
459          s_negcache[toLower(qname)]=ne;
460          negindic=true;
461        }
462        else if(i->d_place==DNSResourceRecord::ANSWER && i->qname==qname && i->qtype.getCode()==QType::CNAME && (!(qtype==QType(QType::CNAME)))) {
463          ret.push_back(*i);
464          newtarget=i->content;
465        }
466        // for ANY answers we *must* have an authoritive answer
467        else if(i->d_place==DNSResourceRecord::ANSWER && toLower(i->qname)==toLower(qname) && (i->qtype==qtype || ( qtype==QType(QType::ANY) && 
468                                                                                                                    d_lwr.d_aabit)))  {
469          LOG<<prefix<<qname<<": answer is in: resolved to '"<<i->content<<"|"<<i->qtype.getName()<<"'"<<endl;
470          done=true;
471          ret.push_back(*i);
472        }
473        else if(i->d_place==DNSResourceRecord::AUTHORITY && endsOn(qname,i->qname) && i->qtype.getCode()==QType::NS) { 
474          if(moreSpecificThan(i->qname,auth)) {
475            newauth=i->qname;
476            LOG<<prefix<<qname<<": got NS record '"<<i->qname<<"' -> '"<<i->content<<"'"<<endl;
477            realreferral=true;
478          }
479          else 
480            LOG<<prefix<<qname<<": got upwards/level NS record '"<<i->qname<<"' -> '"<<i->content<<"', had '"<<auth<<"'"<<endl;
481          nsset.insert(toLower(i->content));
482        }
483        else if(i->d_place==DNSResourceRecord::AUTHORITY && endsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA && 
484           d_lwr.d_rcode==RCode::NoError) {
485          LOG<<prefix<<qname<<": got negative caching indication for '"<<toLower(qname)+"|"+i->qtype.getName()+"'"<<endl;
486          ret.push_back(*i);
487         
488          NegCacheEntry ne;
489          ne.name=i->qname;
490          ne.ttd=time(0)+i->ttl;
491          s_negcache[toLower(qname)+"|"+qtype.getName()]=ne;
492          negindic=true;
493        }
494      }
495
496      if(done){ 
497        LOG<<prefix<<qname<<": status=got results, this level of recursion done"<<endl;
498        return 0;
499      }
500      if(d_lwr.d_rcode==RCode::NXDomain) {
501        LOG<<prefix<<qname<<": status=NXDOMAIN, we are done "<<(negindic ? "(have negative SOA)" : "")<<endl;
502        return RCode::NXDomain;
503      }
504      if(!newtarget.empty()) {
505        LOG<<prefix<<qname<<": status=got a CNAME referral, starting over with "<<newtarget<<endl;
506        set<GetBestNSAnswer>beenthere2;
507        return doResolve(newtarget, qtype, ret,0,beenthere2);
508      }
509      if(nsset.empty() && !d_lwr.d_rcode) {
510        LOG<<prefix<<qname<<": status=noerror, other types may exist, but we are done "<<(negindic ? "(have negative SOA)" : "")<<endl;
511        return 0;
512      }
513      else if(realreferral) {
514        LOG<<prefix<<qname<<": status=did not resolve, got "<<nsset.size()<<" NS, looping to them"<<endl;
515        auth=newauth;
516        nameservers=nsset;
517        break; 
518      }
519      else {
520        LOG<<prefix<<qname<<": status=NS "<<*tns<<" is lame for '"<<auth<<"', trying sibling NS"<<endl;
521        s_throttle.throttle(remoteIP+"|"+qname+"|"+qtype.getName(),60,0);
522      }
523    }
524  }
525  return -1;
526}
527
528void SyncRes::addCruft(const string &qname, vector<DNSResourceRecord>& ret)
529{
530  for(vector<DNSResourceRecord>::const_iterator k=ret.begin();k!=ret.end();++k)  // don't add stuff to an NXDOMAIN!
531    if(k->d_place==DNSResourceRecord::AUTHORITY && k->qtype==QType(QType::SOA))
532      return;
533
534  //  LOG<<qname<<": Adding best authority records from cache"<<endl;
535  // addAuthorityRecords(qname,ret,0);
536  // LOG<<qname<<": Done adding best authority records."<<endl;
537
538  LOG<<d_prefix<<qname<<": Starting additional processing"<<endl;
539  vector<DNSResourceRecord> addit;
540  for(vector<DNSResourceRecord>::const_iterator k=ret.begin();k!=ret.end();++k) 
541    if((k->d_place==DNSResourceRecord::ANSWER && k->qtype==QType(QType::MX)) || 
542       ((k->d_place==DNSResourceRecord::AUTHORITY || k->d_place==DNSResourceRecord::ANSWER) && k->qtype==QType(QType::NS))) {
543      LOG<<d_prefix<<qname<<": record '"<<k->content<<"|"<<k->qtype.getName()<<"' needs IP for additional processing"<<endl;
544      set<GetBestNSAnswer>beenthere;
545      doResolve(k->content,QType(QType::A),addit,1,beenthere);
546      if(arg().mustDo("aaaa-additional-processing"))
547        doResolve(k->content,QType(QType::AAAA),addit,1,beenthere);
548    }
549 
550  for(vector<DNSResourceRecord>::iterator k=addit.begin();k!=addit.end();++k) {
551    if(k->qtype.getCode()==QType::A || k->qtype.getCode()==QType::AAAA) {
552      k->d_place=DNSResourceRecord::ADDITIONAL;
553      ret.push_back(*k);
554    }
555  }
556  LOG<<d_prefix<<qname<<": Done with additional processing"<<endl;
557}
558
559void SyncRes::addAuthorityRecords(const string& qname, vector<DNSResourceRecord>& ret, int depth)
560{
561  set<DNSResourceRecord> bestns;
562  set<GetBestNSAnswer>beenthere;
563  getBestNSFromCache(qname, bestns, depth,beenthere);
564  for(set<DNSResourceRecord>::const_iterator k=bestns.begin();k!=bestns.end();++k) {
565    DNSResourceRecord ns=*k;
566    ns.d_place=DNSResourceRecord::AUTHORITY;
567    ns.ttl-=time(0);
568    ret.push_back(ns);
569  }
570}
Note: See TracBrowser for help on using the browser.