]>
Commit | Line | Data |
---|---|---|
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 | |
51 | extern StatBag S; | |
52 | ||
53 | vector<UeberBackend *>UeberBackend::instances; | |
54 | pthread_mutex_t UeberBackend::instances_lock=PTHREAD_MUTEX_INITIALIZER; | |
55 | ||
56 | sem_t UeberBackend::d_dynserialize; | |
12c86877 BH |
57 | |
58 | // initially we are blocked | |
59 | bool UeberBackend::d_go=false; | |
60 | pthread_mutex_t UeberBackend::d_mut = PTHREAD_MUTEX_INITIALIZER; | |
61 | pthread_cond_t UeberBackend::d_cond = PTHREAD_COND_INITIALIZER; | |
62 | ||
12c86877 BH |
63 | //! Loads a module and reports it to all UeberBackend threads |
64 | bool 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 | ||
78 | void 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 | 86 | bool 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 | 94 | bool 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 | 104 | int 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 | 113 | bool 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 | 122 | bool 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 | 131 | bool 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 | 140 | bool 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 | 149 | bool 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 | 158 | bool 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 | 167 | bool 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 | 177 | bool 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 | 187 | bool 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 | 196 | bool 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 | ||
205 | bool 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 |
213 | void UeberBackend::reload() |
214 | { | |
215 | for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i ) | |
216 | { | |
217 | ( *i )->reload(); | |
218 | } | |
219 | } | |
220 | ||
973ad2b5 | 221 | void 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 | ||
234 | void 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 | ||
244 | void 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 | 252 | bool 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 | ||
306 | auth_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 | 328 | bool 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 | 350 | bool 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 | 376 | bool 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 |
384 | UeberBackend::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 |
403 | void del(DNSBackend* d) |
404 | { | |
405 | delete d; | |
406 | } | |
407 | ||
408 | void 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 |
424 | int 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 | ||
454 | void 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 | 463 | void 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 | 487 | void 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 | |
493 | UeberBackend::~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 | 500 | void 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 | 556 | void 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 |
563 | bool 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 | 589 | bool 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 |
596 | bool 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 | ||
604 | bool 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 | 612 | AtomicCounter UeberBackend::handle::instances(0); |
12c86877 BH |
613 | |
614 | UeberBackend::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 | ||
624 | UeberBackend::handle::~handle() | |
625 | { | |
16f7d28d | 626 | --instances; |
12c86877 BH |
627 | } |
628 | ||
12c86877 BH |
629 | bool 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 | } |