]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/test-ueberbackend_cc.cc
updated KSK and ZSK Rollover procedures, small fixes in Algorithm Rollover procedure
[thirdparty/pdns.git] / pdns / test-ueberbackend_cc.cc
1 #define BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_NO_MAIN
3
4 #ifdef HAVE_CONFIG_H
5 #include "config.h"
6 #endif
7
8 #include <unordered_map>
9
10 #include <boost/test/unit_test.hpp>
11
12 #include <boost/multi_index_container.hpp>
13 #include <boost/multi_index/ordered_index.hpp>
14 #include <boost/multi_index/hashed_index.hpp>
15 #include <boost/multi_index/key_extractors.hpp>
16
17 #include "arguments.hh"
18 #include "auth-querycache.hh"
19 #include "auth-zonecache.hh"
20 #include "ueberbackend.hh"
21
22 class SimpleBackend : public DNSBackend
23 {
24 public:
25 struct SimpleDNSRecord
26 {
27 SimpleDNSRecord(const DNSName& name, uint16_t type, const std::string& content, uint32_t ttl): d_content(content), d_name(name), d_ttl(ttl), d_type(type)
28 {
29 }
30
31 std::string d_content;
32 DNSName d_name;
33 uint32_t d_ttl;
34 uint16_t d_type;
35 };
36
37 struct OrderedNameTypeTag;
38
39 typedef multi_index_container<
40 SimpleDNSRecord,
41 indexed_by <
42 ordered_non_unique<tag<OrderedNameTypeTag>,
43 composite_key<
44 SimpleDNSRecord,
45 member<SimpleDNSRecord, DNSName, &SimpleDNSRecord::d_name>,
46 member<SimpleDNSRecord, uint16_t, &SimpleDNSRecord::d_type>
47 >,
48 composite_key_compare<CanonDNSNameCompare, std::less<uint16_t> >
49 >
50 >
51 > RecordStorage;
52
53 struct SimpleDNSZone
54 {
55 SimpleDNSZone(const DNSName& name, uint64_t id): d_records(std::make_shared<RecordStorage>()), d_name(name), d_id(id)
56 {
57 }
58 std::shared_ptr<RecordStorage> d_records;
59 DNSName d_name;
60 uint64_t d_id;
61 };
62
63 struct HashedNameTag {};
64 struct IDTag {};
65
66 typedef multi_index_container<
67 SimpleDNSZone,
68 indexed_by <
69 ordered_unique<tag<IDTag>, member<SimpleDNSZone, uint64_t, &SimpleDNSZone::d_id> >,
70 hashed_unique<tag<HashedNameTag>, member<SimpleDNSZone, DNSName, &SimpleDNSZone::d_name> >
71 >
72 > ZoneStorage;
73
74 struct SimpleMetaData
75 {
76 SimpleMetaData(const DNSName& name, const std::string& kind, const std::vector<std::string>& values): d_name(name), d_kind(kind), d_values(values)
77 {
78 }
79
80 DNSName d_name;
81 std::string d_kind;
82 std::vector<std::string> d_values;
83 };
84
85 struct OrderedNameKindTag {};
86
87 typedef multi_index_container<
88 SimpleMetaData,
89 indexed_by <
90 ordered_unique<tag<OrderedNameKindTag>,
91 composite_key<
92 SimpleMetaData,
93 member<SimpleMetaData, DNSName, &SimpleMetaData::d_name>,
94 member<SimpleMetaData, std::string, &SimpleMetaData::d_kind>
95 >,
96 composite_key_compare<CanonDNSNameCompare, std::less<std::string> >
97 >
98 >
99 > MetaDataStorage;
100
101 // Initialize our backend ID from the suffix, skipping the '-' that DNSBackend adds there
102 SimpleBackend(const std::string& suffix) :
103 d_suffix(suffix), d_backendId(pdns::checked_stoi<decltype(d_backendId)>(suffix.substr(1)))
104 {
105 }
106
107 bool findZone(const DNSName& qdomain, int zoneId, std::shared_ptr<RecordStorage>& records, uint64_t& currentZoneId) const
108 {
109 currentZoneId = -1;
110 records.reset();
111
112 if (zoneId != -1) {
113 const auto& idx = boost::multi_index::get<IDTag>(s_zones.at(d_backendId));
114 auto it = idx.find(zoneId);
115 if (it == idx.end()) {
116 return false;
117 }
118 records = it->d_records;
119 currentZoneId = it->d_id;
120 }
121 else {
122 const auto& idx = boost::multi_index::get<HashedNameTag>(s_zones.at(d_backendId));
123 auto it = idx.find(qdomain);
124 if (it == idx.end()) {
125 return false;
126 }
127 records = it->d_records;
128 currentZoneId = it->d_id;
129 }
130
131 return true;
132 }
133
134 void lookup(const QType& qtype, const DNSName& qdomain, int zoneId = -1, DNSPacket *pkt_p = nullptr) override
135 {
136 d_currentScopeMask = 0;
137 findZone(qdomain, zoneId, d_records, d_currentZone);
138
139 if (d_records) {
140 if (qdomain == DNSName("geo.powerdns.com.") && pkt_p != nullptr) {
141 if (pkt_p->getRealRemote() == Netmask("192.0.2.1")) {
142 d_currentScopeMask = 32;
143 }
144 else if (pkt_p->getRealRemote() == Netmask("198.51.100.1")) {
145 d_currentScopeMask = 24;
146 }
147 }
148
149 auto& idx = d_records->get<OrderedNameTypeTag>();
150 if (qtype == QType::ANY) {
151 auto range = idx.equal_range(qdomain);
152 d_iter = range.first;
153 d_end = range.second;
154 }
155 else {
156 auto range = idx.equal_range(std::make_tuple(qdomain, qtype.getCode()));
157 d_iter = range.first;
158 d_end = range.second;
159 }
160 }
161 }
162
163 bool get(DNSResourceRecord& drr) override
164 {
165 if (!d_records) {
166 return false;
167 }
168
169 if (d_iter == d_end) {
170 return false;
171 }
172
173 drr.qname = d_iter->d_name;
174 drr.domain_id = d_currentZone;
175 drr.content = d_iter->d_content;
176 drr.qtype = d_iter->d_type;
177 drr.ttl = d_iter->d_ttl;
178
179 // drr.auth = d_iter->auth; might bring pain at some point, let's not cross that bridge until then
180 drr.auth = true;
181 drr.scopeMask = d_currentScopeMask;
182
183 ++d_iter;
184 return true;
185 }
186
187 bool list(const DNSName& target, int zoneId, bool include_disabled = false) override
188 {
189 findZone(target, zoneId, d_records, d_currentZone);
190
191 if (d_records) {
192 d_iter = d_records->begin();
193 d_end = d_records->end();
194 return true;
195 }
196
197 return false;
198 }
199
200 bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector<std::string>& meta) override
201 {
202 const auto& idx = boost::multi_index::get<OrderedNameKindTag>(s_metadata.at(d_backendId));
203 auto it = idx.find(std::make_tuple(name, kind));
204 if (it == idx.end()) {
205 /* funnily enough, we are expected to return true even though we might not know that zone */
206 return true;
207 }
208
209 meta = it->d_values;
210 return true;
211 }
212
213 bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector<std::string>& meta) override
214 {
215 auto& idx = boost::multi_index::get<OrderedNameKindTag>(s_metadata.at(d_backendId));
216 auto it = idx.find(std::make_tuple(name, kind));
217 if (it == idx.end()) {
218 s_metadata.at(d_backendId).insert(SimpleMetaData(name, kind, meta));
219 return true;
220 }
221 idx.replace(it, SimpleMetaData(name, kind, meta));
222 return true;
223 }
224
225 /* this is not thread-safe */
226 static std::unordered_map<uint64_t, ZoneStorage> s_zones;
227 static std::unordered_map<uint64_t, MetaDataStorage> s_metadata;
228
229 protected:
230 std::string d_suffix;
231 std::shared_ptr<RecordStorage> d_records{nullptr};
232 RecordStorage::index<OrderedNameTypeTag>::type::const_iterator d_iter;
233 RecordStorage::index<OrderedNameTypeTag>::type::const_iterator d_end;
234 const uint64_t d_backendId;
235 uint64_t d_currentZone{0};
236 uint8_t d_currentScopeMask{0};
237 };
238
239 class SimpleBackendBestAuth : public SimpleBackend
240 {
241 public:
242 SimpleBackendBestAuth(const std::string& suffix): SimpleBackend(suffix)
243 {
244 }
245
246 bool getAuth(const DNSName& target, SOAData* sd) override
247 {
248 static const DNSName best("d.0.1.0.0.2.ip6.arpa.");
249
250 ++d_authLookupCount;
251
252 if (target.isPartOf(best)) {
253 /* return the best SOA right away */
254 std::shared_ptr<RecordStorage> records;
255 uint64_t zoneId;
256 if (!findZone(best, -1, records, zoneId)) {
257 return false;
258 }
259
260 auto& idx = records->get<OrderedNameTypeTag>();
261 auto range = idx.equal_range(std::make_tuple(best, QType::SOA));
262 if (range.first == range.second) {
263 return false;
264 }
265
266 fillSOAData(range.first->d_content, *sd);
267 sd->ttl = range.first->d_ttl;
268 sd->qname = best;
269 sd->domain_id = zoneId;
270 return true;
271 }
272
273 return getSOA(target, *sd);
274 }
275
276 size_t d_authLookupCount{0};
277 };
278
279 class SimpleBackendNoMeta : public SimpleBackend
280 {
281 public:
282 SimpleBackendNoMeta(const std::string& suffix): SimpleBackend(suffix)
283 {
284 }
285
286 bool getDomainMetadata(const DNSName& name, const std::string& kind, std::vector<std::string>& meta) override
287 {
288 return false;
289 }
290
291 bool setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector<std::string>& meta) override
292 {
293 return false;
294 }
295 };
296
297 std::unordered_map<uint64_t, SimpleBackend::ZoneStorage> SimpleBackend::s_zones;
298 std::unordered_map<uint64_t, SimpleBackend::MetaDataStorage> SimpleBackend::s_metadata;
299
300 class SimpleBackendFactory : public BackendFactory
301 {
302 public:
303 SimpleBackendFactory(): BackendFactory("SimpleBackend")
304 {
305 }
306
307 DNSBackend *make(const string& suffix="") override
308 {
309 return new SimpleBackend(suffix);
310 }
311 };
312
313 class SimpleBackendBestAuthFactory : public BackendFactory
314 {
315 public:
316 SimpleBackendBestAuthFactory(): BackendFactory("SimpleBackendBestAuth")
317 {
318 }
319
320 DNSBackend *make(const string& suffix="") override
321 {
322 return new SimpleBackendBestAuth(suffix);
323 }
324 };
325
326 class SimpleBackendNoMetaFactory : public BackendFactory
327 {
328 public:
329 SimpleBackendNoMetaFactory(): BackendFactory("SimpleBackendNoMeta")
330 {
331 }
332
333 DNSBackend *make(const string& suffix="") override
334 {
335 return new SimpleBackendNoMeta(suffix);
336 }
337 };
338
339 struct UeberBackendSetupArgFixture {
340 UeberBackendSetupArgFixture() {
341 extern AuthQueryCache QC;
342 ::arg().set("query-cache-ttl")="0";
343 ::arg().set("negquery-cache-ttl")="0";
344 ::arg().set("consistent-backends")="no";
345 QC.purge();
346 g_zoneCache.setRefreshInterval(0);
347 g_zoneCache.clear();
348 BackendMakers().clear();
349 SimpleBackend::s_zones.clear();
350 SimpleBackend::s_metadata.clear();
351 };
352 };
353
354 static void testWithoutThenWithAuthCache(std::function<void(UeberBackend& ub)> func)
355 {
356 extern AuthQueryCache QC;
357
358 {
359 /* disable the cache */
360 ::arg().set("query-cache-ttl")="0";
361 ::arg().set("negquery-cache-ttl")="0";
362 QC.purge();
363 QC.setMaxEntries(0);
364 /* keep zone cache disabled */
365 g_zoneCache.setRefreshInterval(0);
366 g_zoneCache.clear();
367
368 UeberBackend ub;
369 func(ub);
370 }
371
372 {
373 /* enable the cache */
374 ::arg().set("query-cache-ttl")="20";
375 ::arg().set("negquery-cache-ttl")="60";
376 QC.purge();
377 QC.setMaxEntries(100000);
378 /* keep zone cache disabled */
379 g_zoneCache.setRefreshInterval(0);
380 g_zoneCache.clear();
381
382 UeberBackend ub;
383 /* a first time to fill the cache */
384 func(ub);
385 /* a second time to make sure every call has been tried with the cache filled */
386 func(ub);
387 }
388 }
389
390 static void testWithoutThenWithZoneCache(std::function<void(UeberBackend& ub)> func)
391 {
392 extern AuthQueryCache QC;
393
394 {
395 /* disable zone cache */
396 g_zoneCache.setRefreshInterval(0);
397 g_zoneCache.clear();
398 /* keep auth caches disabled */
399 ::arg().set("query-cache-ttl")="0";
400 ::arg().set("negquery-cache-ttl")="0";
401 QC.purge();
402 QC.setMaxEntries(0);
403
404 UeberBackend ub;
405 func(ub);
406 }
407
408 // This test is broken without getAllDomains() in SimpleBackend
409 // {
410 // /* enable zone cache */
411 // //g_zoneCache.setRefreshInterval(60);
412 // g_zoneCache.clear();
413 // /* keep auth caches disabled */
414 // ::arg().set("query-cache-ttl")="0";
415 // ::arg().set("negquery-cache-ttl")="0";
416 // QC.purge();
417 // QC.setMaxEntries(0);
418 //
419 // UeberBackend ub;
420 // ub.updateZoneCache();
421 // func(ub);
422 // }
423 }
424
425 BOOST_FIXTURE_TEST_SUITE(test_ueberbackend_cc, UeberBackendSetupArgFixture)
426
427 static std::vector<DNSZoneRecord> getRecords(UeberBackend& ub, const DNSName& name, uint16_t qtype, int zoneId, const DNSPacket* pkt)
428 {
429 std::vector<DNSZoneRecord> result;
430
431 ub.lookup(QType(qtype), name, zoneId, const_cast<DNSPacket*>(pkt));
432
433 DNSZoneRecord dzr;
434 while (ub.get(dzr))
435 {
436 result.push_back(std::move(dzr));
437 }
438
439 return result;
440 }
441
442 static void checkRecordExists(const std::vector<DNSZoneRecord>& records, const DNSName& name, uint16_t type, int zoneId, uint8_t scopeMask, bool auth)
443 {
444 BOOST_REQUIRE_GE(records.size(), 1U);
445 for (const auto& record : records) {
446 if (record.domain_id == zoneId &&
447 record.dr.d_type == type &&
448 record.dr.d_name == name &&
449 record.auth == auth &&
450 record.scopeMask == scopeMask) {
451 return;
452 }
453 }
454 BOOST_CHECK_MESSAGE(false, "Record " + name.toString() + "/" + QType(type).toString() + " - " + std::to_string(zoneId) + " not found");
455 }
456
457 BOOST_AUTO_TEST_CASE(test_simple) {
458
459 try {
460 SimpleBackend::SimpleDNSZone zoneA(DNSName("powerdns.com."), 1);
461 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::SOA, "ns1.powerdns.com. powerdns.com. 3 600 600 3600000 604800", 3600));
462 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::AAAA, "2001:db8::1", 60));
463 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("www.powerdns.com."), QType::A, "192.168.0.1", 60));
464 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("geo.powerdns.com."), QType::A, "192.168.0.42", 60));
465 SimpleBackend::s_zones[1].insert(zoneA);
466
467 BackendMakers().report(new SimpleBackendFactory());
468 BackendMakers().launch("SimpleBackend:1");
469 UeberBackend::go();
470
471 auto testFunction = [](UeberBackend& ub) -> void {
472 {
473 // test SOA with unknown zone id == -1
474 auto records = getRecords(ub, DNSName("powerdns.com."), QType::SOA, -1, nullptr);
475 BOOST_REQUIRE_EQUAL(records.size(), 1U);
476 checkRecordExists(records, DNSName("powerdns.com."), QType::SOA, 1, 0, true);
477 }
478
479 {
480 // test ANY with zone id == -1
481 auto records = getRecords(ub, DNSName("powerdns.com."), QType::ANY, -1, nullptr);
482 BOOST_REQUIRE_EQUAL(records.size(), 2U);
483 checkRecordExists(records, DNSName("powerdns.com."), QType::SOA, 1, 0, true);
484 checkRecordExists(records, DNSName("powerdns.com."), QType::AAAA, 1, 0, true);
485 }
486
487 {
488 // test AAAA with zone id == -1
489 auto records = getRecords(ub, DNSName("powerdns.com."), QType::AAAA, -1, nullptr);
490 BOOST_REQUIRE_EQUAL(records.size(), 1U);
491 checkRecordExists(records, DNSName("powerdns.com."), QType::AAAA, 1, 0, true);
492 }
493
494 {
495 // test NODATA with zone id == -1
496 auto records = getRecords(ub, DNSName("powerdns.com."), QType::PTR, -1, nullptr);
497 BOOST_REQUIRE_EQUAL(records.size(), 0U);
498 }
499
500 {
501 // test ANY with zone id set
502 auto records = getRecords(ub, DNSName("powerdns.com."), QType::ANY, 1, nullptr);
503 BOOST_REQUIRE_EQUAL(records.size(), 2U);
504 checkRecordExists(records, DNSName("powerdns.com."), QType::SOA, 1, 0, true);
505 checkRecordExists(records, DNSName("powerdns.com."), QType::AAAA, 1, 0, true);
506 }
507
508 {
509 // test AAAA with zone id set
510 auto records = getRecords(ub, DNSName("powerdns.com."), QType::AAAA, 1, nullptr);
511 BOOST_REQUIRE_EQUAL(records.size(), 1U);
512 checkRecordExists(records, DNSName("powerdns.com."), QType::AAAA, 1, 0, true);
513 }
514
515 {
516 // test NODATA with zone id set
517 auto records = getRecords(ub, DNSName("powerdns.com."), QType::PTR, 1, nullptr);
518 BOOST_REQUIRE_EQUAL(records.size(), 0U);
519 }
520
521 {
522 // test ANY with wrong zone id
523 auto records = getRecords(ub, DNSName("powerdns.com."), QType::ANY, 65535, nullptr);
524 BOOST_REQUIRE_EQUAL(records.size(), 0U);
525 }
526
527 {
528 // test a DNS packet is correctly passed and that the corresponding scope is passed back
529 DNSPacket pkt(true);
530 ComboAddress remote("192.0.2.1");
531 pkt.setRemote(&remote);
532 auto records = getRecords(ub, DNSName("geo.powerdns.com."), QType::ANY, 1, &pkt);
533 BOOST_REQUIRE_EQUAL(records.size(), 1U);
534 checkRecordExists(records, DNSName("geo.powerdns.com."), QType::A, 1, 32, true);
535 // and that we don't get the same result for a different client
536 remote = ComboAddress("198.51.100.1");
537 pkt.setRemote(&remote);
538 records = getRecords(ub, DNSName("geo.powerdns.com."), QType::ANY, 1, &pkt);
539 BOOST_REQUIRE_EQUAL(records.size(), 1U);
540 checkRecordExists(records, DNSName("geo.powerdns.com."), QType::A, 1, 24, true);
541 }
542
543 };
544 testWithoutThenWithAuthCache(testFunction);
545 testWithoutThenWithZoneCache(testFunction);
546 }
547 catch(const PDNSException& e) {
548 cerr<<e.reason<<endl;
549 throw;
550 }
551 catch(const std::exception& e) {
552 cerr<<e.what()<<endl;
553 throw;
554 }
555 catch(...) {
556 cerr<<"An unexpected error occurred.."<<endl;
557 throw;
558 }
559 }
560
561 BOOST_AUTO_TEST_CASE(test_multi_backends_separate_zones) {
562 // one zone in backend 1, a second zone in backend 2
563 // no overlap
564
565 try {
566 SimpleBackend::SimpleDNSZone zoneA(DNSName("powerdns.com."), 1);
567 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::SOA, "ns1.powerdns.com. powerdns.com. 3 600 600 3600000 604800", 3600));
568 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::AAAA, "2001:db8::1", 60));
569 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("www.powerdns.com."), QType::A, "192.168.0.1", 60));
570 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("geo.powerdns.com."), QType::A, "192.168.0.42", 60));
571 SimpleBackend::s_zones[1].insert(zoneA);
572
573 SimpleBackend::SimpleDNSZone zoneB(DNSName("powerdns.org."), 2);
574 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.org."), QType::SOA, "ns1.powerdns.org. powerdns.org. 3 600 600 3600000 604800", 3600));
575 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.org."), QType::AAAA, "2001:db8::2", 60));
576 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("www.powerdns.org."), QType::AAAA, "2001:db8::2", 60));
577 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("geo.powerdns.org."), QType::AAAA, "2001:db8::42", 60));
578 SimpleBackend::s_zones[2].insert(zoneB);
579
580 BackendMakers().report(new SimpleBackendFactory());
581 BackendMakers().launch("SimpleBackend:1, SimpleBackend:2");
582 UeberBackend::go();
583
584 auto testFunction = [](UeberBackend& ub) -> void {
585 {
586 // test SOA with unknown zone id == -1
587 auto records = getRecords(ub, DNSName("powerdns.com."), QType::SOA, -1, nullptr);
588 BOOST_REQUIRE_EQUAL(records.size(), 1U);
589 checkRecordExists(records, DNSName("powerdns.com."), QType::SOA, 1, 0, true);
590
591 records = getRecords(ub, DNSName("powerdns.org."), QType::SOA, -1, nullptr);
592 BOOST_REQUIRE_EQUAL(records.size(), 1U);
593 checkRecordExists(records, DNSName("powerdns.org."), QType::SOA, 2, 0, true);
594 }
595
596 {
597 // test ANY with zone id == -1
598 auto records = getRecords(ub, DNSName("powerdns.com."), QType::ANY, -1, nullptr);
599 BOOST_REQUIRE_EQUAL(records.size(), 2U);
600 checkRecordExists(records, DNSName("powerdns.com."), QType::SOA, 1, 0, true);
601 checkRecordExists(records, DNSName("powerdns.com."), QType::AAAA, 1, 0, true);
602
603 records = getRecords(ub, DNSName("powerdns.org."), QType::ANY, -1, nullptr);
604 BOOST_REQUIRE_EQUAL(records.size(), 2U);
605 checkRecordExists(records, DNSName("powerdns.org."), QType::SOA, 2, 0, true);
606 checkRecordExists(records, DNSName("powerdns.org."), QType::AAAA, 2, 0, true);
607 }
608
609 {
610 // test AAAA with zone id == -1
611 auto records = getRecords(ub, DNSName("powerdns.com."), QType::AAAA, -1, nullptr);
612 BOOST_REQUIRE_EQUAL(records.size(), 1U);
613 checkRecordExists(records, DNSName("powerdns.com."), QType::AAAA, 1, 0, true);
614
615 records = getRecords(ub, DNSName("powerdns.org."), QType::AAAA, -1, nullptr);
616 BOOST_REQUIRE_EQUAL(records.size(), 1U);
617 checkRecordExists(records, DNSName("powerdns.org."), QType::AAAA, 2, 0, true);
618 }
619
620 {
621 // test NODATA with zone id == -1
622 auto records = getRecords(ub, DNSName("powerdns.com."), QType::PTR, -1, nullptr);
623 BOOST_REQUIRE_EQUAL(records.size(), 0U);
624
625 records = getRecords(ub, DNSName("powerdns.org."), QType::PTR, -1, nullptr);
626 BOOST_REQUIRE_EQUAL(records.size(), 0U);
627 }
628
629 {
630 // test ANY with zone id set
631 auto records = getRecords(ub, DNSName("powerdns.com."), QType::ANY, 1, nullptr);
632 BOOST_REQUIRE_EQUAL(records.size(), 2U);
633 checkRecordExists(records, DNSName("powerdns.com."), QType::SOA, 1, 0, true);
634 checkRecordExists(records, DNSName("powerdns.com."), QType::AAAA, 1, 0, true);
635
636 records = getRecords(ub, DNSName("powerdns.org."), QType::ANY, 2, nullptr);
637 BOOST_REQUIRE_EQUAL(records.size(), 2U);
638 checkRecordExists(records, DNSName("powerdns.org."), QType::SOA, 2, 0, true);
639 checkRecordExists(records, DNSName("powerdns.org."), QType::AAAA, 2, 0, true);
640 }
641
642 {
643 // test AAAA with zone id set
644 auto records = getRecords(ub, DNSName("powerdns.com."), QType::AAAA, 1, nullptr);
645 BOOST_REQUIRE_EQUAL(records.size(), 1U);
646 checkRecordExists(records, DNSName("powerdns.com."), QType::AAAA, 1, 0, true);
647
648 records = getRecords(ub, DNSName("www.powerdns.org."), QType::AAAA, 2, nullptr);
649 BOOST_REQUIRE_EQUAL(records.size(), 1U);
650 checkRecordExists(records, DNSName("www.powerdns.org."), QType::AAAA, 2, 0, true);
651 }
652
653 {
654 // test NODATA with zone id set
655 auto records = getRecords(ub, DNSName("powerdns.com."), QType::PTR, 1, nullptr);
656 BOOST_REQUIRE_EQUAL(records.size(), 0U);
657
658 records = getRecords(ub, DNSName("powerdns.org."), QType::PTR, 2, nullptr);
659 BOOST_REQUIRE_EQUAL(records.size(), 0U);
660 }
661
662 {
663 // test ANY with wrong zone id
664 auto records = getRecords(ub, DNSName("powerdns.com."), QType::ANY, 2, nullptr);
665 BOOST_REQUIRE_EQUAL(records.size(), 0U);
666
667 records = getRecords(ub, DNSName("powerdns.org."), QType::ANY, 1, nullptr);
668 BOOST_REQUIRE_EQUAL(records.size(), 0U);
669
670 records = getRecords(ub, DNSName("not-powerdns.com."), QType::ANY, 65535, nullptr);
671 BOOST_REQUIRE_EQUAL(records.size(), 0U);
672 }
673
674 {
675 // test a DNS packet is correctly passed and that the corresponding scope is passed back
676 DNSPacket pkt(true);
677 ComboAddress remote("192.0.2.1");
678 pkt.setRemote(&remote);
679 auto records = getRecords(ub, DNSName("geo.powerdns.com."), QType::ANY, 1, &pkt);
680 BOOST_REQUIRE_EQUAL(records.size(), 1U);
681 checkRecordExists(records, DNSName("geo.powerdns.com."), QType::A, 1, 32, true);
682 // and that we don't get the same result for a different client
683 remote = ComboAddress("198.51.100.1");
684 pkt.setRemote(&remote);
685 records = getRecords(ub, DNSName("geo.powerdns.com."), QType::ANY, 1, &pkt);
686 BOOST_REQUIRE_EQUAL(records.size(), 1U);
687 checkRecordExists(records, DNSName("geo.powerdns.com."), QType::A, 1, 24, true);
688 }
689
690 };
691 testWithoutThenWithAuthCache(testFunction);
692 testWithoutThenWithZoneCache(testFunction);
693 }
694 catch(const PDNSException& e) {
695 cerr<<e.reason<<endl;
696 throw;
697 }
698 catch(const std::exception& e) {
699 cerr<<e.what()<<endl;
700 throw;
701 }
702 catch(...) {
703 cerr<<"An unexpected error occurred.."<<endl;
704 throw;
705 }
706 }
707
708 BOOST_AUTO_TEST_CASE(test_multi_backends_overlay) {
709 // one backend holds the SOA, NS and one A
710 // a second backend holds another A and AAAA
711 try {
712 SimpleBackend::SimpleDNSZone zoneA(DNSName("powerdns.com."), 1);
713 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::SOA, "ns1.powerdns.com. powerdns.com. 3 600 600 3600000 604800", 3600));
714 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::NS, "ns1.powerdns.com.", 3600));
715 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::A, "192.168.0.1", 60));
716 SimpleBackend::s_zones[1].insert(zoneA);
717
718 SimpleBackend::SimpleDNSZone zoneB(DNSName("powerdns.com."), 1);
719 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::A, "192.168.0.2", 60));
720 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::AAAA, "2001:db8::1", 60));
721 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("www.powerdns.com."), QType::A, "192.168.0.1", 60));
722 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("geo.powerdns.com."), QType::A, "192.168.0.42", 60));
723 SimpleBackend::s_zones[2].insert(zoneB);
724
725 BackendMakers().report(new SimpleBackendFactory());
726 BackendMakers().launch("SimpleBackend:1, SimpleBackend:2");
727 UeberBackend::go();
728
729 auto testFunction = [](UeberBackend& ub) -> void {
730 {
731 // test SOA with unknown zone id == -1
732 auto records = getRecords(ub, DNSName("powerdns.com."), QType::SOA, -1, nullptr);
733 BOOST_REQUIRE_EQUAL(records.size(), 1U);
734 checkRecordExists(records, DNSName("powerdns.com."), QType::SOA, 1, 0, true);
735 }
736
737 {
738 // test ANY with zone id == -1
739 auto records = getRecords(ub, DNSName("powerdns.com."), QType::ANY, -1, nullptr);
740 // /!\ only 3 records are returned since we don't allow spreading the same name over several backends
741 BOOST_REQUIRE_EQUAL(records.size(), 3U);
742 checkRecordExists(records, DNSName("powerdns.com."), QType::SOA, 1, 0, true);
743 checkRecordExists(records, DNSName("powerdns.com."), QType::NS, 1, 0, true);
744 checkRecordExists(records, DNSName("powerdns.com."), QType::A, 1, 0, true);
745 //checkRecordExists(records, DNSName("powerdns.com."), QType::AAAA, 1, 0, true);
746 }
747
748 {
749 // test AAAA with zone id == -1
750 auto records = getRecords(ub, DNSName("powerdns.com."), QType::AAAA, -1, nullptr);
751 // /!\ the AAAA will be found on an exact search, but not on an ANY one
752 BOOST_REQUIRE_EQUAL(records.size(), 1U);
753 checkRecordExists(records, DNSName("powerdns.com."), QType::AAAA, 1, 0, true);
754 }
755
756 {
757 // test NODATA with zone id == -1
758 auto records = getRecords(ub, DNSName("powerdns.com."), QType::PTR, -1, nullptr);
759 BOOST_REQUIRE_EQUAL(records.size(), 0U);
760 }
761
762 {
763 // test ANY with zone id set
764 auto records = getRecords(ub, DNSName("powerdns.com."), QType::ANY, 1, nullptr);
765 // /!\ only 3 records are returned since we don't allow spreading the same name over several backends
766 BOOST_REQUIRE_EQUAL(records.size(), 3U);
767 checkRecordExists(records, DNSName("powerdns.com."), QType::SOA, 1, 0, true);
768 checkRecordExists(records, DNSName("powerdns.com."), QType::NS, 1, 0, true);
769 checkRecordExists(records, DNSName("powerdns.com."), QType::A, 1, 0, true);
770 //checkRecordExists(records, DNSName("powerdns.com."), QType::AAAA, 1, 0, true);
771 }
772
773 {
774 // test AAAA with zone id set
775 auto records = getRecords(ub, DNSName("powerdns.com."), QType::AAAA, 1, nullptr);
776 // /!\ the AAAA will be found on an exact search, but not on an ANY one
777 BOOST_REQUIRE_EQUAL(records.size(), 1U);
778 checkRecordExists(records, DNSName("powerdns.com."), QType::AAAA, 1, 0, true);
779 }
780
781 {
782 // test www - A with zone id set (only in the second backend)
783 auto records = getRecords(ub, DNSName("www.powerdns.com."), QType::A, 1, nullptr);
784 BOOST_REQUIRE_EQUAL(records.size(), 1U);
785 checkRecordExists(records, DNSName("www.powerdns.com."), QType::A, 1, 0, true);
786 }
787
788 {
789 // test NODATA with zone id set
790 auto records = getRecords(ub, DNSName("powerdns.com."), QType::PTR, 1, nullptr);
791 BOOST_REQUIRE_EQUAL(records.size(), 0U);
792 }
793
794 {
795 // test ANY with wrong zone id
796 auto records = getRecords(ub, DNSName("powerdns.com."), QType::ANY, 2, nullptr);
797 BOOST_REQUIRE_EQUAL(records.size(), 0U);
798 }
799
800 {
801 // test a DNS packet is correctly passed and that the corresponding scope is passed back
802 DNSPacket pkt(true);
803 ComboAddress remote("192.0.2.1");
804 pkt.setRemote(&remote);
805 auto records = getRecords(ub, DNSName("geo.powerdns.com."), QType::ANY, 1, &pkt);
806 BOOST_REQUIRE_EQUAL(records.size(), 1U);
807 checkRecordExists(records, DNSName("geo.powerdns.com."), QType::A, 1, 32, true);
808 // and that we don't get the same result for a different client
809 remote = ComboAddress("198.51.100.1");
810 pkt.setRemote(&remote);
811 records = getRecords(ub, DNSName("geo.powerdns.com."), QType::ANY, 1, &pkt);
812 BOOST_REQUIRE_EQUAL(records.size(), 1U);
813 checkRecordExists(records, DNSName("geo.powerdns.com."), QType::A, 1, 24, true);
814 }
815
816 };
817 testWithoutThenWithAuthCache(testFunction);
818 testWithoutThenWithZoneCache(testFunction);
819 }
820 catch(const PDNSException& e) {
821 cerr<<e.reason<<endl;
822 throw;
823 }
824 catch(const std::exception& e) {
825 cerr<<e.what()<<endl;
826 throw;
827 }
828 catch(...) {
829 cerr<<"An unexpected error occurred.."<<endl;
830 throw;
831 }
832 }
833
834 BOOST_AUTO_TEST_CASE(test_multi_backends_overlay_name) {
835 // one backend holds the apex with SOA, NS and one A
836 // a second backend holds others names
837 try {
838 SimpleBackend::SimpleDNSZone zoneA(DNSName("powerdns.com."), 1);
839 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::SOA, "ns1.powerdns.com. powerdns.com. 3 600 600 3600000 604800", 3600));
840 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::NS, "ns1.powerdns.com.", 3600));
841 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::A, "192.168.0.1", 60));
842 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::A, "192.168.0.2", 60));
843 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::AAAA, "2001:db8::1", 60));
844 SimpleBackend::s_zones[1].insert(zoneA);
845
846 SimpleBackend::SimpleDNSZone zoneB(DNSName("powerdns.com."), 1);
847 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("www.powerdns.com."), QType::A, "192.168.0.1", 60));
848 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("www.powerdns.com."), QType::AAAA, "192.168.0.1", 60));
849 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("geo.powerdns.com."), QType::A, "192.168.0.42", 60));
850 SimpleBackend::s_zones[2].insert(zoneB);
851
852 BackendMakers().report(new SimpleBackendFactory());
853 BackendMakers().launch("SimpleBackend:1, SimpleBackend:2");
854 UeberBackend::go();
855
856 auto testFunction = [](UeberBackend& ub) -> void {
857 {
858 // test SOA with unknown zone id == -1
859 auto records = getRecords(ub, DNSName("powerdns.com."), QType::SOA, -1, nullptr);
860 BOOST_REQUIRE_EQUAL(records.size(), 1U);
861 checkRecordExists(records, DNSName("powerdns.com."), QType::SOA, 1, 0, true);
862 }
863
864 {
865 // test ANY with zone id == -1
866 auto records = getRecords(ub, DNSName("powerdns.com."), QType::ANY, -1, nullptr);
867 BOOST_REQUIRE_EQUAL(records.size(), 5U);
868 checkRecordExists(records, DNSName("powerdns.com."), QType::SOA, 1, 0, true);
869 checkRecordExists(records, DNSName("powerdns.com."), QType::NS, 1, 0, true);
870 checkRecordExists(records, DNSName("powerdns.com."), QType::A, 1, 0, true);
871 checkRecordExists(records, DNSName("powerdns.com."), QType::AAAA, 1, 0, true);
872 }
873
874 {
875 // test AAAA with zone id == -1
876 auto records = getRecords(ub, DNSName("powerdns.com."), QType::AAAA, -1, nullptr);
877 BOOST_REQUIRE_EQUAL(records.size(), 1U);
878 checkRecordExists(records, DNSName("powerdns.com."), QType::AAAA, 1, 0, true);
879 }
880
881 {
882 // test NODATA with zone id == -1
883 auto records = getRecords(ub, DNSName("powerdns.com."), QType::PTR, -1, nullptr);
884 BOOST_REQUIRE_EQUAL(records.size(), 0U);
885 }
886
887 {
888 // test ANY with zone id set
889 auto records = getRecords(ub, DNSName("powerdns.com."), QType::ANY, 1, nullptr);
890 BOOST_REQUIRE_EQUAL(records.size(), 5U);
891 checkRecordExists(records, DNSName("powerdns.com."), QType::SOA, 1, 0, true);
892 checkRecordExists(records, DNSName("powerdns.com."), QType::NS, 1, 0, true);
893 checkRecordExists(records, DNSName("powerdns.com."), QType::A, 1, 0, true);
894 checkRecordExists(records, DNSName("powerdns.com."), QType::AAAA, 1, 0, true);
895 }
896
897 {
898 // test AAAA with zone id set
899 auto records = getRecords(ub, DNSName("powerdns.com."), QType::AAAA, 1, nullptr);
900 BOOST_REQUIRE_EQUAL(records.size(), 1U);
901 checkRecordExists(records, DNSName("powerdns.com."), QType::AAAA, 1, 0, true);
902 }
903
904 {
905 // test www - A with zone id set (only in the second backend)
906 auto records = getRecords(ub, DNSName("www.powerdns.com."), QType::A, 1, nullptr);
907 BOOST_REQUIRE_EQUAL(records.size(), 1U);
908 checkRecordExists(records, DNSName("www.powerdns.com."), QType::A, 1, 0, true);
909 }
910
911 {
912 // test NODATA with zone id set
913 auto records = getRecords(ub, DNSName("powerdns.com."), QType::PTR, 1, nullptr);
914 BOOST_REQUIRE_EQUAL(records.size(), 0U);
915 }
916
917 {
918 // test ANY with wrong zone id
919 auto records = getRecords(ub, DNSName("powerdns.com."), QType::ANY, 2, nullptr);
920 BOOST_REQUIRE_EQUAL(records.size(), 0U);
921 }
922
923 {
924 // test a DNS packet is correctly passed and that the corresponding scope is passed back
925 DNSPacket pkt(true);
926 ComboAddress remote("192.0.2.1");
927 pkt.setRemote(&remote);
928 auto records = getRecords(ub, DNSName("geo.powerdns.com."), QType::ANY, 1, &pkt);
929 BOOST_REQUIRE_EQUAL(records.size(), 1U);
930 checkRecordExists(records, DNSName("geo.powerdns.com."), QType::A, 1, 32, true);
931 // and that we don't get the same result for a different client
932 remote = ComboAddress("198.51.100.1");
933 pkt.setRemote(&remote);
934 records = getRecords(ub, DNSName("geo.powerdns.com."), QType::ANY, 1, &pkt);
935 BOOST_REQUIRE_EQUAL(records.size(), 1U);
936 checkRecordExists(records, DNSName("geo.powerdns.com."), QType::A, 1, 24, true);
937 }
938
939 };
940 testWithoutThenWithAuthCache(testFunction);
941 testWithoutThenWithZoneCache(testFunction);
942 }
943 catch(const PDNSException& e) {
944 cerr<<e.reason<<endl;
945 throw;
946 }
947 catch(const std::exception& e) {
948 cerr<<e.what()<<endl;
949 throw;
950 }
951 catch(...) {
952 cerr<<"An unexpected error occurred.."<<endl;
953 throw;
954 }
955 }
956
957 BOOST_AUTO_TEST_CASE(test_child_zone) {
958 // Backend 1 holds zone A "com" while backend 2 holds zone B "powerdns.com"
959 // Check that DS queries are correctly handled
960
961 try {
962 SimpleBackend::SimpleDNSZone zoneA(DNSName("com."), 1);
963 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("com."), QType::SOA, "a.gtld-servers.net. nstld.verisign-grs.com. 3 600 600 3600000 604800", 3600));
964 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::NS, "ns1.powerdns.com.", 3600));
965 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::DS, "44030 8 3 7DD75AE1565051F9563CF8DF976AC99CDCA51E3463019C81BD2BB083 82F3854E", 3600));
966 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("ns1.powerdns.com."), QType::A, "192.0.2.1", 3600));
967 SimpleBackend::s_zones[1].insert(zoneA);
968
969 SimpleBackend::SimpleDNSZone zoneB(DNSName("powerdns.com."), 2);
970 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::SOA, "ns1.powerdns.com. powerdns.com. 3 600 600 3600000 604800", 3600));
971 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::AAAA, "2001:db8::2", 60));
972 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::NS, "ns1.powerdns.com.", 3600));
973 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("ns1.powerdns.com."), QType::A, "192.0.2.1", 3600));
974 SimpleBackend::s_zones[2].insert(zoneB);
975
976 BackendMakers().report(new SimpleBackendFactory());
977 BackendMakers().launch("SimpleBackend:1, SimpleBackend:2");
978 UeberBackend::go();
979
980 auto testFunction = [](UeberBackend& ub) -> void {
981 {
982 // test SOA with unknown zone id == -1
983 auto records = getRecords(ub, DNSName("com."), QType::SOA, -1, nullptr);
984 BOOST_REQUIRE_EQUAL(records.size(), 1U);
985 checkRecordExists(records, DNSName("com."), QType::SOA, 1, 0, true);
986
987 records = getRecords(ub, DNSName("powerdns.com."), QType::SOA, -1, nullptr);
988 BOOST_REQUIRE_EQUAL(records.size(), 1U);
989 checkRecordExists(records, DNSName("powerdns.com."), QType::SOA, 2, 0, true);
990 }
991
992 {
993 // test ANY with zone id == -1
994 auto records = getRecords(ub, DNSName("powerdns.com."), QType::ANY, -1, nullptr);
995 BOOST_REQUIRE_EQUAL(records.size(), 3U);
996 checkRecordExists(records, DNSName("powerdns.com."), QType::SOA, 2, 0, true);
997 checkRecordExists(records, DNSName("powerdns.com."), QType::NS, 2, 0, true);
998 checkRecordExists(records, DNSName("powerdns.com."), QType::AAAA, 2, 0, true);
999 }
1000
1001 {
1002 // test getAuth() for DS
1003 SOAData sd;
1004 BOOST_REQUIRE(ub.getAuth(DNSName("powerdns.com."), QType::DS, &sd));
1005 BOOST_CHECK_EQUAL(sd.qname.toString(), "com.");
1006 BOOST_CHECK_EQUAL(sd.domain_id, 1);
1007 }
1008
1009 {
1010 // test getAuth() for A
1011 SOAData sd;
1012 BOOST_REQUIRE(ub.getAuth(DNSName("powerdns.com."), QType::A, &sd));
1013 BOOST_CHECK_EQUAL(sd.qname.toString(), "powerdns.com.");
1014 BOOST_CHECK_EQUAL(sd.domain_id, 2);
1015 }
1016
1017 };
1018 testWithoutThenWithAuthCache(testFunction);
1019 testWithoutThenWithZoneCache(testFunction);
1020 }
1021 catch(const PDNSException& e) {
1022 cerr<<e.reason<<endl;
1023 throw;
1024 }
1025 catch(const std::exception& e) {
1026 cerr<<e.what()<<endl;
1027 throw;
1028 }
1029 catch(...) {
1030 cerr<<"An unexpected error occurred.."<<endl;
1031 throw;
1032 }
1033 }
1034
1035 BOOST_AUTO_TEST_CASE(test_multi_backends_best_soa) {
1036 // several backends, one returns the best SOA it has right away
1037 // while the others do simple lookups
1038
1039 try {
1040 SimpleBackend::SimpleDNSZone zoneA(DNSName("d.0.1.0.0.2.ip6.arpa."), 1);
1041 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("d.0.1.0.0.2.ip6.arpa."), QType::SOA, "ns.apnic.net. read-txt-record-of-zone-first-dns-admin.apnic.net. 3005126844 7200 1800 604800 3600", 3600));
1042 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("2.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa."), QType::PTR, "a.reverse.", 3600));
1043 SimpleBackend::s_zones[1].insert(zoneA);
1044
1045 SimpleBackend::SimpleDNSZone zoneB(DNSName("0.1.0.0.2.ip6.arpa."), 2);
1046 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("0.1.0.0.2.ip6.arpa."), QType::SOA, "ns.apnic.net. read-txt-record-of-zone-first-dns-admin.apnic.net. 3005126844 7200 1800 604800 3600", 3600));
1047 SimpleBackend::s_zones[2].insert(zoneB);
1048
1049 BackendMakers().report(new SimpleBackendFactory());
1050 BackendMakers().report(new SimpleBackendBestAuthFactory());
1051 BackendMakers().launch("SimpleBackendBestAuth:1, SimpleBackend:2");
1052 UeberBackend::go();
1053
1054 auto testFunction = [](UeberBackend& ub) -> void {
1055 {
1056 auto sbba = dynamic_cast<SimpleBackendBestAuth*>(ub.backends.at(0));
1057 BOOST_REQUIRE(sbba != nullptr);
1058 sbba->d_authLookupCount = 0;
1059
1060 // test getAuth()
1061 SOAData sd;
1062 BOOST_REQUIRE(ub.getAuth(DNSName("2.4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa."), QType::PTR, &sd));
1063 BOOST_CHECK_EQUAL(sd.qname.toString(), "d.0.1.0.0.2.ip6.arpa.");
1064 BOOST_CHECK_EQUAL(sd.domain_id, 1);
1065
1066 // check that at most one auth lookup occurred to this backend (O with caching enabled)
1067 BOOST_CHECK_LE(sbba->d_authLookupCount, 1U);
1068 }
1069
1070 };
1071 testWithoutThenWithAuthCache(testFunction);
1072 testWithoutThenWithZoneCache(testFunction);
1073 }
1074 catch(const PDNSException& e) {
1075 cerr<<e.reason<<endl;
1076 throw;
1077 }
1078 catch(const std::exception& e) {
1079 cerr<<e.what()<<endl;
1080 throw;
1081 }
1082 catch(...) {
1083 cerr<<"An unexpected error occurred.."<<endl;
1084 throw;
1085 }
1086 }
1087
1088 BOOST_AUTO_TEST_CASE(test_multi_backends_metadata) {
1089 // we have metadata stored in the first and second backend.
1090 // We can read from the first backend but not from the second, since the first will return "true" even though it has nothing
1091 // Updating will insert into the first backend, leaving the first one untouched
1092
1093 try {
1094 SimpleBackend::SimpleDNSZone zoneA(DNSName("powerdns.com."), 1);
1095 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::SOA, "ns1.powerdns.com. powerdns.com. 3 600 600 3600000 604800", 3600));
1096 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.com."), QType::AAAA, "2001:db8::1", 60));
1097 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("www.powerdns.com."), QType::A, "192.168.0.1", 60));
1098 zoneA.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("geo.powerdns.com."), QType::A, "192.168.0.42", 60));
1099 SimpleBackend::s_zones[1].insert(zoneA);
1100 SimpleBackend::s_metadata[1].insert(SimpleBackend::SimpleMetaData(DNSName("powerdns.com."), "test-data-a", { "value1", "value2"}));
1101
1102 SimpleBackend::SimpleDNSZone zoneB(DNSName("powerdns.org."), 2);
1103 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.org."), QType::SOA, "ns1.powerdns.org. powerdns.org. 3 600 600 3600000 604800", 3600));
1104 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("powerdns.org."), QType::AAAA, "2001:db8::2", 60));
1105 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("www.powerdns.org."), QType::AAAA, "2001:db8::2", 60));
1106 zoneB.d_records->insert(SimpleBackend::SimpleDNSRecord(DNSName("geo.powerdns.org."), QType::AAAA, "2001:db8::42", 60));
1107 SimpleBackend::s_zones[2].insert(zoneB);
1108 SimpleBackend::s_metadata[2].insert(SimpleBackend::SimpleMetaData(DNSName("powerdns.org."), "test-data-b", { "value1", "value2"}));
1109
1110 BackendMakers().report(new SimpleBackendFactory());
1111 BackendMakers().launch("SimpleBackend:1, SimpleBackend:2");
1112 UeberBackend::go();
1113
1114 auto testFunction = [](UeberBackend& ub) -> void {
1115 {
1116 // check the initial values
1117 std::vector<std::string> values;
1118 BOOST_CHECK(ub.getDomainMetadata(DNSName("powerdns.com."), "test-data-a", values));
1119 BOOST_REQUIRE_EQUAL(values.size(), 2U);
1120 BOOST_CHECK_EQUAL(values.at(0), "value1");
1121 BOOST_CHECK_EQUAL(values.at(1), "value2");
1122 values.clear();
1123 BOOST_CHECK(ub.getDomainMetadata(DNSName("powerdns.com."), "test-data-b", values));
1124 BOOST_CHECK_EQUAL(values.size(), 0U);
1125 values.clear();
1126 BOOST_CHECK(ub.getDomainMetadata(DNSName("powerdns.org."), "test-data-a", values));
1127 BOOST_CHECK_EQUAL(values.size(), 0U);
1128 values.clear();
1129 BOOST_CHECK(ub.getDomainMetadata(DNSName("powerdns.org."), "test-data-b", values));
1130 BOOST_CHECK_EQUAL(values.size(), 0U);
1131 }
1132
1133 {
1134 // update the values
1135 BOOST_CHECK(ub.setDomainMetadata(DNSName("powerdns.com."), "test-data-a", { "value3" }));
1136 BOOST_CHECK(ub.setDomainMetadata(DNSName("powerdns.org."), "test-data-a", { "value4" }));
1137 BOOST_CHECK(ub.setDomainMetadata(DNSName("powerdns.org."), "test-data-b", { "value5" }));
1138 }
1139
1140 // check the updated values
1141 {
1142 std::vector<std::string> values;
1143 BOOST_CHECK(ub.getDomainMetadata(DNSName("powerdns.com."), "test-data-a", values));
1144 BOOST_REQUIRE_EQUAL(values.size(), 1U);
1145 BOOST_CHECK_EQUAL(values.at(0), "value3");
1146 values.clear();
1147 BOOST_CHECK(ub.getDomainMetadata(DNSName("powerdns.org."), "test-data-a", values));
1148 BOOST_REQUIRE_EQUAL(values.size(), 1U);
1149 BOOST_CHECK_EQUAL(values.at(0), "value4");
1150 values.clear();
1151 BOOST_CHECK(ub.getDomainMetadata(DNSName("powerdns.org."), "test-data-b", values));
1152 BOOST_REQUIRE_EQUAL(values.size(), 1U);
1153 BOOST_CHECK_EQUAL(values.at(0), "value5");
1154 }
1155
1156 {
1157 // check that it has not been updated in the second backend
1158 const auto& it = SimpleBackend::s_metadata[2].find(std::make_tuple(DNSName("powerdns.org."), "test-data-b"));
1159 BOOST_REQUIRE(it != SimpleBackend::s_metadata[2].end());
1160 BOOST_REQUIRE_EQUAL(it->d_values.size(), 2U);
1161 BOOST_CHECK_EQUAL(it->d_values.at(0), "value1");
1162 BOOST_CHECK_EQUAL(it->d_values.at(1), "value2");
1163 }
1164 };
1165
1166 UeberBackend ub;
1167 testFunction(ub);
1168 }
1169 catch(const PDNSException& e) {
1170 cerr<<e.reason<<endl;
1171 throw;
1172 }
1173 catch(const std::exception& e) {
1174 cerr<<e.what()<<endl;
1175 throw;
1176 }
1177 catch(...) {
1178 cerr<<"An unexpected error occurred.."<<endl;
1179 throw;
1180 }
1181 }
1182
1183
1184 BOOST_AUTO_TEST_SUITE_END();