1 #define BOOST_TEST_DYN_LINK
2 #include <boost/test/unit_test.hpp>
4 #include "test-syncres_cc.hh"
5 #include "taskqueue.hh"
6 #include "rec-taskqueue.hh"
8 BOOST_AUTO_TEST_SUITE(syncres_cc1
)
10 BOOST_AUTO_TEST_CASE(test_root_primed
)
12 std::unique_ptr
<SyncRes
> sr
;
17 const DNSName
target("a.root-servers.net.");
19 /* we are primed, but only with non-auth data so we cannot resolve A a.root-servers.net. without any query */
20 vector
<DNSRecord
> ret
;
21 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
22 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
23 BOOST_REQUIRE_EQUAL(ret
.size(), 0U);
26 res
= sr
->beginResolve(target
, QType(QType::AAAA
), QClass::IN
, ret
);
27 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
28 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Indeterminate
);
29 BOOST_REQUIRE_EQUAL(ret
.size(), 0U);
32 catch (const ImmediateServFailException
) {
37 BOOST_AUTO_TEST_CASE(test_root_primed_ns
)
39 std::unique_ptr
<SyncRes
> sr
;
43 const DNSName
target(".");
45 /* we are primed, but we should not be able to NS . without any query
46 because the . NS entry is not stored as authoritative */
48 size_t queriesCount
= 0;
50 sr
->setAsyncCallback([target
, &queriesCount
](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
53 if (domain
== target
&& type
== QType::NS
) {
55 setLWResult(res
, 0, true, false, true);
56 char addr
[] = "a.root-servers.net.";
57 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
59 addRecordToLW(res
, g_rootdnsname
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
62 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
63 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
65 return LWResult::Result::Success
;
68 return LWResult::Result::Timeout
;
71 vector
<DNSRecord
> ret
;
72 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
73 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
74 BOOST_REQUIRE_EQUAL(ret
.size(), 13U);
75 BOOST_CHECK_EQUAL(queriesCount
, 1U);
78 BOOST_AUTO_TEST_CASE(test_root_not_primed
)
80 std::unique_ptr
<SyncRes
> sr
;
83 size_t queriesCount
= 0;
85 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
88 if (domain
== g_rootdnsname
&& type
== QType::NS
) {
89 setLWResult(res
, 0, true, false, true);
90 addRecordToLW(res
, g_rootdnsname
, QType::NS
, "a.root-servers.net.", DNSResourceRecord::ANSWER
, 3600);
91 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
92 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
94 return LWResult::Result::Success
;
97 return LWResult::Result::Timeout
;
100 /* we are not primed yet, so SyncRes will have to call primeHints()
101 then call getRootNS(), for which at least one of the root servers needs to answer */
102 vector
<DNSRecord
> ret
;
103 int res
= sr
->beginResolve(DNSName("."), QType(QType::NS
), QClass::IN
, ret
);
104 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
105 BOOST_CHECK_EQUAL(ret
.size(), 1U);
106 BOOST_CHECK_EQUAL(queriesCount
, 2U);
109 BOOST_AUTO_TEST_CASE(test_root_not_primed_and_no_response
)
111 std::unique_ptr
<SyncRes
> sr
;
113 // We expect an error, do not log it
114 g_log
.toConsole(Logger::Critical
);
115 std::set
<ComboAddress
> downServers
;
117 /* we are not primed yet, so SyncRes will have to call primeHints()
118 then call getRootNS(), for which at least one of the root servers needs to answer.
119 None will, so it should ServFail.
121 sr
->setAsyncCallback([&downServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* /* res */, bool* /* chained */) {
122 downServers
.insert(ip
);
123 return LWResult::Result::Timeout
;
126 vector
<DNSRecord
> ret
;
127 int res
= sr
->beginResolve(DNSName("."), QType(QType::NS
), QClass::IN
, ret
);
128 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
129 BOOST_CHECK_EQUAL(ret
.size(), 0U);
130 BOOST_CHECK(downServers
.size() > 0);
131 /* we explicitly refuse to mark the root servers down */
132 for (const auto& server
: downServers
) {
133 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 0U);
137 BOOST_AUTO_TEST_CASE(test_root_ns_poison_resistance
)
139 std::unique_ptr
<SyncRes
> sr
;
143 const DNSName
target("www.example.com.");
145 sr
->setAsyncCallback([target
](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
146 if (domain
== g_rootdnsname
&& type
== QType::NS
) {
148 setLWResult(res
, 0, true, false, true);
149 char addr
[] = "a.root-servers.net.";
150 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
152 addRecordToLW(res
, g_rootdnsname
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
155 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
156 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
158 return LWResult::Result::Success
;
161 if (domain
== target
&& type
== QType::A
) {
163 setLWResult(res
, 0, true, false, true);
164 addRecordToLW(res
, target
, QType::A
, "1.2.3.4", DNSResourceRecord::ANSWER
, 3600);
166 addRecordToLW(res
, ".", QType::NS
, "poison.name.", DNSResourceRecord::AUTHORITY
, 3600);
167 addRecordToLW(res
, "poison.name", QType::A
, "4.5.6.7", DNSResourceRecord::ADDITIONAL
, 3600);
169 return LWResult::Result::Success
;
172 return LWResult::Result::Timeout
;
175 vector
<DNSRecord
> ret
;
176 // Check we have 13 root servers
177 int res
= sr
->beginResolve(g_rootdnsname
, QType(QType::NS
), QClass::IN
, ret
);
178 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
179 BOOST_REQUIRE_EQUAL(ret
.size(), 13U);
183 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
184 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
185 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
187 // Still should have 13
189 res
= sr
->beginResolve(g_rootdnsname
, QType(QType::NS
), QClass::IN
, ret
);
190 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
191 BOOST_REQUIRE_EQUAL(ret
.size(), 13U);
194 BOOST_AUTO_TEST_CASE(test_root_primed_ns_update
)
196 std::unique_ptr
<SyncRes
> sr
;
200 const DNSName
target(".");
201 const DNSName
aroot("a.root-servers.net.");
202 const string newA
= "1.2.3.4";
203 const string newAAAA
= "1::2";
205 /* we are primed, but we should not be able to NS . without any query
206 because the . NS entry is not stored as authoritative */
208 size_t queriesCount
= 0;
210 auto asynccb
= [target
, &queriesCount
, aroot
, newA
, newAAAA
](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
213 if (domain
== target
&& type
== QType::NS
) {
215 setLWResult(res
, 0, true, false, true);
216 char addr
[] = "a.root-servers.net.";
217 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
219 addRecordToLW(res
, g_rootdnsname
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
222 addRecordToLW(res
, aroot
.toString(), QType::A
, newA
, DNSResourceRecord::ADDITIONAL
, 3600);
223 addRecordToLW(res
, aroot
.toString(), QType::AAAA
, newAAAA
, DNSResourceRecord::ADDITIONAL
, 3600);
225 return LWResult::Result::Success
;
227 return LWResult::Result::Timeout
;
230 sr
->setAsyncCallback(asynccb
);
233 Utility::gettimeofday(&now
, nullptr);
235 vector
<DNSRecord
> ret
;
236 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
237 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
238 BOOST_REQUIRE_EQUAL(ret
.size(), 13U);
239 BOOST_CHECK_EQUAL(queriesCount
, 1U);
242 time_t cached
= g_recCache
->get(now
.tv_sec
, aroot
, QType::A
, MemRecursorCache::None
, &ret
, ComboAddress());
243 BOOST_CHECK(cached
> 0);
244 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
245 BOOST_CHECK(getRR
<ARecordContent
>(ret
[0])->getCA() == ComboAddress(newA
));
248 cached
= g_recCache
->get(now
.tv_sec
, aroot
, QType::AAAA
, MemRecursorCache::None
, &ret
, ComboAddress());
249 BOOST_CHECK(cached
> 0);
250 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
251 BOOST_CHECK(getRR
<AAAARecordContent
>(ret
[0])->getCA() == ComboAddress(newAAAA
));
254 static void test_edns_formerr_fallback_f(bool sample
)
256 std::unique_ptr
<SyncRes
> sr
;
259 sr
->setQNameMinimization();
261 ComboAddress noEDNSServer
;
262 size_t queriesWithEDNS
= 0;
263 size_t queriesWithoutEDNS
= 0;
265 sr
->setAsyncCallback([&queriesWithEDNS
, &queriesWithoutEDNS
, &noEDNSServer
, sample
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool /* sendRDQuery */, int EDNS0Level
, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
266 if (EDNS0Level
!= 0) {
270 setLWResult(res
, RCode::FormErr
);
271 return LWResult::Result::Success
;
274 queriesWithoutEDNS
++;
276 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& !doTCP
) {
277 setLWResult(res
, 0, true, false, false);
278 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
279 return LWResult::Result::Success
;
282 return sample
? basicRecordsForQnameMinimization(res
, domain
, type
) : LWResult::Result::Timeout
;
287 /* fake that the root NS doesn't handle EDNS, check that we fallback */
288 vector
<DNSRecord
> ret
;
289 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
290 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
291 BOOST_CHECK_EQUAL(ret
.size(), 1U);
292 BOOST_CHECK_EQUAL(queriesWithEDNS
, sample
? 3U : 1U);
293 BOOST_CHECK_EQUAL(queriesWithoutEDNS
, sample
? 4U : 1U);
294 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), sample
? 3U : 1U);
295 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(noEDNSServer
), SyncRes::EDNSStatus::NOEDNS
);
298 BOOST_AUTO_TEST_CASE(test_edns_formerr_fallback
)
300 test_edns_formerr_fallback_f(false);
303 BOOST_AUTO_TEST_CASE(test_edns_formerr_fallback_qmin
)
305 // DISABLED UNTIL QNAME MINIMIZATION IS THERE
307 test_edns_formerr_fallback_f(true);
310 BOOST_AUTO_TEST_CASE(test_edns_formerr_but_edns_enabled
)
312 std::unique_ptr
<SyncRes
> sr
;
315 /* in this test, the auth answers with FormErr to an EDNS-enabled
316 query, but the response does contain EDNS so we should not mark
317 it as EDNS ignorant or intolerant.
319 size_t queriesWithEDNS
= 0;
320 size_t queriesWithoutEDNS
= 0;
321 std::set
<ComboAddress
> usedServers
;
323 sr
->setAsyncCallback([&queriesWithEDNS
, &queriesWithoutEDNS
, &usedServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int type
, bool /* doTCP */, bool /* sendRDQuery */, int EDNS0Level
, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
324 if (EDNS0Level
> 0) {
328 queriesWithoutEDNS
++;
330 usedServers
.insert(ip
);
332 if (type
== QType::DNAME
) {
333 setLWResult(res
, RCode::FormErr
);
334 if (EDNS0Level
> 0) {
335 res
->d_haveEDNS
= true;
337 return LWResult::Result::Success
;
340 return LWResult::Result::Timeout
;
345 vector
<DNSRecord
> ret
;
346 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::DNAME
), QClass::IN
, ret
);
347 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
348 BOOST_CHECK_EQUAL(ret
.size(), 0U);
349 BOOST_CHECK_EQUAL(queriesWithEDNS
, 26U);
350 BOOST_CHECK_EQUAL(queriesWithoutEDNS
, 0U);
351 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), 0U);
352 BOOST_CHECK_EQUAL(usedServers
.size(), 26U);
353 for (const auto& server
: usedServers
) {
354 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
358 BOOST_AUTO_TEST_CASE(test_meta_types
)
360 std::unique_ptr
<SyncRes
> sr
;
363 static const std::set
<uint16_t> invalidTypes
= {128, QType::AXFR
, QType::IXFR
, QType::RRSIG
, QType::NSEC3
, QType::OPT
, QType::TSIG
, QType::TKEY
, QType::MAILA
, QType::MAILB
, 65535};
365 for (const auto qtype
: invalidTypes
) {
366 size_t queriesCount
= 0;
368 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& /* ip */, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* /* res */, bool* /* chained */) {
370 return LWResult::Result::Timeout
;
375 vector
<DNSRecord
> ret
;
376 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(qtype
), QClass::IN
, ret
);
377 BOOST_CHECK_EQUAL(res
, -1);
378 BOOST_CHECK_EQUAL(ret
.size(), 0U);
379 BOOST_CHECK_EQUAL(queriesCount
, 0U);
383 BOOST_AUTO_TEST_CASE(test_tc_fallback_to_tcp
)
385 std::unique_ptr
<SyncRes
> sr
;
388 sr
->setAsyncCallback([](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool doTCP
, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
390 setLWResult(res
, 0, false, true, false);
391 return LWResult::Result::Success
;
393 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& doTCP
) {
394 setLWResult(res
, 0, true, false, false);
395 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
396 return LWResult::Result::Success
;
399 return LWResult::Result::Timeout
;
404 /* fake that the NS truncates every request over UDP, we should fallback to TCP */
405 vector
<DNSRecord
> ret
;
406 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
407 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
410 BOOST_AUTO_TEST_CASE(test_tc_over_tcp
)
412 std::unique_ptr
<SyncRes
> sr
;
415 size_t tcpQueriesCount
= 0;
417 sr
->setAsyncCallback([&tcpQueriesCount
](const ComboAddress
& /* ip */, const DNSName
& domain
, int /* type */, bool doTCP
, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
419 setLWResult(res
, 0, true, true, false);
420 return LWResult::Result::Success
;
423 /* first TCP query is answered with a TC response */
425 if (tcpQueriesCount
== 1) {
426 setLWResult(res
, 0, true, true, false);
429 setLWResult(res
, 0, true, false, false);
432 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
433 return LWResult::Result::Success
;
438 vector
<DNSRecord
> ret
;
439 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
440 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
441 BOOST_CHECK_EQUAL(tcpQueriesCount
, 2U);
444 BOOST_AUTO_TEST_CASE(test_all_nss_down
)
446 std::unique_ptr
<SyncRes
> sr
;
448 std::set
<ComboAddress
> downServers
;
452 sr
->setAsyncCallback([&downServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
453 if (isRootServer(ip
)) {
454 setLWResult(res
, 0, false, false, true);
455 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
456 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
457 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
458 return LWResult::Result::Success
;
460 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
461 setLWResult(res
, 0, false, false, true);
462 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
463 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
464 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
465 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
466 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
467 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
468 return LWResult::Result::Success
;
471 downServers
.insert(ip
);
472 return LWResult::Result::Timeout
;
476 DNSName
target("powerdns.com.");
478 vector
<DNSRecord
> ret
;
479 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
480 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
481 BOOST_CHECK_EQUAL(ret
.size(), 0U);
482 BOOST_CHECK_EQUAL(downServers
.size(), 4U);
484 time_t now
= sr
->getNow().tv_sec
;
485 for (const auto& server
: downServers
) {
486 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1U);
487 BOOST_CHECK(SyncRes::isThrottled(now
, server
, target
, QType::A
));
491 BOOST_AUTO_TEST_CASE(test_all_nss_network_error
)
493 std::unique_ptr
<SyncRes
> sr
;
495 std::set
<ComboAddress
> downServers
;
499 sr
->setAsyncCallback([&downServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
500 if (isRootServer(ip
)) {
501 setLWResult(res
, 0, false, false, true);
502 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
503 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
504 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
505 return LWResult::Result::Success
;
507 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
508 setLWResult(res
, 0, false, false, true);
509 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
510 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
511 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
512 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
513 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
514 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
515 return LWResult::Result::Success
;
518 downServers
.insert(ip
);
519 return LWResult::Result::Timeout
;
523 /* exact same test than the previous one, except instead of a time out we fake a network error */
524 DNSName
target("powerdns.com.");
526 vector
<DNSRecord
> ret
;
527 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
528 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
529 BOOST_CHECK_EQUAL(ret
.size(), 0U);
530 BOOST_CHECK_EQUAL(downServers
.size(), 4U);
532 time_t now
= sr
->getNow().tv_sec
;
533 for (const auto& server
: downServers
) {
534 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1U);
535 BOOST_CHECK(SyncRes::isThrottled(now
, server
, target
, QType::A
));
539 BOOST_AUTO_TEST_CASE(test_all_nss_send_tc_then_garbage_over_tcp
)
541 std::unique_ptr
<SyncRes
> sr
;
546 std::set
<ComboAddress
> downServers
;
548 sr
->setAsyncCallback([&downServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int /* type */, bool doTCP
, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
549 if (isRootServer(ip
)) {
550 setLWResult(res
, 0, false, false, true);
551 addRecordToLW(res
, "lock-up.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
552 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
553 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
554 return LWResult::Result::Success
;
558 setLWResult(res
, 0, false, true, false);
559 return LWResult::Result::Success
;
562 downServers
.insert(ip
);
564 setLWResult(res
, RCode::FormErr
, false, false, false);
565 res
->d_validpacket
= false;
566 return LWResult::Result::Success
;
570 DNSName
target("www.lock-up.");
572 vector
<DNSRecord
> ret
;
573 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
574 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
575 BOOST_CHECK_EQUAL(ret
.size(), 0U);
576 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
578 for (const auto& server
: downServers
) {
579 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
580 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 1000000U);
584 BOOST_AUTO_TEST_CASE(test_all_nss_send_garbage_over_udp
)
586 std::unique_ptr
<SyncRes
> sr
;
591 std::set
<ComboAddress
> downServers
;
592 size_t queriesCount
= 0;
594 sr
->setAsyncCallback([&queriesCount
, &downServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
595 if (isRootServer(ip
)) {
596 setLWResult(res
, 0, false, false, true);
597 addRecordToLW(res
, "lock-up.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
598 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
599 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
600 return LWResult::Result::Success
;
604 downServers
.insert(ip
);
606 setLWResult(res
, RCode::FormErr
, false, false, false);
607 res
->d_validpacket
= false;
608 return LWResult::Result::Success
;
611 DNSName
target("www.lock-up.");
613 vector
<DNSRecord
> ret
;
614 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
615 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
616 BOOST_CHECK_EQUAL(ret
.size(), 0U);
617 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
618 /* two queries with EDNS, that's it */
619 BOOST_CHECK_EQUAL(queriesCount
, 2U);
621 for (const auto& server
: downServers
) {
622 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
623 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 1000000U);
624 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSIGNORANT
);
628 BOOST_AUTO_TEST_CASE(test_regular_ns_send_refused
)
630 std::unique_ptr
<SyncRes
> sr
;
635 std::set
<ComboAddress
> downServers
;
636 size_t queriesCount
= 0;
638 sr
->setAsyncCallback([&queriesCount
, &downServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
639 if (isRootServer(ip
)) {
640 setLWResult(res
, 0, false, false, true);
641 addRecordToLW(res
, "refused.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
642 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
643 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
644 return LWResult::Result::Success
;
648 downServers
.insert(ip
);
650 setLWResult(res
, RCode::Refused
, false, false, true);
652 return LWResult::Result::Success
;
655 DNSName
target("www.refused.");
657 vector
<DNSRecord
> ret
;
658 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
659 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
660 BOOST_CHECK_EQUAL(ret
.size(), 0U);
661 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
662 BOOST_CHECK_EQUAL(queriesCount
, 2U);
664 for (const auto& server
: downServers
) {
665 /* same as any other server */
666 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
667 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 0U);
668 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
672 BOOST_AUTO_TEST_CASE(test_forward_ns_send_refused
)
674 std::unique_ptr
<SyncRes
> sr
;
679 std::set
<ComboAddress
> downServers
;
680 size_t queriesCount
= 0;
682 const DNSName
target("www.refused.");
684 SyncRes::AuthDomain ad
;
685 const std::vector
<ComboAddress
> forwardedNSs
{ComboAddress("192.0.2.42:53"), ComboAddress("192.0.2.43:53")};
686 ad
.d_rdForward
= false;
687 ad
.d_servers
= forwardedNSs
;
688 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
690 sr
->setAsyncCallback([&queriesCount
, &downServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
691 if (isRootServer(ip
)) {
692 setLWResult(res
, 0, false, false, true);
693 addRecordToLW(res
, "refused.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
694 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
695 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
696 return LWResult::Result::Success
;
700 downServers
.insert(ip
);
702 setLWResult(res
, RCode::Refused
, false, false, true);
704 return LWResult::Result::Success
;
707 vector
<DNSRecord
> ret
;
708 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
709 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
710 BOOST_CHECK_EQUAL(ret
.size(), 0U);
711 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
712 BOOST_CHECK_EQUAL(queriesCount
, 2U);
714 for (const auto& server
: forwardedNSs
) {
715 BOOST_CHECK_EQUAL(downServers
.count(server
), 1U);
716 /* same as any other server */
717 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
718 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 0U);
719 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
723 BOOST_AUTO_TEST_CASE(test_forward_ns_send_servfail
)
725 std::unique_ptr
<SyncRes
> sr
;
730 std::set
<ComboAddress
> downServers
;
731 size_t queriesCount
= 0;
733 const DNSName
target("www.refused.");
735 SyncRes::AuthDomain ad
;
736 const std::vector
<ComboAddress
> forwardedNSs
{ComboAddress("192.0.2.42:53"), ComboAddress("192.0.2.43:53")};
737 ad
.d_rdForward
= false;
738 ad
.d_servers
= forwardedNSs
;
739 (*SyncRes::t_sstorage
.domainmap
)[DNSName("refused.")] = ad
;
741 sr
->setAsyncCallback([&queriesCount
, &downServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
742 if (isRootServer(ip
)) {
743 setLWResult(res
, 0, false, false, true);
744 addRecordToLW(res
, "refused.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
745 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
746 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
747 return LWResult::Result::Success
;
751 downServers
.insert(ip
);
753 setLWResult(res
, RCode::ServFail
, false, false, true);
755 return LWResult::Result::Success
;
758 vector
<DNSRecord
> ret
;
759 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
760 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
761 BOOST_CHECK_EQUAL(ret
.size(), 0U);
762 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
763 BOOST_CHECK_EQUAL(queriesCount
, 2U);
765 for (const auto& server
: forwardedNSs
) {
766 BOOST_CHECK_EQUAL(downServers
.count(server
), 1U);
767 /* on servfail from a server we forward to we only increase the NS speed so
768 that a different server might be tried instead, but we don't throttle */
769 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
770 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName(server
.toStringWithPort()), server
), 1000000U);
771 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
775 BOOST_AUTO_TEST_CASE(test_only_one_ns_up_resolving_itself_with_glue
)
777 std::unique_ptr
<SyncRes
> sr
;
782 DNSName
target("www.powerdns.com.");
784 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
785 if (isRootServer(ip
)) {
786 setLWResult(res
, 0, false, false, true);
787 if (domain
== target
) {
788 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
789 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.net.", DNSResourceRecord::AUTHORITY
, 172800);
790 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
791 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
793 else if (domain
== DNSName("pdns-public-ns2.powerdns.net.")) {
794 addRecordToLW(res
, "powerdns.net.", QType::NS
, "pdns-public-ns2.powerdns.net.", DNSResourceRecord::AUTHORITY
, 172800);
795 addRecordToLW(res
, "powerdns.net.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
796 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
797 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
799 return LWResult::Result::Success
;
801 else if (ip
== ComboAddress("192.0.2.3:53")) {
802 setLWResult(res
, 0, true, false, true);
803 if (domain
== DNSName("pdns-public-ns2.powerdns.net.")) {
804 if (type
== QType::A
) {
805 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::A
, "192.0.2.3");
807 else if (type
== QType::AAAA
) {
808 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::AAAA
, "2001:DB8::3");
811 else if (domain
== target
) {
812 if (type
== QType::A
) {
813 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
815 else if (type
== QType::AAAA
) {
816 addRecordToLW(res
, domain
, QType::AAAA
, "2001:DB8::1");
819 return LWResult::Result::Success
;
821 return LWResult::Result::Timeout
;
824 vector
<DNSRecord
> ret
;
825 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
826 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
827 BOOST_CHECK_EQUAL(ret
.size(), 1U);
830 BOOST_AUTO_TEST_CASE(test_os_limit_errors
)
832 std::unique_ptr
<SyncRes
> sr
;
834 std::set
<ComboAddress
> downServers
;
838 sr
->setAsyncCallback([&downServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
839 if (isRootServer(ip
)) {
840 setLWResult(res
, 0, false, false, true);
841 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
842 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
843 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
844 return LWResult::Result::Success
;
846 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
847 setLWResult(res
, 0, false, false, true);
848 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
849 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
850 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
851 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
852 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
853 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
854 return LWResult::Result::Success
;
857 if (downServers
.size() < 3) {
858 /* only the last one will answer */
859 downServers
.insert(ip
);
860 return LWResult::Result::OSLimitError
;
863 setLWResult(res
, 0, true, false, true);
864 addRecordToLW(res
, "powerdns.com.", QType::A
, "192.0.2.42");
865 return LWResult::Result::Success
;
870 DNSName
target("powerdns.com.");
872 vector
<DNSRecord
> ret
;
873 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
874 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
875 BOOST_CHECK_EQUAL(ret
.size(), 1U);
876 BOOST_CHECK_EQUAL(downServers
.size(), 3U);
878 /* Error is reported as "OS limit error" (-2) so the servers should _NOT_ be marked down */
879 time_t now
= sr
->getNow().tv_sec
;
880 for (const auto& server
: downServers
) {
881 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 0U);
882 BOOST_CHECK(!SyncRes::isThrottled(now
, server
, target
, QType::A
));
886 BOOST_AUTO_TEST_CASE(test_glued_referral
)
888 std::unique_ptr
<SyncRes
> sr
;
893 const DNSName
target("powerdns.com.");
895 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
896 /* this will cause issue with qname minimization if we ever implement it */
897 if (domain
!= target
) {
898 return LWResult::Result::Timeout
;
901 if (isRootServer(ip
)) {
902 setLWResult(res
, 0, false, false, true);
903 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
904 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
905 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
906 return LWResult::Result::Success
;
908 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
909 setLWResult(res
, 0, false, false, true);
910 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
911 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
912 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
913 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
914 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
915 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
916 return LWResult::Result::Success
;
918 else if (ip
== ComboAddress("192.0.2.2:53") || ip
== ComboAddress("192.0.2.3:53") || ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("[2001:DB8::3]:53")) {
919 setLWResult(res
, 0, true, false, true);
920 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
921 return LWResult::Result::Success
;
924 return LWResult::Result::Timeout
;
928 vector
<DNSRecord
> ret
;
929 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
930 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
931 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
932 BOOST_CHECK(ret
[0].d_type
== QType::A
);
933 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
936 BOOST_AUTO_TEST_CASE(test_glueless_referral
)
938 std::unique_ptr
<SyncRes
> sr
;
943 const DNSName
target("powerdns.com.");
945 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
946 if (isRootServer(ip
)) {
947 setLWResult(res
, 0, false, false, true);
949 if (domain
.isPartOf(DNSName("com."))) {
950 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
952 else if (domain
.isPartOf(DNSName("org."))) {
953 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
956 setLWResult(res
, RCode::NXDomain
, false, false, true);
957 return LWResult::Result::Success
;
960 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
961 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
962 return LWResult::Result::Success
;
964 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
965 if (domain
== target
) {
966 setLWResult(res
, 0, false, false, true);
967 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
968 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
969 return LWResult::Result::Success
;
971 else if (domain
== DNSName("pdns-public-ns1.powerdns.org.")) {
972 setLWResult(res
, 0, true, false, true);
973 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2");
974 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::AAAA
, "2001:DB8::2");
975 return LWResult::Result::Success
;
977 else if (domain
== DNSName("pdns-public-ns2.powerdns.org.")) {
978 setLWResult(res
, 0, true, false, true);
979 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::A
, "192.0.2.3");
980 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::AAAA
, "2001:DB8::3");
981 return LWResult::Result::Success
;
984 setLWResult(res
, RCode::NXDomain
, false, false, true);
985 return LWResult::Result::Success
;
987 else if (ip
== ComboAddress("192.0.2.2:53") || ip
== ComboAddress("192.0.2.3:53") || ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("[2001:DB8::3]:53")) {
988 setLWResult(res
, 0, true, false, true);
989 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
990 return LWResult::Result::Success
;
993 return LWResult::Result::Timeout
;
997 vector
<DNSRecord
> ret
;
998 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
999 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1000 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1001 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1002 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1005 BOOST_AUTO_TEST_CASE(test_glueless_referral_aaaa_task
)
1007 std::unique_ptr
<SyncRes
> sr
;
1012 const DNSName
target("powerdns.com.");
1014 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1015 if (isRootServer(ip
)) {
1016 setLWResult(res
, 0, false, false, true);
1018 if (domain
.isPartOf(DNSName("com."))) {
1019 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1021 else if (domain
.isPartOf(DNSName("org."))) {
1022 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1025 setLWResult(res
, RCode::NXDomain
, false, false, true);
1026 return LWResult::Result::Success
;
1029 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1030 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1031 return LWResult::Result::Success
;
1033 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
1034 if (domain
== target
) {
1035 setLWResult(res
, 0, false, false, true);
1036 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1037 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1038 return LWResult::Result::Success
;
1040 else if (domain
== DNSName("pdns-public-ns1.powerdns.org.")) {
1041 setLWResult(res
, 0, true, false, true);
1042 if (type
== QType::A
) {
1043 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2");
1046 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::AAAA
, "2001:DB8::2");
1048 return LWResult::Result::Success
;
1050 else if (domain
== DNSName("pdns-public-ns2.powerdns.org.")) {
1051 setLWResult(res
, 0, true, false, true);
1052 if (type
== QType::A
) {
1053 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::A
, "192.0.2.3");
1056 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::AAAA
, "2001:DB8::3");
1058 return LWResult::Result::Success
;
1061 setLWResult(res
, RCode::NXDomain
, false, false, true);
1062 return LWResult::Result::Success
;
1064 else if (ip
== ComboAddress("192.0.2.2:53") || ip
== ComboAddress("192.0.2.3:53") || ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("[2001:DB8::3]:53")) {
1065 setLWResult(res
, 0, true, false, true);
1066 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
1067 return LWResult::Result::Success
;
1070 return LWResult::Result::Timeout
;
1074 vector
<DNSRecord
> ret
;
1075 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1076 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1077 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1078 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1079 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1081 // One task should be submitted
1082 BOOST_REQUIRE_EQUAL(getTaskSize(), 1U);
1083 auto task
= taskQueuePop();
1084 BOOST_CHECK(task
.d_qname
== DNSName("pdns-public-ns1.powerdns.org") || task
.d_qname
== DNSName("pdns-public-ns2.powerdns.org"));
1085 BOOST_CHECK_EQUAL(task
.d_qtype
, QType::AAAA
);
1088 BOOST_AUTO_TEST_CASE(test_edns_subnet_by_domain
)
1090 std::unique_ptr
<SyncRes
> sr
;
1095 const DNSName
target("powerdns.com.");
1096 SyncRes::addEDNSDomain(target
);
1098 EDNSSubnetOpts incomingECS
;
1099 incomingECS
.source
= Netmask("192.0.2.128/32");
1100 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1102 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1103 BOOST_REQUIRE(srcmask
);
1104 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1106 if (isRootServer(ip
)) {
1107 setLWResult(res
, 0, false, false, true);
1108 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1109 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1111 /* this one did not use the ECS info */
1112 srcmask
= boost::none
;
1114 return LWResult::Result::Success
;
1116 else if (ip
== ComboAddress("192.0.2.1:53")) {
1118 setLWResult(res
, 0, true, false, false);
1119 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1121 /* this one did, but only up to a precision of /16, not the full /24 */
1122 srcmask
= Netmask("192.0.0.0/16");
1124 return LWResult::Result::Success
;
1127 return LWResult::Result::Timeout
;
1130 SyncRes::s_ecsqueries
= 0;
1131 SyncRes::s_ecsresponses
= 0;
1132 vector
<DNSRecord
> ret
;
1133 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1134 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1135 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1136 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1137 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1138 BOOST_CHECK_EQUAL(SyncRes::s_ecsqueries
, 2U);
1139 BOOST_CHECK_EQUAL(SyncRes::s_ecsresponses
, 1U);
1140 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize4
) {
1141 BOOST_CHECK_EQUAL(entry
.second
, entry
.first
== 15 ? 1U : 0U);
1143 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize6
) {
1144 BOOST_CHECK_EQUAL(entry
.second
, 0U);
1148 BOOST_AUTO_TEST_CASE(test_edns_subnet_by_addr
)
1150 std::unique_ptr
<SyncRes
> sr
;
1155 const DNSName
target("powerdns.com.");
1156 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1158 EDNSSubnetOpts incomingECS
;
1159 incomingECS
.source
= Netmask("2001:DB8::FF/128");
1160 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1162 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1163 if (isRootServer(ip
)) {
1164 BOOST_REQUIRE(!srcmask
);
1166 setLWResult(res
, 0, false, false, true);
1167 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1168 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1169 return LWResult::Result::Success
;
1171 else if (ip
== ComboAddress("192.0.2.1:53")) {
1173 BOOST_REQUIRE(srcmask
);
1174 BOOST_CHECK_EQUAL(srcmask
->toString(), "2001:db8::/56");
1176 setLWResult(res
, 0, true, false, false);
1177 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1178 return LWResult::Result::Success
;
1181 return LWResult::Result::Timeout
;
1184 SyncRes::s_ecsqueries
= 0;
1185 SyncRes::s_ecsresponses
= 0;
1186 vector
<DNSRecord
> ret
;
1187 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1188 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1189 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1190 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1191 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1192 BOOST_CHECK_EQUAL(SyncRes::s_ecsqueries
, 1U);
1193 BOOST_CHECK_EQUAL(SyncRes::s_ecsresponses
, 1U);
1194 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize4
) {
1195 BOOST_CHECK_EQUAL(entry
.second
, 0u);
1197 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize6
) {
1198 BOOST_CHECK_EQUAL(entry
.second
, entry
.first
== 55 ? 1U : 0U);
1202 BOOST_AUTO_TEST_CASE(test_ecs_use_requestor
)
1204 std::unique_ptr
<SyncRes
> sr
;
1209 const DNSName
target("powerdns.com.");
1210 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1211 // No incoming ECS data
1212 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::none
);
1214 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1215 if (isRootServer(ip
)) {
1216 BOOST_REQUIRE(!srcmask
);
1218 setLWResult(res
, 0, false, false, true);
1219 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1220 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1221 return LWResult::Result::Success
;
1223 else if (ip
== ComboAddress("192.0.2.1:53")) {
1225 BOOST_REQUIRE(srcmask
);
1226 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1228 setLWResult(res
, 0, true, false, false);
1229 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1230 return LWResult::Result::Success
;
1233 return LWResult::Result::Timeout
;
1236 vector
<DNSRecord
> ret
;
1237 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1238 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1239 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1240 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1241 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1244 BOOST_AUTO_TEST_CASE(test_ecs_use_scope_zero
)
1246 std::unique_ptr
<SyncRes
> sr
;
1251 const DNSName
target("powerdns.com.");
1252 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1253 SyncRes::clearEDNSLocalSubnets();
1254 SyncRes::addEDNSLocalSubnet("192.0.2.254/32");
1255 // No incoming ECS data, Requestor IP not in ecs-add-for
1256 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::none
);
1258 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1259 if (isRootServer(ip
)) {
1260 BOOST_REQUIRE(!srcmask
);
1262 setLWResult(res
, 0, false, false, true);
1263 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1264 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1265 return LWResult::Result::Success
;
1267 else if (ip
== ComboAddress("192.0.2.1:53")) {
1269 BOOST_REQUIRE(srcmask
);
1270 BOOST_CHECK_EQUAL(srcmask
->toString(), "127.0.0.1/32");
1272 setLWResult(res
, 0, true, false, false);
1273 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1274 return LWResult::Result::Success
;
1277 return LWResult::Result::Timeout
;
1280 vector
<DNSRecord
> ret
;
1281 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1282 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1283 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1284 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1285 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1288 BOOST_AUTO_TEST_CASE(test_ecs_honor_incoming_mask
)
1290 std::unique_ptr
<SyncRes
> sr
;
1295 const DNSName
target("powerdns.com.");
1296 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1297 SyncRes::clearEDNSLocalSubnets();
1298 SyncRes::addEDNSLocalSubnet("192.0.2.254/32");
1299 EDNSSubnetOpts incomingECS
;
1300 incomingECS
.source
= Netmask("192.0.0.0/16");
1301 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1303 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1304 if (isRootServer(ip
)) {
1305 BOOST_REQUIRE(!srcmask
);
1307 setLWResult(res
, 0, false, false, true);
1308 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1309 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1310 return LWResult::Result::Success
;
1312 else if (ip
== ComboAddress("192.0.2.1:53")) {
1314 BOOST_REQUIRE(srcmask
);
1315 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.0.0/16");
1317 setLWResult(res
, 0, true, false, false);
1318 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1319 return LWResult::Result::Success
;
1322 return LWResult::Result::Timeout
;
1325 vector
<DNSRecord
> ret
;
1326 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1327 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1328 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1329 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1330 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1333 BOOST_AUTO_TEST_CASE(test_ecs_honor_incoming_mask_zero
)
1335 std::unique_ptr
<SyncRes
> sr
;
1340 const DNSName
target("powerdns.com.");
1341 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1342 SyncRes::clearEDNSLocalSubnets();
1343 SyncRes::addEDNSLocalSubnet("192.0.2.254/32");
1344 EDNSSubnetOpts incomingECS
;
1345 incomingECS
.source
= Netmask("0.0.0.0/0");
1346 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1348 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1349 if (isRootServer(ip
)) {
1350 BOOST_REQUIRE(!srcmask
);
1352 setLWResult(res
, 0, false, false, true);
1353 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1354 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1355 return LWResult::Result::Success
;
1357 else if (ip
== ComboAddress("192.0.2.1:53")) {
1359 BOOST_REQUIRE(srcmask
);
1360 BOOST_CHECK_EQUAL(srcmask
->toString(), "127.0.0.1/32");
1362 setLWResult(res
, 0, true, false, false);
1363 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1364 return LWResult::Result::Success
;
1367 return LWResult::Result::Timeout
;
1370 vector
<DNSRecord
> ret
;
1371 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1372 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1373 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1374 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1375 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1378 BOOST_AUTO_TEST_CASE(test_following_cname
)
1380 std::unique_ptr
<SyncRes
> sr
;
1385 const DNSName
target("cname.powerdns.com.");
1386 const DNSName
cnameTarget("cname-target.powerdns.com");
1388 sr
->setAsyncCallback([target
, cnameTarget
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1389 if (isRootServer(ip
)) {
1390 setLWResult(res
, 0, false, false, true);
1391 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1392 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1393 return LWResult::Result::Success
;
1395 else if (ip
== ComboAddress("192.0.2.1:53")) {
1397 if (domain
== target
) {
1398 setLWResult(res
, 0, true, false, false);
1399 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1400 return LWResult::Result::Success
;
1402 else if (domain
== cnameTarget
) {
1403 setLWResult(res
, 0, true, false, false);
1404 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1407 return LWResult::Result::Success
;
1410 return LWResult::Result::Timeout
;
1413 vector
<DNSRecord
> ret
;
1414 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1415 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1416 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1417 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1418 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1419 BOOST_CHECK(ret
[1].d_type
== QType::A
);
1420 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1423 BOOST_AUTO_TEST_CASE(test_cname_nxdomain
)
1425 std::unique_ptr
<SyncRes
> sr
;
1430 const DNSName
target("cname.powerdns.com.");
1431 const DNSName
cnameTarget("cname-target.powerdns.com");
1433 sr
->setAsyncCallback([target
, cnameTarget
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1434 if (isRootServer(ip
)) {
1435 setLWResult(res
, 0, false, false, true);
1436 addRecordToLW(res
, "powerdns.com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1437 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1438 return LWResult::Result::Success
;
1440 else if (ip
== ComboAddress("192.0.2.1:53")) {
1442 if (domain
== target
) {
1443 setLWResult(res
, RCode::NXDomain
, true, false, false);
1444 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1445 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1447 else if (domain
== cnameTarget
) {
1448 setLWResult(res
, RCode::NXDomain
, true, false, false);
1449 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1450 return LWResult::Result::Success
;
1453 return LWResult::Result::Success
;
1456 return LWResult::Result::Timeout
;
1459 vector
<DNSRecord
> ret
;
1460 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1461 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1462 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1463 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1464 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1465 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1467 /* a second time, to check the cache */
1469 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1470 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1471 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1472 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1473 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1474 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1477 BOOST_AUTO_TEST_CASE(test_included_poisonous_cname
)
1479 std::unique_ptr
<SyncRes
> sr
;
1484 /* In this test we directly get the NS server for cname.powerdns.com.,
1485 and we don't know whether it's also authoritative for
1486 cname-target.powerdns.com or powerdns.com, so we shouldn't accept
1487 the additional A record for cname-target.powerdns.com. */
1488 const DNSName
target("cname.powerdns.com.");
1489 const DNSName
cnameTarget("cname-target.powerdns.com");
1491 sr
->setAsyncCallback([target
, cnameTarget
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1492 if (isRootServer(ip
)) {
1494 setLWResult(res
, 0, false, false, true);
1496 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1497 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1498 return LWResult::Result::Success
;
1500 else if (ip
== ComboAddress("192.0.2.1:53")) {
1502 if (domain
== target
) {
1503 setLWResult(res
, 0, true, false, false);
1504 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1505 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
);
1506 return LWResult::Result::Success
;
1508 else if (domain
== cnameTarget
) {
1509 setLWResult(res
, 0, true, false, false);
1510 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.3");
1511 return LWResult::Result::Success
;
1514 return LWResult::Result::Success
;
1517 return LWResult::Result::Timeout
;
1520 vector
<DNSRecord
> ret
;
1521 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1522 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1523 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1524 BOOST_REQUIRE(ret
[0].d_type
== QType::CNAME
);
1525 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1526 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget(), cnameTarget
);
1527 BOOST_REQUIRE(ret
[1].d_type
== QType::A
);
1528 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1529 BOOST_CHECK(getRR
<ARecordContent
>(ret
[1])->getCA() == ComboAddress("192.0.2.3"));
1532 BOOST_AUTO_TEST_CASE(test_cname_loop
)
1534 std::unique_ptr
<SyncRes
> sr
;
1540 const DNSName
target("cname.powerdns.com.");
1542 sr
->setAsyncCallback([target
, &count
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1545 if (isRootServer(ip
)) {
1547 setLWResult(res
, 0, false, false, true);
1548 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1549 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1550 return LWResult::Result::Success
;
1552 else if (ip
== ComboAddress("192.0.2.1:53")) {
1554 if (domain
== target
) {
1555 setLWResult(res
, 0, true, false, false);
1556 addRecordToLW(res
, domain
, QType::CNAME
, domain
.toString());
1557 return LWResult::Result::Success
;
1560 return LWResult::Result::Success
;
1563 return LWResult::Result::Timeout
;
1566 vector
<DNSRecord
> ret
;
1567 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1568 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1569 BOOST_CHECK_EQUAL(ret
.size(), 0U);
1570 BOOST_CHECK_EQUAL(count
, 2U);
1572 // Again to check cache
1574 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1577 catch (const ImmediateServFailException
& ex
) {
1582 BOOST_AUTO_TEST_CASE(test_cname_long_loop
)
1584 std::unique_ptr
<SyncRes
> sr
;
1590 const DNSName
target1("cname1.powerdns.com.");
1591 const DNSName
target2("cname2.powerdns.com.");
1592 const DNSName
target3("cname3.powerdns.com.");
1593 const DNSName
target4("cname4.powerdns.com.");
1595 sr
->setAsyncCallback([target1
, target2
, target3
, target4
, &count
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1598 if (isRootServer(ip
)) {
1600 setLWResult(res
, 0, false, false, true);
1601 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1602 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1603 return LWResult::Result::Success
;
1605 else if (ip
== ComboAddress("192.0.2.1:53")) {
1607 if (domain
== target1
) {
1608 setLWResult(res
, 0, true, false, false);
1609 addRecordToLW(res
, domain
, QType::CNAME
, target2
.toString());
1610 return LWResult::Result::Success
;
1612 else if (domain
== target2
) {
1613 setLWResult(res
, 0, true, false, false);
1614 addRecordToLW(res
, domain
, QType::CNAME
, target3
.toString());
1615 return LWResult::Result::Success
;
1617 else if (domain
== target3
) {
1618 setLWResult(res
, 0, true, false, false);
1619 addRecordToLW(res
, domain
, QType::CNAME
, target4
.toString());
1620 return LWResult::Result::Success
;
1622 else if (domain
== target4
) {
1623 setLWResult(res
, 0, true, false, false);
1624 addRecordToLW(res
, domain
, QType::CNAME
, target1
.toString());
1625 return LWResult::Result::Success
;
1628 return LWResult::Result::Success
;
1631 return LWResult::Result::Timeout
;
1634 vector
<DNSRecord
> ret
;
1635 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1636 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1637 BOOST_CHECK_EQUAL(ret
.size(), 0U);
1638 BOOST_CHECK_EQUAL(count
, 8U);
1640 // And again to check cache
1642 sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1645 catch (const ImmediateServFailException
& ex
) {
1650 BOOST_AUTO_TEST_CASE(test_cname_depth
)
1652 std::unique_ptr
<SyncRes
> sr
;
1658 const DNSName
target("cname.powerdns.com.");
1660 sr
->setAsyncCallback([target
, &depth
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1661 if (isRootServer(ip
)) {
1663 setLWResult(res
, 0, false, false, true);
1664 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1665 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1666 return LWResult::Result::Success
;
1668 else if (ip
== ComboAddress("192.0.2.1:53")) {
1670 setLWResult(res
, 0, true, false, false);
1671 addRecordToLW(res
, domain
, QType::CNAME
, std::to_string(depth
) + "-cname.powerdns.com");
1673 return LWResult::Result::Success
;
1676 return LWResult::Result::Timeout
;
1679 vector
<DNSRecord
> ret
;
1680 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1681 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1682 BOOST_CHECK_EQUAL(ret
.size(), depth
);
1683 /* we have an arbitrary limit at 10 when following a CNAME chain */
1684 BOOST_CHECK_EQUAL(depth
, 10U + 2U);
1687 BOOST_AUTO_TEST_CASE(test_time_limit
)
1689 std::unique_ptr
<SyncRes
> sr
;
1695 const DNSName
target("cname.powerdns.com.");
1697 sr
->setAsyncCallback([target
, &queries
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1700 if (isRootServer(ip
)) {
1701 setLWResult(res
, 0, false, false, true);
1702 /* Pretend that this query took 2000 ms */
1705 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1706 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1707 return LWResult::Result::Success
;
1709 else if (ip
== ComboAddress("192.0.2.1:53")) {
1711 setLWResult(res
, 0, true, false, false);
1712 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1713 return LWResult::Result::Success
;
1716 return LWResult::Result::Timeout
;
1719 /* Set the maximum time to 1 ms */
1720 SyncRes::s_maxtotusec
= 1000;
1723 vector
<DNSRecord
> ret
;
1724 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1727 catch (const ImmediateServFailException
& e
) {
1729 BOOST_CHECK_EQUAL(queries
, 1U);
1732 BOOST_AUTO_TEST_CASE(test_dname_processing
)
1734 std::unique_ptr
<SyncRes
> sr
;
1739 const DNSName
dnameOwner("powerdns.com");
1740 const DNSName
dnameTarget("powerdns.net");
1742 const DNSName
target("dname.powerdns.com.");
1743 const DNSName
cnameTarget("dname.powerdns.net");
1745 const DNSName
uncachedTarget("dname-uncached.powerdns.com.");
1746 const DNSName
uncachedCNAMETarget("dname-uncached.powerdns.net.");
1748 const DNSName
synthCNAME("cname-uncached.powerdns.com.");
1749 const DNSName
synthCNAMETarget("cname-uncached.powerdns.net.");
1753 sr
->setAsyncCallback([dnameOwner
, dnameTarget
, target
, cnameTarget
, uncachedTarget
, uncachedCNAMETarget
, &queries
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1756 if (isRootServer(ip
)) {
1757 if (domain
.isPartOf(dnameOwner
)) {
1758 setLWResult(res
, 0, false, false, true);
1759 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1760 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1761 return LWResult::Result::Success
;
1763 if (domain
.isPartOf(dnameTarget
)) {
1764 setLWResult(res
, 0, false, false, true);
1765 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1766 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1767 return LWResult::Result::Success
;
1770 else if (ip
== ComboAddress("192.0.2.1:53")) {
1771 if (domain
== target
) {
1772 setLWResult(res
, 0, true, false, false);
1773 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
1774 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1775 return LWResult::Result::Success
;
1778 else if (ip
== ComboAddress("192.0.2.2:53")) {
1779 if (domain
== cnameTarget
) {
1780 setLWResult(res
, 0, true, false, false);
1781 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1783 if (domain
== uncachedCNAMETarget
) {
1784 setLWResult(res
, 0, true, false, false);
1785 addRecordToLW(res
, domain
, QType::A
, "192.0.2.3");
1787 return LWResult::Result::Success
;
1789 return LWResult::Result::Timeout
;
1792 vector
<DNSRecord
> ret
;
1793 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1795 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1796 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
1798 BOOST_CHECK_EQUAL(queries
, 4u);
1800 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1801 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1802 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1804 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
1805 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
1807 BOOST_CHECK(ret
[2].d_type
== QType::A
);
1808 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
1810 // Now check the cache
1812 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1814 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1815 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
1817 BOOST_CHECK_EQUAL(queries
, 4U);
1819 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1820 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1821 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1823 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
1824 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
1826 BOOST_CHECK(ret
[2].d_type
== QType::A
);
1827 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
1829 // Check if we correctly return a synthesized CNAME, should send out just 1 more query
1831 res
= sr
->beginResolve(uncachedTarget
, QType(QType::A
), QClass::IN
, ret
);
1833 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1834 BOOST_CHECK_EQUAL(queries
, 5U);
1836 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1837 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1838 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1840 BOOST_REQUIRE(ret
[1].d_type
== QType::CNAME
);
1841 BOOST_CHECK_EQUAL(ret
[1].d_name
, uncachedTarget
);
1842 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[1])->getTarget(), uncachedCNAMETarget
);
1844 BOOST_CHECK(ret
[2].d_type
== QType::A
);
1845 BOOST_CHECK_EQUAL(ret
[2].d_name
, uncachedCNAMETarget
);
1847 // Check if we correctly return the DNAME from cache when asked
1849 res
= sr
->beginResolve(dnameOwner
, QType(QType::DNAME
), QClass::IN
, ret
);
1850 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1851 BOOST_CHECK_EQUAL(queries
, 5U);
1853 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1854 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1855 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1857 // Check if we correctly return the synthesized CNAME from cache when asked
1859 res
= sr
->beginResolve(synthCNAME
, QType(QType::CNAME
), QClass::IN
, ret
);
1860 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1861 BOOST_CHECK_EQUAL(queries
, 5U);
1863 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1864 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1865 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1867 BOOST_REQUIRE(ret
[1].d_type
== QType::CNAME
);
1868 BOOST_CHECK(ret
[1].d_name
== synthCNAME
);
1869 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[1])->getTarget(), synthCNAMETarget
);
1872 BOOST_AUTO_TEST_CASE(test_dname_dnssec_secure
)
1874 std::unique_ptr
<SyncRes
> sr
;
1876 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
1880 const DNSName
dnameOwner("powerdns");
1881 const DNSName
dnameTarget("example");
1883 const DNSName
target("dname.powerdns");
1884 const DNSName
cnameTarget("dname.example");
1888 auto luaconfsCopy
= g_luaconfs
.getCopy();
1889 luaconfsCopy
.dsAnchors
.clear();
1890 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1891 generateKeyMaterial(dnameOwner
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1892 generateKeyMaterial(dnameTarget
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1893 g_luaconfs
.setState(luaconfsCopy
);
1897 sr
->setAsyncCallback([dnameOwner
, dnameTarget
, target
, cnameTarget
, keys
, &queries
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1899 /* We don't use the genericDSAndDNSKEYHandler here, as it would deny names existing at the wrong level of the tree, due to the way computeZoneCuts works
1900 * As such, we need to do some more work to make the answers correct.
1903 if (isRootServer(ip
)) {
1904 if (domain
.countLabels() == 0 && type
== QType::DNSKEY
) { // .|DNSKEY
1905 setLWResult(res
, 0, true, false, true);
1906 addDNSKEY(keys
, domain
, 300, res
->d_records
);
1907 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
1908 return LWResult::Result::Success
;
1910 if (domain
.countLabels() == 1 && type
== QType::DS
) { // powerdns|DS or example|DS
1911 setLWResult(res
, 0, true, false, true);
1912 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
1913 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
1914 return LWResult::Result::Success
;
1916 // For the rest, delegate!
1917 if (domain
.isPartOf(dnameOwner
)) {
1918 setLWResult(res
, 0, false, false, true);
1919 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1920 addDS(dnameOwner
, 300, res
->d_records
, keys
);
1921 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
1922 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1923 return LWResult::Result::Success
;
1925 if (domain
.isPartOf(dnameTarget
)) {
1926 setLWResult(res
, 0, false, false, true);
1927 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1928 addDS(dnameTarget
, 300, res
->d_records
, keys
);
1929 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
1930 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1931 return LWResult::Result::Success
;
1934 else if (ip
== ComboAddress("192.0.2.1:53")) {
1935 if (domain
.countLabels() == 1 && type
== QType::DNSKEY
) { // powerdns|DNSKEY
1936 setLWResult(res
, 0, true, false, true);
1937 addDNSKEY(keys
, domain
, 300, res
->d_records
);
1938 addRRSIG(keys
, res
->d_records
, domain
, 300);
1939 return LWResult::Result::Success
;
1941 if (domain
== target
&& type
== QType::DS
) { // dname.powerdns|DS
1942 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
1944 if (domain
== target
) {
1945 setLWResult(res
, 0, true, false, false);
1946 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
1947 addRRSIG(keys
, res
->d_records
, dnameOwner
, 300);
1948 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString()); // CNAME from a DNAME is not signed
1949 return LWResult::Result::Success
;
1952 else if (ip
== ComboAddress("192.0.2.2:53")) {
1953 if (domain
.countLabels() == 1 && type
== QType::DNSKEY
) { // example|DNSKEY
1954 setLWResult(res
, 0, true, false, true);
1955 addDNSKEY(keys
, domain
, 300, res
->d_records
);
1956 addRRSIG(keys
, res
->d_records
, domain
, 300);
1957 return LWResult::Result::Success
;
1959 if (domain
== cnameTarget
&& type
== QType::DS
) { // dname.example|DS
1960 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
1962 if (domain
== cnameTarget
) {
1963 setLWResult(res
, 0, true, false, false);
1964 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1965 addRRSIG(keys
, res
->d_records
, dnameTarget
, 300);
1967 return LWResult::Result::Success
;
1969 return LWResult::Result::Timeout
;
1972 vector
<DNSRecord
> ret
;
1973 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1975 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1976 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
1977 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
1979 BOOST_CHECK_EQUAL(queries
, 7U);
1981 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1982 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1983 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1985 BOOST_REQUIRE(ret
[1].d_type
== QType::RRSIG
);
1986 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
1988 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
1989 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
1991 BOOST_CHECK(ret
[3].d_type
== QType::A
);
1992 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
1994 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
1995 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
1999 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2001 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2002 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2003 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2005 BOOST_CHECK_EQUAL(queries
, 7U);
2007 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2008 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2009 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2011 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2012 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2014 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2015 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2017 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2018 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2020 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2021 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2024 BOOST_AUTO_TEST_CASE(test_dname_plus_ns_dnssec_secure
)
2026 std::unique_ptr
<SyncRes
> sr
;
2028 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
2032 const DNSName
dnameOwner("powerdns");
2033 const DNSName
dnameTarget("example");
2035 const DNSName
target("dname.powerdns");
2036 const DNSName
cnameTarget("dname.example");
2040 auto luaconfsCopy
= g_luaconfs
.getCopy();
2041 luaconfsCopy
.dsAnchors
.clear();
2042 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2043 generateKeyMaterial(dnameTarget
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2044 g_luaconfs
.setState(luaconfsCopy
);
2048 sr
->setAsyncCallback([dnameOwner
, dnameTarget
, target
, cnameTarget
, keys
, &queries
](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
2051 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
2052 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
2055 if (domain
.isPartOf(dnameOwner
)) {
2056 setLWResult(res
, 0, true, false, true);
2057 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2058 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2059 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString()); // CNAME from a DNAME is not signed
2061 addRecordToLW(res
, dnameTarget
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2062 addDS(dnameTarget
, 300, res
->d_records
, keys
);
2063 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2064 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2065 return LWResult::Result::Success
;
2067 else if (domain
== cnameTarget
) {
2068 setLWResult(res
, 0, true, false, true);
2069 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2070 addRRSIG(keys
, res
->d_records
, dnameTarget
, 300);
2071 return LWResult::Result::Success
;
2073 return LWResult::Result::Timeout
;
2076 vector
<DNSRecord
> ret
;
2077 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2079 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2080 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2081 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2083 BOOST_CHECK_EQUAL(queries
, 4U);
2085 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2086 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2087 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2089 BOOST_REQUIRE(ret
[1].d_type
== QType::RRSIG
);
2090 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2092 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2093 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2095 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2096 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2098 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2099 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2103 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2105 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2106 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2107 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2109 BOOST_CHECK_EQUAL(queries
, 4U);
2111 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2112 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2113 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2115 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2116 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2118 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2119 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2121 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2122 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2124 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2125 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2128 BOOST_AUTO_TEST_CASE(test_dname_dnssec_insecure
)
2131 * The DNAME itself is signed, but the final A record is not
2133 std::unique_ptr
<SyncRes
> sr
;
2135 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
2139 const DNSName
dnameOwner("powerdns");
2140 const DNSName
dnameTarget("example");
2142 const DNSName
target("dname.powerdns");
2143 const DNSName
cnameTarget("dname.example");
2147 auto luaconfsCopy
= g_luaconfs
.getCopy();
2148 luaconfsCopy
.dsAnchors
.clear();
2149 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2150 generateKeyMaterial(dnameOwner
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2151 g_luaconfs
.setState(luaconfsCopy
);
2155 sr
->setAsyncCallback([dnameOwner
, dnameTarget
, target
, cnameTarget
, keys
, &queries
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
2158 if (isRootServer(ip
)) {
2159 if (domain
.countLabels() == 0 && type
== QType::DNSKEY
) { // .|DNSKEY
2160 setLWResult(res
, 0, true, false, true);
2161 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2162 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2163 return LWResult::Result::Success
;
2165 if (domain
== dnameOwner
&& type
== QType::DS
) { // powerdns|DS
2166 setLWResult(res
, 0, true, false, true);
2167 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
2168 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2169 return LWResult::Result::Success
;
2171 if (domain
== dnameTarget
&& type
== QType::DS
) { // example|DS
2172 return genericDSAndDNSKEYHandler(res
, domain
, DNSName("."), type
, keys
);
2174 // For the rest, delegate!
2175 if (domain
.isPartOf(dnameOwner
)) {
2176 setLWResult(res
, 0, false, false, true);
2177 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2178 addDS(dnameOwner
, 300, res
->d_records
, keys
);
2179 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2180 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2181 return LWResult::Result::Success
;
2183 if (domain
.isPartOf(dnameTarget
)) {
2184 setLWResult(res
, 0, false, false, true);
2185 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2186 addDS(dnameTarget
, 300, res
->d_records
, keys
);
2187 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2188 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2189 return LWResult::Result::Success
;
2192 else if (ip
== ComboAddress("192.0.2.1:53")) {
2193 if (domain
.countLabels() == 1 && type
== QType::DNSKEY
) { // powerdns|DNSKEY
2194 setLWResult(res
, 0, true, false, true);
2195 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2196 addRRSIG(keys
, res
->d_records
, domain
, 300);
2197 return LWResult::Result::Success
;
2199 if (domain
== target
&& type
== QType::DS
) { // dname.powerdns|DS
2200 return genericDSAndDNSKEYHandler(res
, domain
, dnameOwner
, type
, keys
, false);
2202 if (domain
== target
) {
2203 setLWResult(res
, 0, true, false, false);
2204 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2205 addRRSIG(keys
, res
->d_records
, dnameOwner
, 300);
2206 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString()); // CNAME from a DNAME is not signed
2207 return LWResult::Result::Success
;
2210 else if (ip
== ComboAddress("192.0.2.2:53")) {
2211 if (domain
== target
&& type
== QType::DS
) { // dname.example|DS
2212 return genericDSAndDNSKEYHandler(res
, domain
, dnameTarget
, type
, keys
, false);
2214 if (domain
== cnameTarget
) {
2215 setLWResult(res
, 0, true, false, false);
2216 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2218 return LWResult::Result::Success
;
2220 return LWResult::Result::Timeout
;
2223 vector
<DNSRecord
> ret
;
2224 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2226 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2227 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
2228 BOOST_REQUIRE_EQUAL(ret
.size(), 4U); /* DNAME + RRSIG(DNAME) + CNAME + A */
2230 BOOST_CHECK_EQUAL(queries
, 7U);
2232 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2233 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2234 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2236 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2237 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2239 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2240 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2242 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2243 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2247 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2249 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2250 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
2251 BOOST_REQUIRE_EQUAL(ret
.size(), 4U); /* DNAME + RRSIG(DNAME) + CNAME + A */
2253 BOOST_CHECK_EQUAL(queries
, 7U);
2255 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2256 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2257 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2259 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2260 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2262 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2263 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2265 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2266 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2269 BOOST_AUTO_TEST_CASE(test_dname_processing_no_CNAME
)
2271 std::unique_ptr
<SyncRes
> sr
;
2276 const DNSName
dnameOwner("powerdns.com");
2277 const DNSName
dnameTarget("powerdns.net");
2279 const DNSName
target("dname.powerdns.com.");
2280 const DNSName
cnameTarget("dname.powerdns.net");
2284 sr
->setAsyncCallback([dnameOwner
, dnameTarget
, target
, cnameTarget
, &queries
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
2287 if (isRootServer(ip
)) {
2288 if (domain
.isPartOf(dnameOwner
)) {
2289 setLWResult(res
, 0, false, false, true);
2290 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2291 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2292 return LWResult::Result::Success
;
2294 if (domain
.isPartOf(dnameTarget
)) {
2295 setLWResult(res
, 0, false, false, true);
2296 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2297 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2298 return LWResult::Result::Success
;
2301 else if (ip
== ComboAddress("192.0.2.1:53")) {
2302 if (domain
== target
) {
2303 setLWResult(res
, 0, true, false, false);
2304 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2305 // No CNAME, recursor should synth
2306 return LWResult::Result::Success
;
2309 else if (ip
== ComboAddress("192.0.2.2:53")) {
2310 if (domain
== cnameTarget
) {
2311 setLWResult(res
, 0, true, false, false);
2312 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2314 return LWResult::Result::Success
;
2316 return LWResult::Result::Timeout
;
2319 vector
<DNSRecord
> ret
;
2320 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2322 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2323 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
2325 BOOST_CHECK_EQUAL(queries
, 4U);
2327 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2328 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2329 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2331 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
2332 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
2334 BOOST_CHECK(ret
[2].d_type
== QType::A
);
2335 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
2337 // Now check the cache
2339 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2341 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2342 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
2344 BOOST_CHECK_EQUAL(queries
, 4U);
2346 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2347 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2348 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2350 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
2351 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
2353 BOOST_CHECK(ret
[2].d_type
== QType::A
);
2354 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
2358 // cerr<<"asyncresolve called to ask "<<ip.toStringWithPort()<<" about "<<domain.toString()<<" / "<<QType(type).getName()<<" over "<<(doTCP ? "TCP" : "UDP")<<" (rd: "<<sendRDQuery<<", EDNS0 level: "<<EDNS0Level<<")"<<endl;
2360 - check out of band support
2366 BOOST_AUTO_TEST_CASE(test_glued_referral_child_ns_set_wrong
)
2368 std::unique_ptr
<SyncRes
> sr
;
2373 const DNSName
target("powerdns.com.");
2375 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
2376 /* this will cause issue with qname minimization if we ever implement it */
2377 if (domain
!= target
) {
2378 return LWResult::Result::Timeout
;
2381 if (isRootServer(ip
)) {
2382 setLWResult(res
, 0, false, false, true);
2383 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2384 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2385 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
2386 return LWResult::Result::Success
;
2388 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
2389 setLWResult(res
, 0, false, false, true);
2390 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
2391 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
2392 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
2393 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
2394 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
2395 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
2396 return LWResult::Result::Success
;
2398 else if (ip
== ComboAddress("192.0.2.2:53") || ip
== ComboAddress("192.0.2.3:53") || ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("[2001:DB8::3]:53")) {
2400 if (type
== QType::A
) {
2401 setLWResult(res
, 0, true, false, true);
2402 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
2403 return LWResult::Result::Success
;
2405 else if (type
== QType::NS
) {
2406 setLWResult(res
, 0, true, false, true);
2407 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-nsX1.powerdns.com.", DNSResourceRecord::ANSWER
, 172800);
2408 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-nsX2.powerdns.com.", DNSResourceRecord::ANSWER
, 172800);
2409 addRecordToLW(res
, "pdns-public-nsX1.powerdns.com.", QType::A
, "192.0.2.11", DNSResourceRecord::ADDITIONAL
, 172800);
2410 addRecordToLW(res
, "pdns-public-nsX1.powerdns.com.", QType::AAAA
, "2001:DB8::11", DNSResourceRecord::ADDITIONAL
, 172800);
2411 addRecordToLW(res
, "pdns-public-nsX2.powerdns.com.", QType::A
, "192.0.2.12", DNSResourceRecord::ADDITIONAL
, 172800);
2412 addRecordToLW(res
, "pdns-public-nsX2.powerdns.com.", QType::AAAA
, "2001:DB8::12", DNSResourceRecord::ADDITIONAL
, 172800);
2413 return LWResult::Result::Success
;
2416 return LWResult::Result::Timeout
;
2420 return LWResult::Result::Timeout
;
2424 vector
<DNSRecord
> ret
;
2425 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2426 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2427 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
2428 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2429 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
2431 // Now resolve NS to get auth NS set in cache and save the parent NS set
2433 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
2434 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2435 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
2436 BOOST_CHECK(ret
[0].d_type
== QType::NS
);
2437 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
2438 BOOST_CHECK_EQUAL(SyncRes::getSaveParentsNSSetsSize(), 1U);
2440 g_recCache
->doWipeCache(target
, false, QType::A
);
2441 SyncRes::s_save_parent_ns_set
= false;
2443 // Try to resolve now via the broken child NS set... should not work
2445 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2446 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
2447 BOOST_REQUIRE_EQUAL(ret
.size(), 0U);
2449 SyncRes::s_save_parent_ns_set
= true;
2451 // Try to resolve now via the broken child... should work now via fallback to parent NS set
2453 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2454 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2455 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
2456 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2457 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
2460 BOOST_AUTO_TEST_SUITE_END()