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_endless_glueless_referral
)
1007 std::unique_ptr
<SyncRes
> sr
;
1012 const DNSName
target("powerdns.com.");
1015 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 */) {
1016 if (isRootServer(ip
)) {
1017 setLWResult(res
, 0, false, false, true);
1019 if (domain
.isPartOf(DNSName("com."))) {
1020 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1022 else if (domain
.isPartOf(DNSName("org."))) {
1023 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1026 setLWResult(res
, RCode::NXDomain
, false, false, true);
1027 return LWResult::Result::Success
;
1030 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1031 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1032 return LWResult::Result::Success
;
1034 if (domain
== target
) {
1035 setLWResult(res
, 0, false, false, true);
1036 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1037 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1038 return LWResult::Result::Success
;
1040 setLWResult(res
, 0, false, false, true);
1041 addRecordToLW(res
, domain
, QType::NS
, std::to_string(count
) + ".ns1.powerdns.org", DNSResourceRecord::AUTHORITY
, 172800);
1042 addRecordToLW(res
, domain
, QType::NS
, std::to_string(count
) + ".ns2.powerdns.org", DNSResourceRecord::AUTHORITY
, 172800);
1044 return LWResult::Result::Success
;
1047 vector
<DNSRecord
> ret
;
1048 BOOST_CHECK_EXCEPTION(sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
),
1049 ImmediateServFailException
,
1050 [](const ImmediateServFailException
& isfe
) {
1051 return isfe
.reason
.substr(0, 9) == "More than";
1055 BOOST_AUTO_TEST_CASE(test_glueless_referral_aaaa_task
)
1057 std::unique_ptr
<SyncRes
> sr
;
1062 const DNSName
target("powerdns.com.");
1064 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 */) {
1065 if (isRootServer(ip
)) {
1066 setLWResult(res
, 0, false, false, true);
1068 if (domain
.isPartOf(DNSName("com."))) {
1069 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1071 else if (domain
.isPartOf(DNSName("org."))) {
1072 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1075 setLWResult(res
, RCode::NXDomain
, false, false, true);
1076 return LWResult::Result::Success
;
1079 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1080 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1081 return LWResult::Result::Success
;
1083 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
1084 if (domain
== target
) {
1085 setLWResult(res
, 0, false, false, true);
1086 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1087 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1088 return LWResult::Result::Success
;
1090 else if (domain
== DNSName("pdns-public-ns1.powerdns.org.")) {
1091 setLWResult(res
, 0, true, false, true);
1092 if (type
== QType::A
) {
1093 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2");
1096 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::AAAA
, "2001:DB8::2");
1098 return LWResult::Result::Success
;
1100 else if (domain
== DNSName("pdns-public-ns2.powerdns.org.")) {
1101 setLWResult(res
, 0, true, false, true);
1102 if (type
== QType::A
) {
1103 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::A
, "192.0.2.3");
1106 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::AAAA
, "2001:DB8::3");
1108 return LWResult::Result::Success
;
1111 setLWResult(res
, RCode::NXDomain
, false, false, true);
1112 return LWResult::Result::Success
;
1114 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")) {
1115 setLWResult(res
, 0, true, false, true);
1116 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
1117 return LWResult::Result::Success
;
1120 return LWResult::Result::Timeout
;
1124 vector
<DNSRecord
> ret
;
1125 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1126 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1127 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1128 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1129 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1131 // One task should be submitted
1132 BOOST_REQUIRE_EQUAL(getTaskSize(), 1U);
1133 auto task
= taskQueuePop();
1134 BOOST_CHECK(task
.d_qname
== DNSName("pdns-public-ns1.powerdns.org") || task
.d_qname
== DNSName("pdns-public-ns2.powerdns.org"));
1135 BOOST_CHECK_EQUAL(task
.d_qtype
, QType::AAAA
);
1138 BOOST_AUTO_TEST_CASE(test_edns_subnet_by_domain
)
1140 std::unique_ptr
<SyncRes
> sr
;
1145 const DNSName
target("powerdns.com.");
1146 SyncRes::addEDNSDomain(target
);
1148 EDNSSubnetOpts incomingECS
;
1149 incomingECS
.source
= Netmask("192.0.2.128/32");
1150 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1152 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 */) {
1153 BOOST_REQUIRE(srcmask
);
1154 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1156 if (isRootServer(ip
)) {
1157 setLWResult(res
, 0, false, false, true);
1158 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1159 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1161 /* this one did not use the ECS info */
1162 srcmask
= boost::none
;
1164 return LWResult::Result::Success
;
1166 else if (ip
== ComboAddress("192.0.2.1:53")) {
1168 setLWResult(res
, 0, true, false, false);
1169 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1171 /* this one did, but only up to a precision of /16, not the full /24 */
1172 srcmask
= Netmask("192.0.0.0/16");
1174 return LWResult::Result::Success
;
1177 return LWResult::Result::Timeout
;
1180 SyncRes::s_ecsqueries
= 0;
1181 SyncRes::s_ecsresponses
= 0;
1182 vector
<DNSRecord
> ret
;
1183 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1184 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1185 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1186 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1187 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1188 BOOST_CHECK_EQUAL(SyncRes::s_ecsqueries
, 2U);
1189 BOOST_CHECK_EQUAL(SyncRes::s_ecsresponses
, 1U);
1190 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize4
) {
1191 BOOST_CHECK_EQUAL(entry
.second
, entry
.first
== 15 ? 1U : 0U);
1193 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize6
) {
1194 BOOST_CHECK_EQUAL(entry
.second
, 0U);
1198 BOOST_AUTO_TEST_CASE(test_edns_subnet_by_addr
)
1200 std::unique_ptr
<SyncRes
> sr
;
1205 const DNSName
target("powerdns.com.");
1206 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1208 EDNSSubnetOpts incomingECS
;
1209 incomingECS
.source
= Netmask("2001:DB8::FF/128");
1210 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1212 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 */) {
1213 if (isRootServer(ip
)) {
1214 BOOST_REQUIRE(!srcmask
);
1216 setLWResult(res
, 0, false, false, true);
1217 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1218 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1219 return LWResult::Result::Success
;
1221 else if (ip
== ComboAddress("192.0.2.1:53")) {
1223 BOOST_REQUIRE(srcmask
);
1224 BOOST_CHECK_EQUAL(srcmask
->toString(), "2001:db8::/56");
1226 setLWResult(res
, 0, true, false, false);
1227 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1228 return LWResult::Result::Success
;
1231 return LWResult::Result::Timeout
;
1234 SyncRes::s_ecsqueries
= 0;
1235 SyncRes::s_ecsresponses
= 0;
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
);
1242 BOOST_CHECK_EQUAL(SyncRes::s_ecsqueries
, 1U);
1243 BOOST_CHECK_EQUAL(SyncRes::s_ecsresponses
, 1U);
1244 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize4
) {
1245 BOOST_CHECK_EQUAL(entry
.second
, 0u);
1247 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize6
) {
1248 BOOST_CHECK_EQUAL(entry
.second
, entry
.first
== 55 ? 1U : 0U);
1252 BOOST_AUTO_TEST_CASE(test_ecs_use_requestor
)
1254 std::unique_ptr
<SyncRes
> sr
;
1259 const DNSName
target("powerdns.com.");
1260 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1261 // No incoming ECS data
1262 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::none
);
1264 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 */) {
1265 if (isRootServer(ip
)) {
1266 BOOST_REQUIRE(!srcmask
);
1268 setLWResult(res
, 0, false, false, true);
1269 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1270 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1271 return LWResult::Result::Success
;
1273 else if (ip
== ComboAddress("192.0.2.1:53")) {
1275 BOOST_REQUIRE(srcmask
);
1276 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1278 setLWResult(res
, 0, true, false, false);
1279 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1280 return LWResult::Result::Success
;
1283 return LWResult::Result::Timeout
;
1286 vector
<DNSRecord
> ret
;
1287 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1288 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1289 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1290 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1291 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1294 BOOST_AUTO_TEST_CASE(test_ecs_use_scope_zero
)
1296 std::unique_ptr
<SyncRes
> sr
;
1301 const DNSName
target("powerdns.com.");
1302 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1303 SyncRes::clearEDNSLocalSubnets();
1304 SyncRes::addEDNSLocalSubnet("192.0.2.254/32");
1305 // No incoming ECS data, Requestor IP not in ecs-add-for
1306 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::none
);
1308 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 */) {
1309 if (isRootServer(ip
)) {
1310 BOOST_REQUIRE(!srcmask
);
1312 setLWResult(res
, 0, false, false, true);
1313 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1314 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1315 return LWResult::Result::Success
;
1317 else if (ip
== ComboAddress("192.0.2.1:53")) {
1319 BOOST_REQUIRE(srcmask
);
1320 BOOST_CHECK_EQUAL(srcmask
->toString(), "127.0.0.1/32");
1322 setLWResult(res
, 0, true, false, false);
1323 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1324 return LWResult::Result::Success
;
1327 return LWResult::Result::Timeout
;
1330 vector
<DNSRecord
> ret
;
1331 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1332 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1333 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1334 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1335 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1338 BOOST_AUTO_TEST_CASE(test_ecs_honor_incoming_mask
)
1340 std::unique_ptr
<SyncRes
> sr
;
1345 const DNSName
target("powerdns.com.");
1346 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1347 SyncRes::clearEDNSLocalSubnets();
1348 SyncRes::addEDNSLocalSubnet("192.0.2.254/32");
1349 EDNSSubnetOpts incomingECS
;
1350 incomingECS
.source
= Netmask("192.0.0.0/16");
1351 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1353 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 */) {
1354 if (isRootServer(ip
)) {
1355 BOOST_REQUIRE(!srcmask
);
1357 setLWResult(res
, 0, false, false, true);
1358 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1359 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1360 return LWResult::Result::Success
;
1362 else if (ip
== ComboAddress("192.0.2.1:53")) {
1364 BOOST_REQUIRE(srcmask
);
1365 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.0.0/16");
1367 setLWResult(res
, 0, true, false, false);
1368 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1369 return LWResult::Result::Success
;
1372 return LWResult::Result::Timeout
;
1375 vector
<DNSRecord
> ret
;
1376 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1377 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1378 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1379 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1380 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1383 BOOST_AUTO_TEST_CASE(test_ecs_honor_incoming_mask_zero
)
1385 std::unique_ptr
<SyncRes
> sr
;
1390 const DNSName
target("powerdns.com.");
1391 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1392 SyncRes::clearEDNSLocalSubnets();
1393 SyncRes::addEDNSLocalSubnet("192.0.2.254/32");
1394 EDNSSubnetOpts incomingECS
;
1395 incomingECS
.source
= Netmask("0.0.0.0/0");
1396 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1398 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 */) {
1399 if (isRootServer(ip
)) {
1400 BOOST_REQUIRE(!srcmask
);
1402 setLWResult(res
, 0, false, false, true);
1403 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1404 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1405 return LWResult::Result::Success
;
1407 else if (ip
== ComboAddress("192.0.2.1:53")) {
1409 BOOST_REQUIRE(srcmask
);
1410 BOOST_CHECK_EQUAL(srcmask
->toString(), "127.0.0.1/32");
1412 setLWResult(res
, 0, true, false, false);
1413 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1414 return LWResult::Result::Success
;
1417 return LWResult::Result::Timeout
;
1420 vector
<DNSRecord
> ret
;
1421 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1422 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1423 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1424 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1425 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1428 BOOST_AUTO_TEST_CASE(test_following_cname
)
1430 std::unique_ptr
<SyncRes
> sr
;
1435 const DNSName
target("cname.powerdns.com.");
1436 const DNSName
cnameTarget("cname-target.powerdns.com");
1438 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 */) {
1439 if (isRootServer(ip
)) {
1440 setLWResult(res
, 0, false, false, true);
1441 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1442 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1443 return LWResult::Result::Success
;
1445 else if (ip
== ComboAddress("192.0.2.1:53")) {
1447 if (domain
== target
) {
1448 setLWResult(res
, 0, true, false, false);
1449 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1450 return LWResult::Result::Success
;
1452 else if (domain
== cnameTarget
) {
1453 setLWResult(res
, 0, true, false, false);
1454 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1457 return LWResult::Result::Success
;
1460 return LWResult::Result::Timeout
;
1463 vector
<DNSRecord
> ret
;
1464 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1465 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1466 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1467 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1468 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1469 BOOST_CHECK(ret
[1].d_type
== QType::A
);
1470 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1473 BOOST_AUTO_TEST_CASE(test_cname_nxdomain
)
1475 std::unique_ptr
<SyncRes
> sr
;
1480 const DNSName
target("cname.powerdns.com.");
1481 const DNSName
cnameTarget("cname-target.powerdns.com");
1483 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 */) {
1484 if (isRootServer(ip
)) {
1485 setLWResult(res
, 0, false, false, true);
1486 addRecordToLW(res
, "powerdns.com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1487 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1488 return LWResult::Result::Success
;
1490 else if (ip
== ComboAddress("192.0.2.1:53")) {
1492 if (domain
== target
) {
1493 setLWResult(res
, RCode::NXDomain
, true, false, false);
1494 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1495 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1497 else if (domain
== cnameTarget
) {
1498 setLWResult(res
, RCode::NXDomain
, true, false, false);
1499 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1500 return LWResult::Result::Success
;
1503 return LWResult::Result::Success
;
1506 return LWResult::Result::Timeout
;
1509 vector
<DNSRecord
> ret
;
1510 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1511 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1512 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1513 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1514 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1515 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1517 /* a second time, to check the cache */
1519 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1520 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1521 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1522 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1523 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1524 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1527 BOOST_AUTO_TEST_CASE(test_included_poisonous_cname
)
1529 std::unique_ptr
<SyncRes
> sr
;
1534 /* In this test we directly get the NS server for cname.powerdns.com.,
1535 and we don't know whether it's also authoritative for
1536 cname-target.powerdns.com or powerdns.com, so we shouldn't accept
1537 the additional A record for cname-target.powerdns.com. */
1538 const DNSName
target("cname.powerdns.com.");
1539 const DNSName
cnameTarget("cname-target.powerdns.com");
1541 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 */) {
1542 if (isRootServer(ip
)) {
1544 setLWResult(res
, 0, false, false, true);
1546 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1547 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1548 return LWResult::Result::Success
;
1550 else if (ip
== ComboAddress("192.0.2.1:53")) {
1552 if (domain
== target
) {
1553 setLWResult(res
, 0, true, false, false);
1554 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1555 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
);
1556 return LWResult::Result::Success
;
1558 else if (domain
== cnameTarget
) {
1559 setLWResult(res
, 0, true, false, false);
1560 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.3");
1561 return LWResult::Result::Success
;
1564 return LWResult::Result::Success
;
1567 return LWResult::Result::Timeout
;
1570 vector
<DNSRecord
> ret
;
1571 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1572 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1573 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1574 BOOST_REQUIRE(ret
[0].d_type
== QType::CNAME
);
1575 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1576 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget(), cnameTarget
);
1577 BOOST_REQUIRE(ret
[1].d_type
== QType::A
);
1578 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1579 BOOST_CHECK(getRR
<ARecordContent
>(ret
[1])->getCA() == ComboAddress("192.0.2.3"));
1582 BOOST_AUTO_TEST_CASE(test_cname_loop
)
1584 std::unique_ptr
<SyncRes
> sr
;
1590 const DNSName
target("cname.powerdns.com.");
1592 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 */) {
1595 if (isRootServer(ip
)) {
1597 setLWResult(res
, 0, false, false, true);
1598 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1599 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1600 return LWResult::Result::Success
;
1602 else if (ip
== ComboAddress("192.0.2.1:53")) {
1604 if (domain
== target
) {
1605 setLWResult(res
, 0, true, false, false);
1606 addRecordToLW(res
, domain
, QType::CNAME
, domain
.toString());
1607 return LWResult::Result::Success
;
1610 return LWResult::Result::Success
;
1613 return LWResult::Result::Timeout
;
1616 vector
<DNSRecord
> ret
;
1617 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1618 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1619 BOOST_CHECK_EQUAL(ret
.size(), 0U);
1620 BOOST_CHECK_EQUAL(count
, 2U);
1622 // Again to check cache
1624 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1627 catch (const ImmediateServFailException
& ex
) {
1632 BOOST_AUTO_TEST_CASE(test_cname_long_loop
)
1634 std::unique_ptr
<SyncRes
> sr
;
1640 const DNSName
target1("cname1.powerdns.com.");
1641 const DNSName
target2("cname2.powerdns.com.");
1642 const DNSName
target3("cname3.powerdns.com.");
1643 const DNSName
target4("cname4.powerdns.com.");
1645 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 */) {
1648 if (isRootServer(ip
)) {
1650 setLWResult(res
, 0, false, false, true);
1651 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1652 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1653 return LWResult::Result::Success
;
1655 else if (ip
== ComboAddress("192.0.2.1:53")) {
1657 if (domain
== target1
) {
1658 setLWResult(res
, 0, true, false, false);
1659 addRecordToLW(res
, domain
, QType::CNAME
, target2
.toString());
1660 return LWResult::Result::Success
;
1662 else if (domain
== target2
) {
1663 setLWResult(res
, 0, true, false, false);
1664 addRecordToLW(res
, domain
, QType::CNAME
, target3
.toString());
1665 return LWResult::Result::Success
;
1667 else if (domain
== target3
) {
1668 setLWResult(res
, 0, true, false, false);
1669 addRecordToLW(res
, domain
, QType::CNAME
, target4
.toString());
1670 return LWResult::Result::Success
;
1672 else if (domain
== target4
) {
1673 setLWResult(res
, 0, true, false, false);
1674 addRecordToLW(res
, domain
, QType::CNAME
, target1
.toString());
1675 return LWResult::Result::Success
;
1678 return LWResult::Result::Success
;
1681 return LWResult::Result::Timeout
;
1684 vector
<DNSRecord
> ret
;
1685 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1686 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1687 BOOST_CHECK_EQUAL(ret
.size(), 0U);
1688 BOOST_CHECK_EQUAL(count
, 8U);
1690 // And again to check cache
1692 sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1695 catch (const ImmediateServFailException
& ex
) {
1700 BOOST_AUTO_TEST_CASE(test_cname_length
)
1702 std::unique_ptr
<SyncRes
> sr
;
1708 const DNSName
target("cname.powerdns.com.");
1710 sr
->setAsyncCallback([target
, &length
](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 */) {
1711 if (isRootServer(ip
)) {
1713 setLWResult(res
, 0, false, false, true);
1714 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1715 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1716 return LWResult::Result::Success
;
1718 else if (ip
== ComboAddress("192.0.2.1:53")) {
1720 setLWResult(res
, 0, true, false, false);
1721 addRecordToLW(res
, domain
, QType::CNAME
, std::to_string(length
) + "-cname.powerdns.com");
1723 return LWResult::Result::Success
;
1726 return LWResult::Result::Timeout
;
1729 vector
<DNSRecord
> ret
;
1730 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1731 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1732 BOOST_CHECK_EQUAL(ret
.size(), length
);
1733 BOOST_CHECK_EQUAL(length
, SyncRes::s_max_CNAMES_followed
+ 1);
1736 BOOST_AUTO_TEST_CASE(test_time_limit
)
1738 std::unique_ptr
<SyncRes
> sr
;
1744 const DNSName
target("cname.powerdns.com.");
1746 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 */) {
1749 if (isRootServer(ip
)) {
1750 setLWResult(res
, 0, false, false, true);
1751 /* Pretend that this query took 2000 ms */
1754 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1755 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1756 return LWResult::Result::Success
;
1758 else if (ip
== ComboAddress("192.0.2.1:53")) {
1760 setLWResult(res
, 0, true, false, false);
1761 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1762 return LWResult::Result::Success
;
1765 return LWResult::Result::Timeout
;
1768 /* Set the maximum time to 1 ms */
1769 SyncRes::s_maxtotusec
= 1000;
1772 vector
<DNSRecord
> ret
;
1773 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1776 catch (const ImmediateServFailException
& e
) {
1778 BOOST_CHECK_EQUAL(queries
, 1U);
1781 BOOST_AUTO_TEST_CASE(test_dname_processing
)
1783 std::unique_ptr
<SyncRes
> sr
;
1788 const DNSName
dnameOwner("powerdns.com");
1789 const DNSName
dnameTarget("powerdns.net");
1791 const DNSName
target("dname.powerdns.com.");
1792 const DNSName
cnameTarget("dname.powerdns.net");
1794 const DNSName
uncachedTarget("dname-uncached.powerdns.com.");
1795 const DNSName
uncachedCNAMETarget("dname-uncached.powerdns.net.");
1797 const DNSName
synthCNAME("cname-uncached.powerdns.com.");
1798 const DNSName
synthCNAMETarget("cname-uncached.powerdns.net.");
1802 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 */) {
1805 if (isRootServer(ip
)) {
1806 if (domain
.isPartOf(dnameOwner
)) {
1807 setLWResult(res
, 0, false, false, true);
1808 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1809 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1810 return LWResult::Result::Success
;
1812 if (domain
.isPartOf(dnameTarget
)) {
1813 setLWResult(res
, 0, false, false, true);
1814 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1815 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1816 return LWResult::Result::Success
;
1819 else if (ip
== ComboAddress("192.0.2.1:53")) {
1820 if (domain
== target
) {
1821 setLWResult(res
, 0, true, false, false);
1822 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
1823 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1824 return LWResult::Result::Success
;
1827 else if (ip
== ComboAddress("192.0.2.2:53")) {
1828 if (domain
== cnameTarget
) {
1829 setLWResult(res
, 0, true, false, false);
1830 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1832 if (domain
== uncachedCNAMETarget
) {
1833 setLWResult(res
, 0, true, false, false);
1834 addRecordToLW(res
, domain
, QType::A
, "192.0.2.3");
1836 return LWResult::Result::Success
;
1838 return LWResult::Result::Timeout
;
1841 vector
<DNSRecord
> ret
;
1842 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1844 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1845 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
1847 BOOST_CHECK_EQUAL(queries
, 4u);
1849 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1850 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1851 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1853 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
1854 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
1856 BOOST_CHECK(ret
[2].d_type
== QType::A
);
1857 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
1859 // Now check the cache
1861 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1863 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1864 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
1866 BOOST_CHECK_EQUAL(queries
, 4U);
1868 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1869 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1870 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1872 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
1873 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
1875 BOOST_CHECK(ret
[2].d_type
== QType::A
);
1876 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
1878 // Check if we correctly return a synthesized CNAME, should send out just 1 more query
1880 res
= sr
->beginResolve(uncachedTarget
, QType(QType::A
), QClass::IN
, ret
);
1882 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1883 BOOST_CHECK_EQUAL(queries
, 5U);
1885 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1886 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1887 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1889 BOOST_REQUIRE(ret
[1].d_type
== QType::CNAME
);
1890 BOOST_CHECK_EQUAL(ret
[1].d_name
, uncachedTarget
);
1891 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[1])->getTarget(), uncachedCNAMETarget
);
1893 BOOST_CHECK(ret
[2].d_type
== QType::A
);
1894 BOOST_CHECK_EQUAL(ret
[2].d_name
, uncachedCNAMETarget
);
1896 // Check if we correctly return the DNAME from cache when asked
1898 res
= sr
->beginResolve(dnameOwner
, QType(QType::DNAME
), QClass::IN
, ret
);
1899 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1900 BOOST_CHECK_EQUAL(queries
, 5U);
1902 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1903 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1904 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1906 // Check if we correctly return the synthesized CNAME from cache when asked
1908 res
= sr
->beginResolve(synthCNAME
, QType(QType::CNAME
), QClass::IN
, ret
);
1909 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1910 BOOST_CHECK_EQUAL(queries
, 5U);
1912 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1913 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1914 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1916 BOOST_REQUIRE(ret
[1].d_type
== QType::CNAME
);
1917 BOOST_CHECK(ret
[1].d_name
== synthCNAME
);
1918 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[1])->getTarget(), synthCNAMETarget
);
1921 BOOST_AUTO_TEST_CASE(test_dname_dnssec_secure
)
1923 std::unique_ptr
<SyncRes
> sr
;
1925 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
1929 const DNSName
dnameOwner("powerdns");
1930 const DNSName
dnameTarget("example");
1932 const DNSName
target("dname.powerdns");
1933 const DNSName
cnameTarget("dname.example");
1937 auto luaconfsCopy
= g_luaconfs
.getCopy();
1938 luaconfsCopy
.dsAnchors
.clear();
1939 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
1940 generateKeyMaterial(dnameOwner
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1941 generateKeyMaterial(dnameTarget
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
1942 g_luaconfs
.setState(luaconfsCopy
);
1946 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 */) {
1948 /* 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
1949 * As such, we need to do some more work to make the answers correct.
1952 if (isRootServer(ip
)) {
1953 if (domain
.countLabels() == 0 && type
== QType::DNSKEY
) { // .|DNSKEY
1954 setLWResult(res
, 0, true, false, true);
1955 addDNSKEY(keys
, domain
, 300, res
->d_records
);
1956 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
1957 return LWResult::Result::Success
;
1959 if (domain
.countLabels() == 1 && type
== QType::DS
) { // powerdns|DS or example|DS
1960 setLWResult(res
, 0, true, false, true);
1961 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
1962 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
1963 return LWResult::Result::Success
;
1965 // For the rest, delegate!
1966 if (domain
.isPartOf(dnameOwner
)) {
1967 setLWResult(res
, 0, false, false, true);
1968 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1969 addDS(dnameOwner
, 300, res
->d_records
, keys
);
1970 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
1971 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1972 return LWResult::Result::Success
;
1974 if (domain
.isPartOf(dnameTarget
)) {
1975 setLWResult(res
, 0, false, false, true);
1976 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1977 addDS(dnameTarget
, 300, res
->d_records
, keys
);
1978 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
1979 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1980 return LWResult::Result::Success
;
1983 else if (ip
== ComboAddress("192.0.2.1:53")) {
1984 if (domain
.countLabels() == 1 && type
== QType::DNSKEY
) { // powerdns|DNSKEY
1985 setLWResult(res
, 0, true, false, true);
1986 addDNSKEY(keys
, domain
, 300, res
->d_records
);
1987 addRRSIG(keys
, res
->d_records
, domain
, 300);
1988 return LWResult::Result::Success
;
1990 if (domain
== target
&& type
== QType::DS
) { // dname.powerdns|DS
1991 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
1993 if (domain
== target
) {
1994 setLWResult(res
, 0, true, false, false);
1995 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
1996 addRRSIG(keys
, res
->d_records
, dnameOwner
, 300);
1997 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString()); // CNAME from a DNAME is not signed
1998 return LWResult::Result::Success
;
2001 else if (ip
== ComboAddress("192.0.2.2:53")) {
2002 if (domain
.countLabels() == 1 && type
== QType::DNSKEY
) { // example|DNSKEY
2003 setLWResult(res
, 0, true, false, true);
2004 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2005 addRRSIG(keys
, res
->d_records
, domain
, 300);
2006 return LWResult::Result::Success
;
2008 if (domain
== cnameTarget
&& type
== QType::DS
) { // dname.example|DS
2009 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
2011 if (domain
== cnameTarget
) {
2012 setLWResult(res
, 0, true, false, false);
2013 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2014 addRRSIG(keys
, res
->d_records
, dnameTarget
, 300);
2016 return LWResult::Result::Success
;
2018 return LWResult::Result::Timeout
;
2021 vector
<DNSRecord
> ret
;
2022 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2024 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2025 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2026 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2028 BOOST_CHECK_EQUAL(queries
, 7U);
2030 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2031 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2032 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2034 BOOST_REQUIRE(ret
[1].d_type
== QType::RRSIG
);
2035 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2037 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2038 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2040 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2041 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2043 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2044 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2048 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2050 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2051 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2052 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2054 BOOST_CHECK_EQUAL(queries
, 7U);
2056 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2057 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2058 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2060 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2061 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2063 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2064 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2066 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2067 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2069 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2070 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2073 BOOST_AUTO_TEST_CASE(test_dname_plus_ns_dnssec_secure
)
2075 std::unique_ptr
<SyncRes
> sr
;
2077 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
2081 const DNSName
dnameOwner("powerdns");
2082 const DNSName
dnameTarget("example");
2084 const DNSName
target("dname.powerdns");
2085 const DNSName
cnameTarget("dname.example");
2089 auto luaconfsCopy
= g_luaconfs
.getCopy();
2090 luaconfsCopy
.dsAnchors
.clear();
2091 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2092 generateKeyMaterial(dnameTarget
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2093 g_luaconfs
.setState(luaconfsCopy
);
2097 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 */) {
2100 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
2101 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
2104 if (domain
.isPartOf(dnameOwner
)) {
2105 setLWResult(res
, 0, true, false, true);
2106 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2107 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2108 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString()); // CNAME from a DNAME is not signed
2110 addRecordToLW(res
, dnameTarget
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2111 addDS(dnameTarget
, 300, res
->d_records
, keys
);
2112 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2113 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2114 return LWResult::Result::Success
;
2116 else if (domain
== cnameTarget
) {
2117 setLWResult(res
, 0, true, false, true);
2118 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2119 addRRSIG(keys
, res
->d_records
, dnameTarget
, 300);
2120 return LWResult::Result::Success
;
2122 return LWResult::Result::Timeout
;
2125 vector
<DNSRecord
> ret
;
2126 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2128 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2129 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2130 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2132 BOOST_CHECK_EQUAL(queries
, 4U);
2134 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2135 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2136 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2138 BOOST_REQUIRE(ret
[1].d_type
== QType::RRSIG
);
2139 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2141 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2142 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2144 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2145 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2147 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2148 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2152 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2154 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2155 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2156 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2158 BOOST_CHECK_EQUAL(queries
, 4U);
2160 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2161 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2162 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2164 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2165 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2167 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2168 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2170 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2171 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2173 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2174 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2177 BOOST_AUTO_TEST_CASE(test_dname_dnssec_insecure
)
2180 * The DNAME itself is signed, but the final A record is not
2182 std::unique_ptr
<SyncRes
> sr
;
2184 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
2188 const DNSName
dnameOwner("powerdns");
2189 const DNSName
dnameTarget("example");
2191 const DNSName
target("dname.powerdns");
2192 const DNSName
cnameTarget("dname.example");
2196 auto luaconfsCopy
= g_luaconfs
.getCopy();
2197 luaconfsCopy
.dsAnchors
.clear();
2198 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2199 generateKeyMaterial(dnameOwner
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2200 g_luaconfs
.setState(luaconfsCopy
);
2204 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 */) {
2207 if (isRootServer(ip
)) {
2208 if (domain
.countLabels() == 0 && type
== QType::DNSKEY
) { // .|DNSKEY
2209 setLWResult(res
, 0, true, false, true);
2210 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2211 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2212 return LWResult::Result::Success
;
2214 if (domain
== dnameOwner
&& type
== QType::DS
) { // powerdns|DS
2215 setLWResult(res
, 0, true, false, true);
2216 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
2217 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2218 return LWResult::Result::Success
;
2220 if (domain
== dnameTarget
&& type
== QType::DS
) { // example|DS
2221 return genericDSAndDNSKEYHandler(res
, domain
, DNSName("."), type
, keys
);
2223 // For the rest, delegate!
2224 if (domain
.isPartOf(dnameOwner
)) {
2225 setLWResult(res
, 0, false, false, true);
2226 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2227 addDS(dnameOwner
, 300, res
->d_records
, keys
);
2228 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2229 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2230 return LWResult::Result::Success
;
2232 if (domain
.isPartOf(dnameTarget
)) {
2233 setLWResult(res
, 0, false, false, true);
2234 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2235 addDS(dnameTarget
, 300, res
->d_records
, keys
);
2236 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2237 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2238 return LWResult::Result::Success
;
2241 else if (ip
== ComboAddress("192.0.2.1:53")) {
2242 if (domain
.countLabels() == 1 && type
== QType::DNSKEY
) { // powerdns|DNSKEY
2243 setLWResult(res
, 0, true, false, true);
2244 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2245 addRRSIG(keys
, res
->d_records
, domain
, 300);
2246 return LWResult::Result::Success
;
2248 if (domain
== target
&& type
== QType::DS
) { // dname.powerdns|DS
2249 return genericDSAndDNSKEYHandler(res
, domain
, dnameOwner
, type
, keys
, false);
2251 if (domain
== target
) {
2252 setLWResult(res
, 0, true, false, false);
2253 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2254 addRRSIG(keys
, res
->d_records
, dnameOwner
, 300);
2255 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString()); // CNAME from a DNAME is not signed
2256 return LWResult::Result::Success
;
2259 else if (ip
== ComboAddress("192.0.2.2:53")) {
2260 if (domain
== target
&& type
== QType::DS
) { // dname.example|DS
2261 return genericDSAndDNSKEYHandler(res
, domain
, dnameTarget
, type
, keys
, false);
2263 if (domain
== cnameTarget
) {
2264 setLWResult(res
, 0, true, false, false);
2265 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2267 return LWResult::Result::Success
;
2269 return LWResult::Result::Timeout
;
2272 vector
<DNSRecord
> ret
;
2273 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2275 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2276 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
2277 BOOST_REQUIRE_EQUAL(ret
.size(), 4U); /* DNAME + RRSIG(DNAME) + CNAME + A */
2279 BOOST_CHECK_EQUAL(queries
, 7U);
2281 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2282 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2283 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2285 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2286 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2288 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2289 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2291 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2292 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2296 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2298 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2299 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
2300 BOOST_REQUIRE_EQUAL(ret
.size(), 4U); /* DNAME + RRSIG(DNAME) + CNAME + A */
2302 BOOST_CHECK_EQUAL(queries
, 7U);
2304 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2305 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2306 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2308 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2309 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2311 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2312 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2314 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2315 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2318 BOOST_AUTO_TEST_CASE(test_dname_processing_no_CNAME
)
2320 std::unique_ptr
<SyncRes
> sr
;
2325 const DNSName
dnameOwner("powerdns.com");
2326 const DNSName
dnameTarget("powerdns.net");
2328 const DNSName
target("dname.powerdns.com.");
2329 const DNSName
cnameTarget("dname.powerdns.net");
2333 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 */) {
2336 if (isRootServer(ip
)) {
2337 if (domain
.isPartOf(dnameOwner
)) {
2338 setLWResult(res
, 0, false, false, true);
2339 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2340 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2341 return LWResult::Result::Success
;
2343 if (domain
.isPartOf(dnameTarget
)) {
2344 setLWResult(res
, 0, false, false, true);
2345 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2346 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2347 return LWResult::Result::Success
;
2350 else if (ip
== ComboAddress("192.0.2.1:53")) {
2351 if (domain
== target
) {
2352 setLWResult(res
, 0, true, false, false);
2353 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2354 // No CNAME, recursor should synth
2355 return LWResult::Result::Success
;
2358 else if (ip
== ComboAddress("192.0.2.2:53")) {
2359 if (domain
== cnameTarget
) {
2360 setLWResult(res
, 0, true, false, false);
2361 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2363 return LWResult::Result::Success
;
2365 return LWResult::Result::Timeout
;
2368 vector
<DNSRecord
> ret
;
2369 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2371 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2372 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
2374 BOOST_CHECK_EQUAL(queries
, 4U);
2376 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2377 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2378 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2380 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
2381 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
2383 BOOST_CHECK(ret
[2].d_type
== QType::A
);
2384 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
2386 // Now check the cache
2388 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2390 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2391 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
2393 BOOST_CHECK_EQUAL(queries
, 4U);
2395 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2396 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2397 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2399 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
2400 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
2402 BOOST_CHECK(ret
[2].d_type
== QType::A
);
2403 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
2407 // cerr<<"asyncresolve called to ask "<<ip.toStringWithPort()<<" about "<<domain.toString()<<" / "<<QType(type).getName()<<" over "<<(doTCP ? "TCP" : "UDP")<<" (rd: "<<sendRDQuery<<", EDNS0 level: "<<EDNS0Level<<")"<<endl;
2409 - check out of band support
2415 BOOST_AUTO_TEST_CASE(test_glued_referral_child_ns_set_wrong
)
2417 std::unique_ptr
<SyncRes
> sr
;
2422 const DNSName
target("powerdns.com.");
2424 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 */) {
2425 /* this will cause issue with qname minimization if we ever implement it */
2426 if (domain
!= target
) {
2427 return LWResult::Result::Timeout
;
2430 if (isRootServer(ip
)) {
2431 setLWResult(res
, 0, false, false, true);
2432 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2433 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2434 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
2435 return LWResult::Result::Success
;
2437 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
2438 setLWResult(res
, 0, false, false, true);
2439 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
2440 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
2441 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
2442 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
2443 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
2444 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
2445 return LWResult::Result::Success
;
2447 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")) {
2449 if (type
== QType::A
) {
2450 setLWResult(res
, 0, true, false, true);
2451 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
2452 return LWResult::Result::Success
;
2454 else if (type
== QType::NS
) {
2455 setLWResult(res
, 0, true, false, true);
2456 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-nsX1.powerdns.com.", DNSResourceRecord::ANSWER
, 172800);
2457 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-nsX2.powerdns.com.", DNSResourceRecord::ANSWER
, 172800);
2458 addRecordToLW(res
, "pdns-public-nsX1.powerdns.com.", QType::A
, "192.0.2.11", DNSResourceRecord::ADDITIONAL
, 172800);
2459 addRecordToLW(res
, "pdns-public-nsX1.powerdns.com.", QType::AAAA
, "2001:DB8::11", DNSResourceRecord::ADDITIONAL
, 172800);
2460 addRecordToLW(res
, "pdns-public-nsX2.powerdns.com.", QType::A
, "192.0.2.12", DNSResourceRecord::ADDITIONAL
, 172800);
2461 addRecordToLW(res
, "pdns-public-nsX2.powerdns.com.", QType::AAAA
, "2001:DB8::12", DNSResourceRecord::ADDITIONAL
, 172800);
2462 return LWResult::Result::Success
;
2465 return LWResult::Result::Timeout
;
2469 return LWResult::Result::Timeout
;
2473 vector
<DNSRecord
> ret
;
2474 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2475 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2476 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
2477 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2478 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
2480 // Now resolve NS to get auth NS set in cache and save the parent NS set
2482 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
2483 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2484 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
2485 BOOST_CHECK(ret
[0].d_type
== QType::NS
);
2486 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
2487 BOOST_CHECK_EQUAL(SyncRes::getSaveParentsNSSetsSize(), 1U);
2489 g_recCache
->doWipeCache(target
, false, QType::A
);
2490 SyncRes::s_save_parent_ns_set
= false;
2492 // Try to resolve now via the broken child NS set... should not work
2494 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2495 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
2496 BOOST_REQUIRE_EQUAL(ret
.size(), 0U);
2498 SyncRes::s_save_parent_ns_set
= true;
2500 // Try to resolve now via the broken child... should work now via fallback to parent NS set
2502 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2503 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2504 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
2505 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2506 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
2509 BOOST_AUTO_TEST_SUITE_END()