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

Revision 440, 20.0 KB (checked in by ahu, 8 years ago)

fix TCP related crashes due to HUUUUGE daum.net records (3.5kbyte!)

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