]>
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> | |
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 | |
49 | extern StatBag S; | |
50 | ||
51 | vector<UeberBackend *>UeberBackend::instances; | |
52 | pthread_mutex_t UeberBackend::instances_lock=PTHREAD_MUTEX_INITIALIZER; | |
53 | ||
54 | sem_t UeberBackend::d_dynserialize; | |
12c86877 BH |
55 | |
56 | // initially we are blocked | |
57 | bool UeberBackend::d_go=false; | |
58 | pthread_mutex_t UeberBackend::d_mut = PTHREAD_MUTEX_INITIALIZER; | |
59 | pthread_cond_t UeberBackend::d_cond = PTHREAD_COND_INITIALIZER; | |
60 | ||
12c86877 BH |
61 | //! Loads a module and reports it to all UeberBackend threads |
62 | bool 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 | ||
76 | void 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 | 84 | bool 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 | 92 | bool 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 | 102 | bool 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 | 111 | bool 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 | 120 | bool 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 | 129 | bool 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 | 138 | bool 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 | 147 | bool 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 | 156 | bool 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 | 165 | bool 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 | 175 | bool 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 | 185 | bool 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 | 194 | bool 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 | ||
203 | bool 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 |
211 | void UeberBackend::reload() |
212 | { | |
213 | for ( vector< DNSBackend * >::iterator i = backends.begin(); i != backends.end(); ++i ) | |
214 | { | |
215 | ( *i )->reload(); | |
216 | } | |
217 | } | |
218 | ||
973ad2b5 | 219 | void 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 | ||
232 | void 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 | ||
242 | void 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 | 250 | bool 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 |
341 | found: |
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 | 354 | bool 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 | 376 | bool 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 | 403 | bool 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 |
411 | UeberBackend::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 |
430 | void del(DNSBackend* d) |
431 | { | |
432 | delete d; | |
433 | } | |
434 | ||
435 | void 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 | 451 | int 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 | ||
477 | void 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 | 486 | void 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 | 504 | void 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 | |
510 | UeberBackend::~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 | 517 | void 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 | 576 | void 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 | 583 | bool 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 | ||
596 | bool 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 | 628 | bool 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 |
635 | bool 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 | ||
643 | bool 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 | 651 | AtomicCounter UeberBackend::handle::instances(0); |
12c86877 BH |
652 | |
653 | UeberBackend::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 | ||
663 | UeberBackend::handle::~handle() | |
664 | { | |
16f7d28d | 665 | --instances; |
12c86877 BH |
666 | } |
667 | ||
90ba52e0 | 668 | bool 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 | } |