]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/ueberbackend.cc
Merge pull request #2934 from cmouse/gdobc-stuff
[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>
c0273500 40#include <boost/foreach.hpp>
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"
13978a71 48#include <boost/serialization/vector.hpp>
ba45c866 49
12c86877
BH
50
51extern StatBag S;
52
53vector<UeberBackend *>UeberBackend::instances;
54pthread_mutex_t UeberBackend::instances_lock=PTHREAD_MUTEX_INITIALIZER;
55
56sem_t UeberBackend::d_dynserialize;
12c86877
BH
57
58// initially we are blocked
59bool UeberBackend::d_go=false;
60pthread_mutex_t UeberBackend::d_mut = PTHREAD_MUTEX_INITIALIZER;
61pthread_cond_t UeberBackend::d_cond = PTHREAD_COND_INITIALIZER;
62
12c86877
BH
63//! Loads a module and reports it to all UeberBackend threads
64bool UeberBackend::loadmodule(const string &name)
65{
74caf870
KM
66 L<<Logger::Warning <<"Loading '"<<name<<"'" << endl;
67
12c86877 68 void *dlib=dlopen(name.c_str(), RTLD_NOW);
74caf870 69
12c86877 70 if(dlib == NULL) {
74caf870 71 L<<Logger::Error <<"Unable to load module '"<<name<<"': "<<dlerror() << endl;
12c86877
BH
72 return false;
73 }
74caf870 74
12c86877 75 return true;
12c86877
BH
76}
77
78void UeberBackend::go(void)
79{
80 pthread_mutex_lock(&d_mut);
81 d_go=true;
82 pthread_cond_broadcast(&d_cond);
83 pthread_mutex_unlock(&d_mut);
84}
85
675fa24c 86bool UeberBackend::getDomainInfo(const DNSName &domain, DomainInfo &di)
12c86877
BH
87{
88 for(vector<DNSBackend *>::const_iterator i=backends.begin();i!=backends.end();++i)
89 if((*i)->getDomainInfo(domain, di))
90 return true;
91 return false;
92}
93
675fa24c 94bool UeberBackend::createDomain(const DNSName &domain)
487cf033
CH
95{
96 BOOST_FOREACH(DNSBackend* mydb, backends) {
97 if(mydb->createDomain(domain)) {
487cf033
CH
98 return true;
99 }
100 }
101 return false;
102}
103
675fa24c 104int UeberBackend::addDomainKey(const DNSName& name, const DNSBackend::KeyData& key)
c0273500 105{
9957cac5 106 int ret;
c0273500 107 BOOST_FOREACH(DNSBackend* db, backends) {
9957cac5
BH
108 if((ret = db->addDomainKey(name, key)) >= 0)
109 return ret;
c0273500 110 }
9957cac5 111 return -1;
c0273500 112}
675fa24c 113bool UeberBackend::getDomainKeys(const DNSName& name, unsigned int kind, std::vector<DNSBackend::KeyData>& keys)
c0273500
BH
114{
115 BOOST_FOREACH(DNSBackend* db, backends) {
116 if(db->getDomainKeys(name, kind, keys))
117 return true;
118 }
119 return false;
120}
121
675fa24c 122bool UeberBackend::getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string> >& meta)
ac993e0a 123{
ac993e0a
AT
124 BOOST_FOREACH(DNSBackend* db, backends) {
125 if(db->getAllDomainMetadata(name, meta))
126 return true;
127 }
128 return false;
129}
130
675fa24c 131bool UeberBackend::getDomainMetadata(const DNSName& name, const std::string& kind, std::vector<std::string>& meta)
c0273500
BH
132{
133 BOOST_FOREACH(DNSBackend* db, backends) {
134 if(db->getDomainMetadata(name, kind, meta))
135 return true;
136 }
137 return false;
138}
139
675fa24c 140bool UeberBackend::setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector<std::string>& meta)
c0273500
BH
141{
142 BOOST_FOREACH(DNSBackend* db, backends) {
143 if(db->setDomainMetadata(name, kind, meta))
144 return true;
145 }
146 return false;
147}
148
675fa24c 149bool UeberBackend::activateDomainKey(const DNSName& name, unsigned int id)
4496f66f
BH
150{
151 BOOST_FOREACH(DNSBackend* db, backends) {
152 if(db->activateDomainKey(name, id))
153 return true;
154 }
155 return false;
156}
157
675fa24c 158bool UeberBackend::deactivateDomainKey(const DNSName& name, unsigned int id)
4496f66f
BH
159{
160 BOOST_FOREACH(DNSBackend* db, backends) {
161 if(db->deactivateDomainKey(name, id))
162 return true;
163 }
164 return false;
165}
166
675fa24c 167bool UeberBackend::removeDomainKey(const DNSName& name, unsigned int id)
4496f66f
BH
168{
169 BOOST_FOREACH(DNSBackend* db, backends) {
170 if(db->removeDomainKey(name, id))
171 return true;
172 }
173 return false;
174}
175
c0273500 176
675fa24c 177bool UeberBackend::getTSIGKey(const DNSName& name, DNSName* algorithm, string* content)
78bcb858
BH
178{
179 BOOST_FOREACH(DNSBackend* db, backends) {
180 if(db->getTSIGKey(name, algorithm, content))
181 return true;
182 }
183 return false;
184}
185
186
675fa24c 187bool UeberBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content)
6f872b78
AT
188{
189 BOOST_FOREACH(DNSBackend* db, backends) {
190 if(db->setTSIGKey(name, algorithm, content))
191 return true;
192 }
193 return false;
194}
195
675fa24c 196bool UeberBackend::deleteTSIGKey(const DNSName& name)
6f872b78
AT
197{
198 BOOST_FOREACH(DNSBackend* db, backends) {
199 if(db->deleteTSIGKey(name))
200 return true;
201 }
202 return false;
203}
204
205bool UeberBackend::getTSIGKeys(std::vector< struct TSIGKey > &keys)
206{
207 BOOST_FOREACH(DNSBackend* db, backends) {
208 db->getTSIGKeys(keys);
209 }
210 return true;
211}
212
12c86877
BH
213void UeberBackend::reload()
214{
215 for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
216 {
217 ( *i )->reload();
218 }
219}
220
973ad2b5 221void UeberBackend::rediscover(string *status)
12c86877 222{
20ca8e7d 223
12c86877
BH
224 for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
225 {
973ad2b5
BH
226 string tmpstr;
227 ( *i )->rediscover(&tmpstr);
6242d8a4
KM
228 if(status)
229 *status+=tmpstr + (i!=backends.begin() ? "\n" : "");
12c86877
BH
230 }
231}
232
233
234void UeberBackend::getUnfreshSlaveInfos(vector<DomainInfo>* domains)
235{
236 for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
237 {
238 ( *i )->getUnfreshSlaveInfos( domains );
239 }
240}
241
242
243
244void UeberBackend::getUpdatedMasters(vector<DomainInfo>* domains)
245{
246 for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
247 {
248 ( *i )->getUpdatedMasters( domains );
249 }
250}
251
675fa24c 252bool UeberBackend::getAuth(DNSPacket *p, SOAData *sd, const DNSName &target)
c14bc34a 253{
d33578f8 254 int best_match_len = -1;
c14bc34a
MZ
255 bool from_cache = false; // Was this result fetched from the cache?
256
c14bc34a
MZ
257 // If not special case of caching explicitly disabled (sd->db = -1), first
258 // find the best match from the cache. If DS then we need to find parent so
259 // dont bother with caching as it confuses matters.
260 if( sd->db != (DNSBackend *)-1 && d_cache_ttl && p->qtype != QType::DS ) {
675fa24c 261 DNSName subdomain(target);
c14bc34a
MZ
262 int cstat, loops = 0;
263 do {
264 d_question.qtype = QType::SOA;
265 d_question.qname = subdomain;
266 d_question.zoneId = -1;
267
268 cstat = cacheHas(d_question,d_answers);
269
270 if(cstat==1 && !d_answers.empty()) {
271 fillSOAData(d_answers[0].content,*sd);
272 sd->domain_id = d_answers[0].domain_id;
273 sd->ttl = d_answers[0].ttl;
274 sd->db = 0;
275 sd->qname = subdomain;
276 //L<<Logger::Error<<"Best cache match: " << sd->qname << " itteration " << loops <<endl;
277
278 // Found first time round this must be the best match
279 if( loops == 0 )
280 return true;
281
282 from_cache = true;
675fa24c 283 best_match_len = sd->qname.countLabels();
c14bc34a
MZ
284
285 break;
286 }
287 loops++;
288 }
675fa24c 289 while( subdomain.chopOff() ); // 'www.powerdns.org' -> 'powerdns.org' -> 'org' -> ''
c14bc34a
MZ
290 }
291
292 for(vector<DNSBackend *>::const_iterator i=backends.begin(); i!=backends.end();++i)
81c486ad 293 if((*i)->getAuth(p, sd, target, best_match_len)) {
3343ad1f 294 best_match_len = sd->qname.countLabels(); // FIXME400
c14bc34a
MZ
295 from_cache = false;
296
297 // Shortcut for the case that we got a direct hit - no need to go
298 // through the other backends then.
675fa24c 299 if( best_match_len == (int)target.countLabels() )
c14bc34a
MZ
300 goto auth_found;
301 }
302
d33578f8 303 if( best_match_len == -1 )
c14bc34a
MZ
304 return false;
305
306auth_found:
307 // Insert into cache. Don't cache if the query was a DS
308 if( d_cache_ttl && ! from_cache && p->qtype != QType::DS ) {
309 //L<<Logger::Error<<"Saving auth cache for " << sd->qname <<endl;
310 d_question.qtype = QType::SOA;
311 d_question.qname = sd->qname;
312 d_question.zoneId = -1;
313
314 DNSResourceRecord rr;
315 rr.qname = sd->qname;
316 rr.qtype = QType::SOA;
317 rr.content = serializeSOAData(*sd);
318 rr.ttl = sd->ttl;
319 rr.domain_id = sd->domain_id;
320 vector<DNSResourceRecord> rrs;
321 rrs.push_back(rr);
322 addCache(d_question, rrs);
323 }
324
325 return true;
326}
327
675fa24c 328bool UeberBackend::getSOA(const DNSName &domain, SOAData &sd, DNSPacket *p)
12c86877
BH
329{
330 d_question.qtype=QType::SOA;
331 d_question.qname=domain;
332 d_question.zoneId=-1;
333
79ba7763
CH
334 int cstat=cacheHas(d_question,d_answers);
335 if(cstat==0) { // negative
336 return false;
12c86877 337 }
79ba7763
CH
338 else if(cstat==1 && !d_answers.empty()) {
339 fillSOAData(d_answers[0].content,sd);
340 sd.domain_id=d_answers[0].domain_id;
341 sd.ttl=d_answers[0].ttl;
342 sd.db=0;
343 return true;
344 }
345
346 // not found in neg. or pos. cache, look it up
347 return getSOAUncached(domain, sd, p);
348}
349
675fa24c 350bool UeberBackend::getSOAUncached(const DNSName &domain, SOAData &sd, DNSPacket *p)
79ba7763
CH
351{
352 d_question.qtype=QType::SOA;
353 d_question.qname=domain;
354 d_question.zoneId=-1;
355
12c86877 356 for(vector<DNSBackend *>::const_iterator i=backends.begin();i!=backends.end();++i)
35933370 357 if((*i)->getSOA(domain, sd, p)) {
f1d64762
MZ
358 if( d_cache_ttl ) {
359 DNSResourceRecord rr;
360 rr.qname=domain;
361 rr.qtype=QType::SOA;
362 rr.content=serializeSOAData(sd);
363 rr.ttl=sd.ttl;
364 rr.domain_id=sd.domain_id;
365 vector<DNSResourceRecord> rrs;
366 rrs.push_back(rr);
367 addCache(d_question, rrs);
368 }
12c86877
BH
369 return true;
370 }
371
79ba7763 372 addNegCache(d_question);
12c86877
BH
373 return false;
374}
375
675fa24c 376bool UeberBackend::superMasterBackend(const string &ip, const DNSName &domain, const vector<DNSResourceRecord>&nsset, string *nameserver, string *account, DNSBackend **db)
12c86877
BH
377{
378 for(vector<DNSBackend *>::const_iterator i=backends.begin();i!=backends.end();++i)
719f9024 379 if((*i)->superMasterBackend(ip, domain, nsset, nameserver, account, db))
12c86877
BH
380 return true;
381 return false;
12c86877
BH
382}
383
12c86877
BH
384UeberBackend::UeberBackend(const string &pname)
385{
12c86877
BH
386 pthread_mutex_lock(&instances_lock);
387 instances.push_back(this); // report to the static list of ourself
388 pthread_mutex_unlock(&instances_lock);
389
51d01c80
AT
390 d_negcached=0;
391 d_ancount=0;
392 domain_id=-1;
393 d_cached=0;
f1d64762
MZ
394 d_cache_ttl = ::arg().asNum("query-cache-ttl");
395 d_negcache_ttl = ::arg().asNum("negquery-cache-ttl");
396
12c86877
BH
397 tid=pthread_self();
398 stale=false;
399
e0d84497 400 backends=BackendMakers().all(pname=="key-only");
12c86877
BH
401}
402
12c86877
BH
403void del(DNSBackend* d)
404{
405 delete d;
406}
407
408void UeberBackend::cleanup()
409{
410 pthread_mutex_lock(&instances_lock);
411
412 remove(instances.begin(),instances.end(),this);
413 instances.resize(instances.size()-1);
414
415 pthread_mutex_unlock(&instances_lock);
416
6242d8a4 417 for_each(backends.begin(),backends.end(),del);
12c86877
BH
418}
419
923a2384
BH
420// silly Solaris fix
421#undef PC
422
cb433f9c
BH
423// returns -1 for miss, 0 for negative match, 1 for hit
424int UeberBackend::cacheHas(const Question &q, vector<DNSResourceRecord> &rrs)
12c86877
BH
425{
426 extern PacketCache PC;
1566533a 427 static AtomicCounter *qcachehit=S.getPointer("query-cache-hit");
428 static AtomicCounter *qcachemiss=S.getPointer("query-cache-miss");
12c86877 429
f1d64762 430 if(!d_cache_ttl && ! d_negcache_ttl) {
12c86877
BH
431 (*qcachemiss)++;
432 return -1;
433 }
434
435 string content;
2f24bcd2 436 // L<<Logger::Warning<<"looking up: '"<<q.qname+"'|N|"+q.qtype.getName()+"|"+itoa(q.zoneId)<<endl;
cf71f03f 437
771af01a 438 bool ret=PC.getEntry(q.qname, q.qtype, PacketCache::QUERYCACHE, content, q.zoneId); // think about lowercasing here
12c86877
BH
439 if(!ret) {
440 (*qcachemiss)++;
441 return -1;
442 }
12c86877 443 (*qcachehit)++;
2f24bcd2 444 if(content.empty()) // negatively cached
12c86877 445 return 0;
cb433f9c
BH
446
447 std::istringstream istr(content);
2665f226 448 boost::archive::binary_iarchive boa(istr, boost::archive::no_header);
7d454f5b 449 rrs.clear();
cb433f9c 450 boa >> rrs;
12c86877
BH
451 return 1;
452}
453
454void UeberBackend::addNegCache(const Question &q)
455{
456 extern PacketCache PC;
f1d64762 457 if(!d_negcache_ttl)
12c86877 458 return;
ee5e1751 459 // 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!
f1d64762 460 PC.insert(q.qname, q.qtype, PacketCache::QUERYCACHE, "", d_negcache_ttl, q.zoneId);
12c86877
BH
461}
462
cb433f9c 463void UeberBackend::addCache(const Question &q, const vector<DNSResourceRecord> &rrs)
12c86877
BH
464{
465 extern PacketCache PC;
46c6efbe 466
f1d64762 467 if(!d_cache_ttl)
12c86877 468 return;
f1d64762
MZ
469
470 unsigned int store_ttl = d_cache_ttl;
471
2f24bcd2 472 // L<<Logger::Warning<<"inserting: "<<q.qname+"|N|"+q.qtype.getName()+"|"+itoa(q.zoneId)<<endl;
cb433f9c 473 std::ostringstream ostr;
2665f226 474 boost::archive::binary_oarchive boa(ostr, boost::archive::no_header);
b35ea8ec
PD
475
476 BOOST_FOREACH(DNSResourceRecord rr, rrs) {
f1d64762
MZ
477 if (rr.ttl < d_cache_ttl)
478 store_ttl = rr.ttl;
ee5e1751 479 if (rr.scopeMask)
480 return;
b35ea8ec 481 }
46c6efbe 482
cb433f9c 483 boa << rrs;
f1d64762 484 PC.insert(q.qname, q.qtype, PacketCache::QUERYCACHE, ostr.str(), store_ttl, q.zoneId);
12c86877
BH
485}
486
675fa24c 487void UeberBackend::alsoNotifies(const DNSName &domain, set<string> *ips)
27d94a79
BH
488{
489 for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i )
490 (*i)->alsoNotifies(domain,ips);
491}
12c86877
BH
492
493UeberBackend::~UeberBackend()
494{
495 DLOG(L<<Logger::Error<<"UeberBackend destructor called, removing ourselves from instances, and deleting our backends"<<endl);
496 cleanup();
497}
498
499// this handle is more magic than most
675fa24c 500void UeberBackend::lookup(const QType &qtype,const DNSName &qname, DNSPacket *pkt_p, int zoneId)
12c86877
BH
501{
502 if(stale) {
503 L<<Logger::Error<<"Stale ueberbackend received question, signalling that we want to be recycled"<<endl;
3f81d239 504 throw PDNSException("We are stale, please recycle");
12c86877
BH
505 }
506
f43c4448 507 DLOG(L<<"UeberBackend received question for "<<qtype.getName()<<" of "<<qname<<endl);
12c86877
BH
508 if(!d_go) {
509 pthread_mutex_lock(&d_mut);
510 while (d_go==false) {
511 L<<Logger::Error<<"UeberBackend is blocked, waiting for 'go'"<<endl;
512 pthread_cond_wait(&d_cond, &d_mut);
513 L<<Logger::Error<<"Broadcast received, unblocked"<<endl;
514 }
515 pthread_mutex_unlock(&d_mut);
516 }
517
c27c8d96
PD
518 domain_id=zoneId;
519
12c86877
BH
520 d_handle.i=0;
521 d_handle.qtype=qtype;
522 d_handle.qname=qname;
523 d_handle.pkt_p=pkt_p;
524 d_ancount=0;
525
526 if(!backends.size()) {
527 L<<Logger::Error<<Logger::NTLog<<"No database backends available - unable to answer questions."<<endl;
528 stale=true; // please recycle us!
3f81d239 529 throw PDNSException("We are stale, please recycle");
12c86877
BH
530 }
531 else {
6242d8a4
KM
532 d_question.qtype=qtype;
533 d_question.qname=qname;
534 d_question.zoneId=zoneId;
535 int cstat=cacheHas(d_question, d_answers);
536 if(cstat<0) { // nothing
537 d_negcached=d_cached=false;
538 d_answers.clear();
539 (d_handle.d_hinterBackend=backends[d_handle.i++])->lookup(qtype, qname,pkt_p,zoneId);
540 }
541 else if(cstat==0) {
542 d_negcached=true;
543 d_cached=false;
544 d_answers.clear();
545 }
546 else {
547 d_negcached=false;
548 d_cached=true;
549 d_cachehandleiter = d_answers.begin();
550 }
12c86877
BH
551 }
552
553 d_handle.parent=this;
12c86877
BH
554}
555
cea26350 556void UeberBackend::getAllDomains(vector<DomainInfo> *domains, bool include_disabled) {
1325e8a2
PD
557 for (vector<DNSBackend*>::iterator i = backends.begin(); i != backends.end(); ++i )
558 {
cea26350 559 (*i)->getAllDomains(domains, include_disabled);
1325e8a2
PD
560 }
561}
562
12c86877
BH
563bool UeberBackend::get(DNSResourceRecord &rr)
564{
565 if(d_negcached) {
566 return false;
567 }
568
569 if(d_cached) {
cb433f9c
BH
570 if(d_cachehandleiter != d_answers.end()) {
571 rr=*d_cachehandleiter++;;
572 return true;
573 }
574 return false;
12c86877 575 }
12c86877 576 if(!d_handle.get(rr)) {
675fa24c 577 if(!d_ancount && d_handle.qname.countLabels()) // don't cache axfr
12c86877
BH
578 addNegCache(d_question);
579
cb433f9c
BH
580 addCache(d_question, d_answers);
581 d_answers.clear();
12c86877
BH
582 return false;
583 }
cb433f9c
BH
584 d_ancount++;
585 d_answers.push_back(rr);
12c86877
BH
586 return true;
587}
588
675fa24c 589bool UeberBackend::list(const DNSName &target, int domain_id, bool include_disabled)
12c86877 590{
36d772ab
BH
591 L<<Logger::Error<<"UeberBackend::list called, should NEVER EVER HAPPEN"<<endl;
592 exit(1);
593 return false;
12c86877 594}
36d772ab 595
9f8e226e
AT
596bool UeberBackend::searchRecords(const string& pattern, int maxResults, vector<DNSResourceRecord>& result)
597{
598 bool rc = false;
599 for ( vector< DNSBackend * >::iterator i = backends.begin(); result.size() < static_cast<vector<DNSResourceRecord>::size_type>(maxResults) && i != backends.end(); ++i )
600 if ((*i)->searchRecords(pattern, maxResults - result.size(), result)) rc = true;
601 return rc;
602}
603
604bool UeberBackend::searchComments(const string& pattern, int maxResults, vector<Comment>& result)
605{
606 bool rc = false;
607 for ( vector< DNSBackend * >::iterator i = backends.begin(); result.size() < static_cast<vector<Comment>::size_type>(maxResults) && i != backends.end(); ++i )
608 if ((*i)->searchComments(pattern, maxResults - result.size(), result)) rc = true;
609 return rc;
610}
12c86877 611
16f7d28d 612AtomicCounter UeberBackend::handle::instances(0);
12c86877
BH
613
614UeberBackend::handle::handle()
615{
616 // L<<Logger::Warning<<"Handle instances: "<<instances<<endl;
16f7d28d 617 ++instances;
457d7c72
AT
618 parent=NULL;
619 d_hinterBackend=NULL;
620 pkt_p=NULL;
621 i=0;
12c86877
BH
622}
623
624UeberBackend::handle::~handle()
625{
16f7d28d 626 --instances;
12c86877
BH
627}
628
12c86877
BH
629bool UeberBackend::handle::get(DNSResourceRecord &r)
630{
631 DLOG(L << "Ueber get() was called for a "<<qtype.getName()<<" record" << endl);
632 bool isMore=false;
633 while(d_hinterBackend && !(isMore=d_hinterBackend->get(r))) { // this backend out of answers
634 if(i<parent->backends.size()) {
635 DLOG(L<<"Backend #"<<i<<" of "<<parent->backends.size()
4957a608 636 <<" out of answers, taking next"<<endl);
12c86877
BH
637
638 d_hinterBackend=parent->backends[i++];
c27c8d96 639 d_hinterBackend->lookup(qtype,qname,pkt_p,parent->domain_id);
12c86877
BH
640 }
641 else
642 break;
643
644 DLOG(L<<"Now asking backend #"<<i<<endl);
645 }
646
647 if(!isMore && i==parent->backends.size()) {
648 DLOG(L<<"UeberBackend reached end of backends"<<endl);
649 return false;
650 }
651
652 DLOG(L<<"Found an answering backend - will not try another one"<<endl);
653 i=parent->backends.size(); // don't go on to the next backend
654 return true;
655}