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