]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/ueberbackend.cc
Merge pull request #4467 from ahupowerdns/deresource
[thirdparty/pdns.git] / pdns / ueberbackend.cc
CommitLineData
12c86877
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
e0d84497 3 Copyright (C) 2005 - 2011 PowerDNS.COM BV
12c86877
BH
4
5 This program is free software; you can redistribute it and/or modify
923a2384
BH
6 it under the terms of the GNU General Public License version 2 as
7 published by the Free Software Foundation
12c86877 8
f782fe38
MH
9 Additionally, the license of this program contains a special
10 exception which allows to distribute the program in binary form when
11 it is linked against OpenSSL.
12
12c86877
BH
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
06bd9ccf 20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
12c86877 21*/
870a0fe4
AT
22#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
cb433f9c
BH
25#include <boost/archive/binary_iarchive.hpp>
26#include <boost/archive/binary_oarchive.hpp>
27
ba45c866 28#include "packetcache.hh"
12c86877 29#include "utility.hh"
c6566265 30
c6566265 31
12c86877
BH
32#include <string>
33#include <map>
34#include <sys/types.h>
cb433f9c 35#include <sstream>
12c86877
BH
36#include <errno.h>
37#include <iostream>
38#include <sstream>
39#include <functional>
fa8fd4d2 40
12c86877
BH
41#include "dns.hh"
42#include "arguments.hh"
43#include "dnsbackend.hh"
44#include "ueberbackend.hh"
45#include "dnspacket.hh"
46#include "logger.hh"
47#include "statbag.hh"
12c86877
BH
48
49extern StatBag S;
50
51vector<UeberBackend *>UeberBackend::instances;
52pthread_mutex_t UeberBackend::instances_lock=PTHREAD_MUTEX_INITIALIZER;
53
54sem_t UeberBackend::d_dynserialize;
12c86877
BH
55
56// initially we are blocked
57bool UeberBackend::d_go=false;
58pthread_mutex_t UeberBackend::d_mut = PTHREAD_MUTEX_INITIALIZER;
59pthread_cond_t UeberBackend::d_cond = PTHREAD_COND_INITIALIZER;
60
12c86877
BH
61//! Loads a module and reports it to all UeberBackend threads
62bool UeberBackend::loadmodule(const string &name)
63{
74caf870
KM
64 L<<Logger::Warning <<"Loading '"<<name<<"'" << endl;
65
12c86877 66 void *dlib=dlopen(name.c_str(), RTLD_NOW);
74caf870 67
12c86877 68 if(dlib == NULL) {
74caf870 69 L<<Logger::Error <<"Unable to load module '"<<name<<"': "<<dlerror() << endl;
12c86877
BH
70 return false;
71 }
74caf870 72
12c86877 73 return true;
12c86877
BH
74}
75
76void UeberBackend::go(void)
77{
78 pthread_mutex_lock(&d_mut);
79 d_go=true;
80 pthread_cond_broadcast(&d_cond);
81 pthread_mutex_unlock(&d_mut);
82}
83
675fa24c 84bool UeberBackend::getDomainInfo(const DNSName &domain, DomainInfo &di)
12c86877
BH
85{
86 for(vector<DNSBackend *>::const_iterator i=backends.begin();i!=backends.end();++i)
87 if((*i)->getDomainInfo(domain, di))
88 return true;
89 return false;
90}
91
675fa24c 92bool UeberBackend::createDomain(const DNSName &domain)
487cf033 93{
ef7cd021 94 for(DNSBackend* mydb : backends) {
487cf033 95 if(mydb->createDomain(domain)) {
487cf033
CH
96 return true;
97 }
98 }
99 return false;
100}
101
82cc0761 102bool UeberBackend::addDomainKey(const DNSName& name, const DNSBackend::KeyData& key, int64_t& id)
c0273500 103{
82cc0761 104 id = -1;
ef7cd021 105 for(DNSBackend* db : backends) {
82cc0761
BZ
106 if(db->addDomainKey(name, key, id))
107 return true;
c0273500 108 }
82cc0761 109 return false;
c0273500 110}
675fa24c 111bool UeberBackend::getDomainKeys(const DNSName& name, unsigned int kind, std::vector<DNSBackend::KeyData>& keys)
c0273500 112{
ef7cd021 113 for(DNSBackend* db : backends) {
c0273500
BH
114 if(db->getDomainKeys(name, kind, keys))
115 return true;
116 }
117 return false;
118}
119
675fa24c 120bool UeberBackend::getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string> >& meta)
ac993e0a 121{
ef7cd021 122 for(DNSBackend* db : backends) {
ac993e0a
AT
123 if(db->getAllDomainMetadata(name, meta))
124 return true;
125 }
126 return false;
127}
128
675fa24c 129bool UeberBackend::getDomainMetadata(const DNSName& name, const std::string& kind, std::vector<std::string>& meta)
c0273500 130{
ef7cd021 131 for(DNSBackend* db : backends) {
c0273500
BH
132 if(db->getDomainMetadata(name, kind, meta))
133 return true;
134 }
135 return false;
136}
137
675fa24c 138bool UeberBackend::setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector<std::string>& meta)
c0273500 139{
ef7cd021 140 for(DNSBackend* db : backends) {
c0273500
BH
141 if(db->setDomainMetadata(name, kind, meta))
142 return true;
143 }
144 return false;
145}
146
675fa24c 147bool UeberBackend::activateDomainKey(const DNSName& name, unsigned int id)
4496f66f 148{
ef7cd021 149 for(DNSBackend* db : backends) {
4496f66f
BH
150 if(db->activateDomainKey(name, id))
151 return true;
152 }
153 return false;
154}
155
675fa24c 156bool UeberBackend::deactivateDomainKey(const DNSName& name, unsigned int id)
4496f66f 157{
ef7cd021 158 for(DNSBackend* db : backends) {
4496f66f
BH
159 if(db->deactivateDomainKey(name, id))
160 return true;
161 }
162 return false;
163}
164
675fa24c 165bool UeberBackend::removeDomainKey(const DNSName& name, unsigned int id)
4496f66f 166{
ef7cd021 167 for(DNSBackend* db : backends) {
4496f66f
BH
168 if(db->removeDomainKey(name, id))
169 return true;
170 }
171 return false;
172}
173
c0273500 174
675fa24c 175bool UeberBackend::getTSIGKey(const DNSName& name, DNSName* algorithm, string* content)
78bcb858 176{
ef7cd021 177 for(DNSBackend* db : backends) {
78bcb858
BH
178 if(db->getTSIGKey(name, algorithm, content))
179 return true;
180 }
181 return false;
182}
183
184
675fa24c 185bool UeberBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content)
6f872b78 186{
ef7cd021 187 for(DNSBackend* db : backends) {
6f872b78
AT
188 if(db->setTSIGKey(name, algorithm, content))
189 return true;
190 }
191 return false;
192}
193
675fa24c 194bool UeberBackend::deleteTSIGKey(const DNSName& name)
6f872b78 195{
ef7cd021 196 for(DNSBackend* db : backends) {
6f872b78
AT
197 if(db->deleteTSIGKey(name))
198 return true;
199 }
200 return false;
201}
202
203bool UeberBackend::getTSIGKeys(std::vector< struct TSIGKey > &keys)
204{
ef7cd021 205 for(DNSBackend* db : backends) {
6f872b78
AT
206 db->getTSIGKeys(keys);
207 }
208 return true;
209}
210
12c86877
BH
211void UeberBackend::reload()
212{
213 for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
214 {
215 ( *i )->reload();
216 }
217}
218
973ad2b5 219void UeberBackend::rediscover(string *status)
12c86877 220{
20ca8e7d 221
12c86877
BH
222 for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
223 {
973ad2b5
BH
224 string tmpstr;
225 ( *i )->rediscover(&tmpstr);
6242d8a4
KM
226 if(status)
227 *status+=tmpstr + (i!=backends.begin() ? "\n" : "");
12c86877
BH
228 }
229}
230
231
232void UeberBackend::getUnfreshSlaveInfos(vector<DomainInfo>* domains)
233{
234 for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
235 {
236 ( *i )->getUnfreshSlaveInfos( domains );
237 }
238}
239
240
241
242void UeberBackend::getUpdatedMasters(vector<DomainInfo>* domains)
243{
244 for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
245 {
246 ( *i )->getUpdatedMasters( domains );
247 }
248}
249
675fa24c 250bool UeberBackend::getAuth(DNSPacket *p, SOAData *sd, const DNSName &target)
c14bc34a 251{
5b9ac871
KM
252 bool found = false;
253 int cstat;
9105d7b3 254 DNSName choppedOff(target);
5b9ac871
KM
255 vector<pair<size_t, SOAData> > bestmatch (backends.size(), make_pair(target.wirelength()+1, SOAData()));
256 do {
257
258 // Check cache
259 if(sd->db != (DNSBackend *)-1 && (d_cache_ttl || d_negcache_ttl)) {
260 d_question.qtype = QType::SOA;
9105d7b3 261 d_question.qname = choppedOff;
5b9ac871
KM
262 d_question.zoneId = -1;
263
264 cstat = cacheHas(d_question,d_answers);
265
266 if(cstat == 1 && !d_answers.empty() && d_cache_ttl) {
c348fec2 267 DLOG(L<<Logger::Error<<"has pos cache entry: "<<choppedOff<<endl);
90ba52e0 268 fillSOAData(d_answers[0], *sd);
269
5b9ac871 270 sd->db = 0;
9105d7b3 271 sd->qname = choppedOff;
5b9ac871
KM
272 goto found;
273 } else if(cstat == 0 && d_negcache_ttl) {
c348fec2 274 DLOG(L<<Logger::Error<<"has neg cache entry: "<<choppedOff<<endl);
5b9ac871 275 continue;
c14bc34a 276 }
c14bc34a 277 }
f70be3c3 278
5b9ac871 279 // Check backends
9105d7b3
RG
280 // A backend can respond to our SOA request with the 'best'
281 // match it has. For example, when asked the SOA for a.b.c.powerdns.com.
282 // it might respond with the SOA for powerdns.com.
283 // We then store that, keep querying the other backends in case
284 // one of them has a more specific SOA but don't bother
285 // asking this specific backend again for b.c.powerdns.com. or c.powerdns.com.
5b9ac871
KM
286 {
287 vector<DNSBackend *>::const_iterator i = backends.begin();
288 vector<pair<size_t, SOAData> >::iterator j = bestmatch.begin();
289 for(; i != backends.end() && j != bestmatch.end(); ++i, ++j) {
290
9105d7b3 291 DLOG(L<<Logger::Error<<"backend: "<<i-backends.begin()<<", qname: "<<choppedOff<<endl);
5b9ac871 292
9105d7b3 293 if(j->first < choppedOff.wirelength()) {
c348fec2 294 DLOG(L<<Logger::Error<<"skip this backend, we already know the 'higher' match: "<<j->second.qname<<endl);
5b9ac871 295 continue;
9105d7b3 296 } else if(j->first == choppedOff.wirelength()) {
c348fec2 297 DLOG(L<<Logger::Error<<"use 'higher' match: "<<j->second.qname<<endl);
5b9ac871
KM
298 *sd = j->second;
299 break;
300 } else {
9105d7b3
RG
301 DLOG(L<<Logger::Error<<"lookup: "<<choppedOff<<endl);
302 if((*i)->getAuth(p, sd, choppedOff)) {
5b9ac871
KM
303 DLOG(L<<Logger::Error<<"got: "<<sd->qname<<endl);
304 j->first = sd->qname.wirelength();
bee25428 305 j->second = *sd;
9105d7b3 306 if(sd->qname == choppedOff) {
5b9ac871
KM
307 break;
308 }
309 } else {
c348fec2 310 DLOG(L<<Logger::Error<<"no match for: "<<choppedOff<<endl);
5b9ac871
KM
311 }
312 }
f70be3c3 313 }
c14bc34a 314
5b9ac871
KM
315 // Add to cache
316 if(i == backends.end()) {
317 if(d_negcache_ttl) {
c348fec2 318 DLOG(L<<Logger::Error<<"add neg cache entry:"<<choppedOff<<endl);
9105d7b3 319 d_question.qname=choppedOff;
5b9ac871
KM
320 addNegCache(d_question);
321 }
322 continue;
323 } else if(d_cache_ttl) {
c348fec2 324 DLOG(L<<Logger::Error<<"add pos cache entry: "<<sd->qname<<endl);
c14bc34a
MZ
325 d_question.qtype = QType::SOA;
326 d_question.qname = sd->qname;
327 d_question.zoneId = -1;
328
90ba52e0 329 DNSZoneRecord rr;
330 rr.dr.d_name = sd->qname;
331 rr.dr.d_type = QType::SOA;
332
333 rr.dr.d_content = makeSOAContent(*sd);
334 rr.dr.d_ttl = sd->ttl;
c14bc34a 335 rr.domain_id = sd->domain_id;
90ba52e0 336
337 addCache(d_question, {rr});
5b9ac871 338 }
c14bc34a
MZ
339 }
340
5b9ac871
KM
341found:
342 if(found == (p->qtype == QType::DS)){
c348fec2 343 DLOG(L<<Logger::Error<<"found: "<<sd->qname<<endl);
5b9ac871
KM
344 return true;
345 } else {
c348fec2 346 DLOG(L<<Logger::Error<<"chasing next: "<<sd->qname<<endl);
5b9ac871
KM
347 found = true;
348 }
349
9105d7b3 350 } while(choppedOff.chopOff());
5b9ac871 351 return found;
c14bc34a
MZ
352}
353
675fa24c 354bool UeberBackend::getSOA(const DNSName &domain, SOAData &sd, DNSPacket *p)
12c86877
BH
355{
356 d_question.qtype=QType::SOA;
357 d_question.qname=domain;
358 d_question.zoneId=-1;
359
79ba7763
CH
360 int cstat=cacheHas(d_question,d_answers);
361 if(cstat==0) { // negative
362 return false;
12c86877 363 }
79ba7763 364 else if(cstat==1 && !d_answers.empty()) {
90ba52e0 365 fillSOAData(d_answers[0],sd);
79ba7763 366 sd.domain_id=d_answers[0].domain_id;
90ba52e0 367 sd.ttl=d_answers[0].dr.d_ttl;
79ba7763
CH
368 sd.db=0;
369 return true;
370 }
371
372 // not found in neg. or pos. cache, look it up
373 return getSOAUncached(domain, sd, p);
374}
375
675fa24c 376bool UeberBackend::getSOAUncached(const DNSName &domain, SOAData &sd, DNSPacket *p)
79ba7763
CH
377{
378 d_question.qtype=QType::SOA;
379 d_question.qname=domain;
380 d_question.zoneId=-1;
381
12c86877 382 for(vector<DNSBackend *>::const_iterator i=backends.begin();i!=backends.end();++i)
35933370 383 if((*i)->getSOA(domain, sd, p)) {
f1d64762 384 if( d_cache_ttl ) {
90ba52e0 385 DNSZoneRecord rr;
386 rr.dr.d_name = sd.qname;
387 rr.dr.d_type = QType::SOA;
388
389 rr.dr.d_content = makeSOAContent(sd);
390 rr.dr.d_ttl = sd.ttl;
391 rr.domain_id = sd.domain_id;
392
393 addCache(d_question, {rr});
394
f1d64762 395 }
12c86877
BH
396 return true;
397 }
398
79ba7763 399 addNegCache(d_question);
12c86877
BH
400 return false;
401}
402
675fa24c 403bool UeberBackend::superMasterBackend(const string &ip, const DNSName &domain, const vector<DNSResourceRecord>&nsset, string *nameserver, string *account, DNSBackend **db)
12c86877
BH
404{
405 for(vector<DNSBackend *>::const_iterator i=backends.begin();i!=backends.end();++i)
719f9024 406 if((*i)->superMasterBackend(ip, domain, nsset, nameserver, account, db))
12c86877
BH
407 return true;
408 return false;
12c86877
BH
409}
410
12c86877
BH
411UeberBackend::UeberBackend(const string &pname)
412{
12c86877
BH
413 pthread_mutex_lock(&instances_lock);
414 instances.push_back(this); // report to the static list of ourself
415 pthread_mutex_unlock(&instances_lock);
416
51d01c80
AT
417 d_negcached=0;
418 d_ancount=0;
419 domain_id=-1;
420 d_cached=0;
f1d64762
MZ
421 d_cache_ttl = ::arg().asNum("query-cache-ttl");
422 d_negcache_ttl = ::arg().asNum("negquery-cache-ttl");
423
12c86877
BH
424 tid=pthread_self();
425 stale=false;
426
e0d84497 427 backends=BackendMakers().all(pname=="key-only");
12c86877
BH
428}
429
12c86877
BH
430void del(DNSBackend* d)
431{
432 delete d;
433}
434
435void UeberBackend::cleanup()
436{
437 pthread_mutex_lock(&instances_lock);
438
439 remove(instances.begin(),instances.end(),this);
440 instances.resize(instances.size()-1);
441
442 pthread_mutex_unlock(&instances_lock);
443
6242d8a4 444 for_each(backends.begin(),backends.end(),del);
12c86877
BH
445}
446
923a2384
BH
447// silly Solaris fix
448#undef PC
449
cb433f9c 450// returns -1 for miss, 0 for negative match, 1 for hit
90ba52e0 451int UeberBackend::cacheHas(const Question &q, vector<DNSZoneRecord> &rrs)
12c86877
BH
452{
453 extern PacketCache PC;
1566533a 454 static AtomicCounter *qcachehit=S.getPointer("query-cache-hit");
455 static AtomicCounter *qcachemiss=S.getPointer("query-cache-miss");
12c86877 456
f1d64762 457 if(!d_cache_ttl && ! d_negcache_ttl) {
12c86877
BH
458 (*qcachemiss)++;
459 return -1;
460 }
461
a3b6f8d0 462 rrs.clear();
2f24bcd2 463 // L<<Logger::Warning<<"looking up: '"<<q.qname+"'|N|"+q.qtype.getName()+"|"+itoa(q.zoneId)<<endl;
cf71f03f 464
a3b6f8d0 465 bool ret=PC.getEntry(q.qname, q.qtype, PacketCache::QUERYCACHE, rrs, q.zoneId); // think about lowercasing here
12c86877
BH
466 if(!ret) {
467 (*qcachemiss)++;
468 return -1;
469 }
12c86877 470 (*qcachehit)++;
a3b6f8d0 471 if(rrs.empty()) // negatively cached
12c86877 472 return 0;
cb433f9c 473
12c86877
BH
474 return 1;
475}
476
477void UeberBackend::addNegCache(const Question &q)
478{
479 extern PacketCache PC;
f1d64762 480 if(!d_negcache_ttl)
12c86877 481 return;
ee5e1751 482 // we should also not be storing negative answers if a pipebackend does scopeMask, but we can't pass a negative scopeMask in an empty set!
90ba52e0 483 PC.insert(q.qname, q.qtype, PacketCache::QUERYCACHE, vector<DNSZoneRecord>(), d_negcache_ttl, q.zoneId);
12c86877
BH
484}
485
90ba52e0 486void UeberBackend::addCache(const Question &q, const vector<DNSZoneRecord> &rrs)
12c86877
BH
487{
488 extern PacketCache PC;
46c6efbe 489
f1d64762 490 if(!d_cache_ttl)
12c86877 491 return;
f1d64762
MZ
492
493 unsigned int store_ttl = d_cache_ttl;
90ba52e0 494 for(const auto& rr : rrs) {
495 if (rr.dr.d_ttl < d_cache_ttl)
496 store_ttl = rr.dr.d_ttl;
429ae4cb 497 if (rr.scopeMask)
498 return;
499 }
500
a3b6f8d0 501 PC.insert(q.qname, q.qtype, PacketCache::QUERYCACHE, rrs, store_ttl, q.zoneId);
12c86877
BH
502}
503
675fa24c 504void UeberBackend::alsoNotifies(const DNSName &domain, set<string> *ips)
27d94a79
BH
505{
506 for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
507 (*i)->alsoNotifies(domain,ips);
508}
12c86877
BH
509
510UeberBackend::~UeberBackend()
511{
512 DLOG(L<<Logger::Error<<"UeberBackend destructor called, removing ourselves from instances, and deleting our backends"<<endl);
513 cleanup();
514}
515
516// this handle is more magic than most
675fa24c 517void UeberBackend::lookup(const QType &qtype,const DNSName &qname, DNSPacket *pkt_p, int zoneId)
12c86877
BH
518{
519 if(stale) {
520 L<<Logger::Error<<"Stale ueberbackend received question, signalling that we want to be recycled"<<endl;
3f81d239 521 throw PDNSException("We are stale, please recycle");
12c86877
BH
522 }
523
f43c4448 524 DLOG(L<<"UeberBackend received question for "<<qtype.getName()<<" of "<<qname<<endl);
12c86877
BH
525 if(!d_go) {
526 pthread_mutex_lock(&d_mut);
527 while (d_go==false) {
528 L<<Logger::Error<<"UeberBackend is blocked, waiting for 'go'"<<endl;
529 pthread_cond_wait(&d_cond, &d_mut);
530 L<<Logger::Error<<"Broadcast received, unblocked"<<endl;
531 }
532 pthread_mutex_unlock(&d_mut);
533 }
534
c27c8d96
PD
535 domain_id=zoneId;
536
12c86877
BH
537 d_handle.i=0;
538 d_handle.qtype=qtype;
539 d_handle.qname=qname;
540 d_handle.pkt_p=pkt_p;
541 d_ancount=0;
542
543 if(!backends.size()) {
b34510a3
CH
544 L<<Logger::Error<<"No database backends available - unable to answer questions."<<endl;
545 stale=true; // please recycle us!
3f81d239 546 throw PDNSException("We are stale, please recycle");
12c86877
BH
547 }
548 else {
6242d8a4
KM
549 d_question.qtype=qtype;
550 d_question.qname=qname;
551 d_question.zoneId=zoneId;
552 int cstat=cacheHas(d_question, d_answers);
553 if(cstat<0) { // nothing
aa7b2405 554 // cout<<"UeberBackend::lookup("<<qname<<"|"<<DNSRecordContent::NumberToType(qtype.getCode())<<"): uncached"<<endl;
6242d8a4
KM
555 d_negcached=d_cached=false;
556 d_answers.clear();
557 (d_handle.d_hinterBackend=backends[d_handle.i++])->lookup(qtype, qname,pkt_p,zoneId);
558 }
559 else if(cstat==0) {
aa7b2405 560 // cout<<"UeberBackend::lookup("<<qname<<"|"<<DNSRecordContent::NumberToType(qtype.getCode())<<"): NEGcached"<<endl;
6242d8a4
KM
561 d_negcached=true;
562 d_cached=false;
563 d_answers.clear();
564 }
565 else {
aa7b2405 566 // cout<<"UeberBackend::lookup("<<qname<<"|"<<DNSRecordContent::NumberToType(qtype.getCode())<<"): CACHED"<<endl;
6242d8a4
KM
567 d_negcached=false;
568 d_cached=true;
569 d_cachehandleiter = d_answers.begin();
570 }
12c86877
BH
571 }
572
573 d_handle.parent=this;
12c86877
BH
574}
575
cea26350 576void UeberBackend::getAllDomains(vector<DomainInfo> *domains, bool include_disabled) {
1325e8a2
PD
577 for (vector<DNSBackend*>::iterator i = backends.begin(); i != backends.end(); ++i )
578 {
cea26350 579 (*i)->getAllDomains(domains, include_disabled);
1325e8a2
PD
580 }
581}
582
12c86877 583bool UeberBackend::get(DNSResourceRecord &rr)
90ba52e0 584{
aa7b2405 585 // cout<<"UeberBackend::get(DNSResourceRecord&) called, translating to a DNSZoneRecord query"<<endl;
90ba52e0 586 DNSZoneRecord dzr;
587 if(!this->get(dzr))
588 return false;
589
590 rr=DNSResourceRecord(dzr.dr);
591 rr.auth = dzr.auth;
592 rr.domain_id = dzr.domain_id;
593 return true;
594}
595
596bool UeberBackend::get(DNSZoneRecord &rr)
12c86877 597{
aa7b2405 598 // cout<<"UeberBackend::get(DNSZoneRecord) called"<<endl;
12c86877
BH
599 if(d_negcached) {
600 return false;
601 }
602
603 if(d_cached) {
cb433f9c
BH
604 if(d_cachehandleiter != d_answers.end()) {
605 rr=*d_cachehandleiter++;;
606 return true;
607 }
608 return false;
12c86877 609 }
12c86877 610 if(!d_handle.get(rr)) {
aa7b2405 611 // cout<<"end of ueberbackend get, seeing if we should cache"<<endl;
612 if(!d_ancount && d_handle.qname.countLabels()) {// don't cache axfr
613 // cout<<"adding negache"<<endl;
12c86877 614 addNegCache(d_question);
aa7b2405 615 }
616 else {
617 // cout<<"adding query cache"<<endl;
618 addCache(d_question, d_answers);
619 }
cb433f9c 620 d_answers.clear();
12c86877
BH
621 return false;
622 }
cb433f9c
BH
623 d_ancount++;
624 d_answers.push_back(rr);
12c86877
BH
625 return true;
626}
627
675fa24c 628bool UeberBackend::list(const DNSName &target, int domain_id, bool include_disabled)
12c86877 629{
36d772ab
BH
630 L<<Logger::Error<<"UeberBackend::list called, should NEVER EVER HAPPEN"<<endl;
631 exit(1);
632 return false;
12c86877 633}
36d772ab 634
9f8e226e
AT
635bool UeberBackend::searchRecords(const string& pattern, int maxResults, vector<DNSResourceRecord>& result)
636{
637 bool rc = false;
638 for ( vector< DNSBackend * >::iterator i = backends.begin(); result.size() < static_cast<vector<DNSResourceRecord>::size_type>(maxResults) && i != backends.end(); ++i )
639 if ((*i)->searchRecords(pattern, maxResults - result.size(), result)) rc = true;
640 return rc;
641}
642
643bool UeberBackend::searchComments(const string& pattern, int maxResults, vector<Comment>& result)
644{
645 bool rc = false;
646 for ( vector< DNSBackend * >::iterator i = backends.begin(); result.size() < static_cast<vector<Comment>::size_type>(maxResults) && i != backends.end(); ++i )
647 if ((*i)->searchComments(pattern, maxResults - result.size(), result)) rc = true;
648 return rc;
649}
12c86877 650
16f7d28d 651AtomicCounter UeberBackend::handle::instances(0);
12c86877
BH
652
653UeberBackend::handle::handle()
654{
655 // L<<Logger::Warning<<"Handle instances: "<<instances<<endl;
16f7d28d 656 ++instances;
457d7c72
AT
657 parent=NULL;
658 d_hinterBackend=NULL;
659 pkt_p=NULL;
660 i=0;
12c86877
BH
661}
662
663UeberBackend::handle::~handle()
664{
16f7d28d 665 --instances;
12c86877
BH
666}
667
90ba52e0 668bool UeberBackend::handle::get(DNSZoneRecord &r)
12c86877
BH
669{
670 DLOG(L << "Ueber get() was called for a "<<qtype.getName()<<" record" << endl);
671 bool isMore=false;
672 while(d_hinterBackend && !(isMore=d_hinterBackend->get(r))) { // this backend out of answers
673 if(i<parent->backends.size()) {
674 DLOG(L<<"Backend #"<<i<<" of "<<parent->backends.size()
4957a608 675 <<" out of answers, taking next"<<endl);
12c86877
BH
676
677 d_hinterBackend=parent->backends[i++];
c27c8d96 678 d_hinterBackend->lookup(qtype,qname,pkt_p,parent->domain_id);
12c86877
BH
679 }
680 else
681 break;
682
683 DLOG(L<<"Now asking backend #"<<i<<endl);
684 }
685
686 if(!isMore && i==parent->backends.size()) {
687 DLOG(L<<"UeberBackend reached end of backends"<<endl);
688 return false;
689 }
690
691 DLOG(L<<"Found an answering backend - will not try another one"<<endl);
692 i=parent->backends.size(); // don't go on to the next backend
693 return true;
694}