1 #ifndef BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_DYN_LINK
5 #include <boost/test/unit_test.hpp>
7 #include "test-syncres_cc.hh"
8 #include "taskqueue.hh"
9 #include "rec-taskqueue.hh"
11 BOOST_AUTO_TEST_SUITE(syncres_cc1
)
13 BOOST_AUTO_TEST_CASE(test_root_primed
)
15 std::unique_ptr
<SyncRes
> sr
;
20 const DNSName
target("a.root-servers.net.");
22 /* we are primed, but only with non-auth data so we cannot resolve A a.root-servers.net. without any query */
23 vector
<DNSRecord
> ret
;
24 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
25 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
26 BOOST_REQUIRE_EQUAL(ret
.size(), 0U);
29 res
= sr
->beginResolve(target
, QType(QType::AAAA
), QClass::IN
, ret
);
30 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
31 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Indeterminate
);
32 BOOST_REQUIRE_EQUAL(ret
.size(), 0U);
35 catch (const ImmediateServFailException
) {
40 BOOST_AUTO_TEST_CASE(test_root_primed_ns
)
42 std::unique_ptr
<SyncRes
> sr
;
46 const DNSName
target(".");
48 /* we are primed, but we should not be able to NS . without any query
49 because the . NS entry is not stored as authoritative */
51 size_t queriesCount
= 0;
53 sr
->setAsyncCallback([&](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
56 if (domain
== target
&& type
== QType::NS
) {
58 setLWResult(res
, 0, true, false, true);
59 char addr
[] = "a.root-servers.net.";
60 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
62 addRecordToLW(res
, g_rootdnsname
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
65 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
66 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
68 return LWResult::Result::Success
;
71 return LWResult::Result::Timeout
;
74 vector
<DNSRecord
> ret
;
75 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
76 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
77 BOOST_REQUIRE_EQUAL(ret
.size(), 13U);
78 BOOST_CHECK_EQUAL(queriesCount
, 1U);
81 BOOST_AUTO_TEST_CASE(test_root_not_primed
)
83 std::unique_ptr
<SyncRes
> sr
;
86 size_t queriesCount
= 0;
88 sr
->setAsyncCallback([&](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
91 if (domain
== g_rootdnsname
&& type
== QType::NS
) {
92 setLWResult(res
, 0, true, false, true);
93 addRecordToLW(res
, g_rootdnsname
, QType::NS
, "a.root-servers.net.", DNSResourceRecord::ANSWER
, 3600);
94 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
95 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
97 return LWResult::Result::Success
;
100 return LWResult::Result::Timeout
;
103 /* we are not primed yet, so SyncRes will have to call primeHints()
104 then call getRootNS(), for which at least one of the root servers needs to answer */
105 vector
<DNSRecord
> ret
;
106 int res
= sr
->beginResolve(DNSName("."), QType(QType::NS
), QClass::IN
, ret
);
107 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
108 BOOST_CHECK_EQUAL(ret
.size(), 1U);
109 BOOST_CHECK_EQUAL(queriesCount
, 2U);
112 BOOST_AUTO_TEST_CASE(test_root_not_primed_and_no_response
)
114 std::unique_ptr
<SyncRes
> sr
;
116 // We expect an error, do not log it
117 g_log
.toConsole(Logger::Critical
);
118 std::set
<ComboAddress
> downServers
;
120 /* we are not primed yet, so SyncRes will have to call primeHints()
121 then call getRootNS(), for which at least one of the root servers needs to answer.
122 None will, so it should ServFail.
124 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* /* res */, bool* /* chained */) {
125 downServers
.insert(address
);
126 return LWResult::Result::Timeout
;
129 vector
<DNSRecord
> ret
;
130 int res
= sr
->beginResolve(DNSName("."), QType(QType::NS
), QClass::IN
, ret
);
131 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
132 BOOST_CHECK_EQUAL(ret
.size(), 0U);
133 BOOST_CHECK(downServers
.size() > 0);
134 /* we explicitly refuse to mark the root servers down */
135 for (const auto& server
: downServers
) {
136 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 0U);
140 BOOST_AUTO_TEST_CASE(test_root_ns_poison_resistance
)
142 std::unique_ptr
<SyncRes
> sr
;
146 const DNSName
target("www.example.com.");
148 sr
->setAsyncCallback([&](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
149 if (domain
== g_rootdnsname
&& type
== QType::NS
) {
151 setLWResult(res
, 0, true, false, true);
152 char addr
[] = "a.root-servers.net.";
153 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
155 addRecordToLW(res
, g_rootdnsname
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
158 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
159 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
161 return LWResult::Result::Success
;
164 if (domain
== target
&& type
== QType::A
) {
166 setLWResult(res
, 0, true, false, true);
167 addRecordToLW(res
, target
, QType::A
, "1.2.3.4", DNSResourceRecord::ANSWER
, 3600);
169 addRecordToLW(res
, ".", QType::NS
, "poison.name.", DNSResourceRecord::AUTHORITY
, 3600);
170 addRecordToLW(res
, "poison.name", QType::A
, "4.5.6.7", DNSResourceRecord::ADDITIONAL
, 3600);
172 return LWResult::Result::Success
;
175 return LWResult::Result::Timeout
;
178 vector
<DNSRecord
> ret
;
179 // Check we have 13 root servers
180 int res
= sr
->beginResolve(g_rootdnsname
, QType(QType::NS
), QClass::IN
, ret
);
181 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
182 BOOST_REQUIRE_EQUAL(ret
.size(), 13U);
186 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
187 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
188 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
190 // Still should have 13
192 res
= sr
->beginResolve(g_rootdnsname
, QType(QType::NS
), QClass::IN
, ret
);
193 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
194 BOOST_REQUIRE_EQUAL(ret
.size(), 13U);
197 BOOST_AUTO_TEST_CASE(test_root_primed_ns_update
)
199 std::unique_ptr
<SyncRes
> sr
;
203 const DNSName
target(".");
204 const DNSName
aroot("a.root-servers.net.");
205 const string newA
= "1.2.3.4";
206 const string newAAAA
= "1::2";
208 /* we are primed, but we should not be able to NS . without any query
209 because the . NS entry is not stored as authoritative */
211 size_t queriesCount
= 0;
213 auto asynccb
= [&](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
216 if (domain
== target
&& type
== QType::NS
) {
218 setLWResult(res
, 0, true, false, true);
219 char addr
[] = "a.root-servers.net.";
220 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
222 addRecordToLW(res
, g_rootdnsname
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
225 addRecordToLW(res
, aroot
.toString(), QType::A
, newA
, DNSResourceRecord::ADDITIONAL
, 3600);
226 addRecordToLW(res
, aroot
.toString(), QType::AAAA
, newAAAA
, DNSResourceRecord::ADDITIONAL
, 3600);
228 return LWResult::Result::Success
;
230 return LWResult::Result::Timeout
;
233 sr
->setAsyncCallback(asynccb
);
236 Utility::gettimeofday(&now
, nullptr);
238 vector
<DNSRecord
> ret
;
239 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
240 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
241 BOOST_REQUIRE_EQUAL(ret
.size(), 13U);
242 BOOST_CHECK_EQUAL(queriesCount
, 1U);
245 time_t cached
= g_recCache
->get(now
.tv_sec
, aroot
, QType::A
, MemRecursorCache::None
, &ret
, ComboAddress());
246 BOOST_CHECK(cached
> 0);
247 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
248 BOOST_CHECK(getRR
<ARecordContent
>(ret
[0])->getCA() == ComboAddress(newA
));
251 cached
= g_recCache
->get(now
.tv_sec
, aroot
, QType::AAAA
, MemRecursorCache::None
, &ret
, ComboAddress());
252 BOOST_CHECK(cached
> 0);
253 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
254 BOOST_CHECK(getRR
<AAAARecordContent
>(ret
[0])->getCA() == ComboAddress(newAAAA
));
257 static void test_edns_formerr_fallback_f(bool sample
)
259 std::unique_ptr
<SyncRes
> sr
;
262 sr
->setQNameMinimization();
264 ComboAddress noEDNSServer
;
265 size_t queriesWithEDNS
= 0;
266 size_t queriesWithoutEDNS
= 0;
268 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int type
, bool doTCP
, bool /* sendRDQuery */, int EDNS0Level
, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
269 if (EDNS0Level
!= 0) {
271 noEDNSServer
= address
;
273 setLWResult(res
, RCode::FormErr
);
274 return LWResult::Result::Success
;
277 queriesWithoutEDNS
++;
279 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& !doTCP
) {
280 setLWResult(res
, 0, true, false, false);
281 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
282 return LWResult::Result::Success
;
285 return sample
? basicRecordsForQnameMinimization(res
, domain
, type
) : LWResult::Result::Timeout
;
290 /* fake that the root NS doesn't handle EDNS, check that we fallback */
291 vector
<DNSRecord
> ret
;
292 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
293 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
294 BOOST_CHECK_EQUAL(ret
.size(), 1U);
295 BOOST_CHECK_EQUAL(queriesWithEDNS
, sample
? 3U : 1U);
296 BOOST_CHECK_EQUAL(queriesWithoutEDNS
, sample
? 4U : 1U);
297 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), sample
? 3U : 1U);
298 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(noEDNSServer
), SyncRes::EDNSStatus::NOEDNS
);
301 BOOST_AUTO_TEST_CASE(test_edns_formerr_fallback
)
303 test_edns_formerr_fallback_f(false);
306 BOOST_AUTO_TEST_CASE(test_edns_formerr_fallback_qmin
)
308 // DISABLED UNTIL QNAME MINIMIZATION IS THERE
310 test_edns_formerr_fallback_f(true);
313 BOOST_AUTO_TEST_CASE(test_edns_formerr_but_edns_enabled
)
315 std::unique_ptr
<SyncRes
> sr
;
318 /* in this test, the auth answers with FormErr to an EDNS-enabled
319 query, but the response does contain EDNS so we should not mark
320 it as EDNS ignorant or intolerant.
322 size_t queriesWithEDNS
= 0;
323 size_t queriesWithoutEDNS
= 0;
324 std::set
<ComboAddress
> usedServers
;
326 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& /* domain */, int type
, bool /* doTCP */, bool /* sendRDQuery */, int EDNS0Level
, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
327 if (EDNS0Level
> 0) {
331 queriesWithoutEDNS
++;
333 usedServers
.insert(address
);
335 if (type
== QType::DNAME
) {
336 setLWResult(res
, RCode::FormErr
);
337 if (EDNS0Level
> 0) {
338 res
->d_haveEDNS
= true;
340 return LWResult::Result::Success
;
343 return LWResult::Result::Timeout
;
348 vector
<DNSRecord
> ret
;
349 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::DNAME
), QClass::IN
, ret
);
350 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
351 BOOST_CHECK_EQUAL(ret
.size(), 0U);
352 BOOST_CHECK_EQUAL(queriesWithEDNS
, 26U);
353 BOOST_CHECK_EQUAL(queriesWithoutEDNS
, 0U);
354 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), 0U);
355 BOOST_CHECK_EQUAL(usedServers
.size(), 26U);
356 for (const auto& server
: usedServers
) {
357 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
361 BOOST_AUTO_TEST_CASE(test_meta_types
)
363 std::unique_ptr
<SyncRes
> sr
;
366 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};
368 for (const auto qtype
: invalidTypes
) {
369 size_t queriesCount
= 0;
371 sr
->setAsyncCallback([&](const ComboAddress
& /* ip */, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* /* res */, bool* /* chained */) {
373 return LWResult::Result::Timeout
;
378 vector
<DNSRecord
> ret
;
379 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(qtype
), QClass::IN
, ret
);
380 BOOST_CHECK_EQUAL(res
, -1);
381 BOOST_CHECK_EQUAL(ret
.size(), 0U);
382 BOOST_CHECK_EQUAL(queriesCount
, 0U);
386 BOOST_AUTO_TEST_CASE(test_tc_fallback_to_tcp
)
388 std::unique_ptr
<SyncRes
> sr
;
391 sr
->setAsyncCallback([&](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool doTCP
, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
393 setLWResult(res
, 0, false, true, false);
394 return LWResult::Result::Success
;
396 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& doTCP
) {
397 setLWResult(res
, 0, true, false, false);
398 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
399 return LWResult::Result::Success
;
402 return LWResult::Result::Timeout
;
407 /* fake that the NS truncates every request over UDP, we should fallback to TCP */
408 vector
<DNSRecord
> ret
;
409 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
410 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
413 BOOST_AUTO_TEST_CASE(test_tc_over_tcp
)
415 std::unique_ptr
<SyncRes
> sr
;
418 size_t tcpQueriesCount
= 0;
420 sr
->setAsyncCallback([&](const ComboAddress
& /* ip */, const DNSName
& domain
, int /* type */, bool doTCP
, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
422 setLWResult(res
, 0, true, true, false);
423 return LWResult::Result::Success
;
426 /* first TCP query is answered with a TC response */
428 if (tcpQueriesCount
== 1) {
429 setLWResult(res
, 0, true, true, false);
432 setLWResult(res
, 0, true, false, false);
435 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
436 return LWResult::Result::Success
;
441 vector
<DNSRecord
> ret
;
442 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
443 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
444 BOOST_CHECK_EQUAL(tcpQueriesCount
, 2U);
447 BOOST_AUTO_TEST_CASE(test_all_nss_down
)
449 std::unique_ptr
<SyncRes
> sr
;
451 std::set
<ComboAddress
> downServers
;
455 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
456 if (isRootServer(address
)) {
457 setLWResult(res
, 0, false, false, true);
458 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
459 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
460 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
461 return LWResult::Result::Success
;
463 if (address
== ComboAddress("192.0.2.1:53") || address
== ComboAddress("[2001:DB8::1]:53")) {
464 setLWResult(res
, 0, false, false, true);
465 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
466 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
467 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
468 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
469 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
470 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
471 return LWResult::Result::Success
;
473 downServers
.insert(address
);
474 res
->d_usec
= g_networkTimeoutMsec
* 1000;
475 return LWResult::Result::Timeout
;
478 DNSName
target("powerdns.com.");
480 vector
<DNSRecord
> ret
;
481 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
482 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
483 BOOST_CHECK_EQUAL(ret
.size(), 0U);
484 BOOST_CHECK_EQUAL(downServers
.size(), 4U);
486 time_t now
= sr
->getNow().tv_sec
;
487 for (const auto& server
: downServers
) {
488 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1U);
489 BOOST_CHECK(SyncRes::isThrottled(now
, server
, target
, QType::A
));
493 BOOST_AUTO_TEST_CASE(test_all_nss_network_error
)
495 std::unique_ptr
<SyncRes
> sr
;
497 std::set
<ComboAddress
> downServers
;
501 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
502 if (isRootServer(address
)) {
503 setLWResult(res
, 0, false, false, true);
504 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
505 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
506 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
507 return LWResult::Result::Success
;
509 if (address
== ComboAddress("192.0.2.1:53") || address
== ComboAddress("[2001:DB8::1]:53")) {
510 setLWResult(res
, 0, false, false, true);
511 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
512 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
513 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
514 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
515 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
516 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
517 return LWResult::Result::Success
;
519 downServers
.insert(address
);
520 res
->d_usec
= g_networkTimeoutMsec
* 1000;
521 return LWResult::Result::Timeout
;
524 /* exact same test than the previous one, except instead of a time out we fake a network error */
525 DNSName
target("powerdns.com.");
527 vector
<DNSRecord
> ret
;
528 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
529 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
530 BOOST_CHECK_EQUAL(ret
.size(), 0U);
531 BOOST_CHECK_EQUAL(downServers
.size(), 4U);
533 time_t now
= sr
->getNow().tv_sec
;
534 for (const auto& server
: downServers
) {
535 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1U);
536 BOOST_CHECK(SyncRes::isThrottled(now
, server
, target
, QType::A
));
540 BOOST_AUTO_TEST_CASE(test_all_nss_send_tc_then_garbage_over_tcp
)
542 std::unique_ptr
<SyncRes
> sr
;
547 std::set
<ComboAddress
> downServers
;
549 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& /* domain */, int /* type */, bool doTCP
, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
550 if (isRootServer(address
)) {
551 setLWResult(res
, 0, false, false, true);
552 addRecordToLW(res
, "lock-up.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
553 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
554 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
555 return LWResult::Result::Success
;
559 setLWResult(res
, 0, false, true, false);
560 return LWResult::Result::Success
;
562 downServers
.insert(address
);
564 setLWResult(res
, RCode::FormErr
, false, false, false);
565 res
->d_validpacket
= false;
566 return LWResult::Result::Success
;
569 DNSName
target("www.lock-up.");
571 vector
<DNSRecord
> ret
;
572 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
573 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
574 BOOST_CHECK_EQUAL(ret
.size(), 0U);
575 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
577 for (const auto& server
: downServers
) {
578 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
579 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 1000000U);
583 BOOST_AUTO_TEST_CASE(test_all_nss_send_garbage_over_udp
)
585 std::unique_ptr
<SyncRes
> sr
;
590 std::set
<ComboAddress
> downServers
;
591 size_t queriesCount
= 0;
593 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
594 if (isRootServer(address
)) {
595 setLWResult(res
, 0, false, false, true);
596 addRecordToLW(res
, "lock-up.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
597 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
598 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
599 return LWResult::Result::Success
;
603 downServers
.insert(address
);
605 setLWResult(res
, RCode::FormErr
, false, false, false);
606 res
->d_validpacket
= false;
607 return LWResult::Result::Success
;
610 DNSName
target("www.lock-up.");
612 vector
<DNSRecord
> ret
;
613 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
614 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
615 BOOST_CHECK_EQUAL(ret
.size(), 0U);
616 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
617 /* two queries with EDNS, that's it */
618 BOOST_CHECK_EQUAL(queriesCount
, 2U);
620 for (const auto& server
: downServers
) {
621 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
622 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 1000000U);
623 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSIGNORANT
);
627 BOOST_AUTO_TEST_CASE(test_regular_ns_send_refused
)
629 std::unique_ptr
<SyncRes
> sr
;
634 std::set
<ComboAddress
> downServers
;
635 size_t queriesCount
= 0;
637 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
638 if (isRootServer(address
)) {
639 setLWResult(res
, 0, false, false, true);
640 addRecordToLW(res
, "refused.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
641 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
642 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
643 return LWResult::Result::Success
;
647 downServers
.insert(address
);
649 setLWResult(res
, RCode::Refused
, false, false, true);
651 return LWResult::Result::Success
;
654 DNSName
target("www.refused.");
656 vector
<DNSRecord
> ret
;
657 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
658 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
659 BOOST_CHECK_EQUAL(ret
.size(), 0U);
660 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
661 BOOST_CHECK_EQUAL(queriesCount
, 2U);
663 for (const auto& server
: downServers
) {
664 /* same as any other server */
665 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
666 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 0U);
667 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
671 BOOST_AUTO_TEST_CASE(test_forward_ns_send_refused
)
673 std::unique_ptr
<SyncRes
> sr
;
678 std::set
<ComboAddress
> downServers
;
679 size_t queriesCount
= 0;
681 const DNSName
target("www.refused.");
683 SyncRes::AuthDomain ad
;
684 const std::vector
<ComboAddress
> forwardedNSs
{ComboAddress("192.0.2.42:53"), ComboAddress("192.0.2.43:53")};
685 ad
.d_rdForward
= false;
686 ad
.d_servers
= forwardedNSs
;
687 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
689 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
690 if (isRootServer(address
)) {
691 setLWResult(res
, 0, false, false, true);
692 addRecordToLW(res
, "refused.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
693 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
694 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
695 return LWResult::Result::Success
;
699 downServers
.insert(address
);
701 setLWResult(res
, RCode::Refused
, false, false, true);
703 return LWResult::Result::Success
;
706 vector
<DNSRecord
> ret
;
707 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
708 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
709 BOOST_CHECK_EQUAL(ret
.size(), 0U);
710 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
711 BOOST_CHECK_EQUAL(queriesCount
, 2U);
713 for (const auto& server
: forwardedNSs
) {
714 BOOST_CHECK_EQUAL(downServers
.count(server
), 1U);
715 /* same as any other server */
716 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
717 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 0U);
718 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
722 BOOST_AUTO_TEST_CASE(test_forward_ns_send_servfail
)
724 std::unique_ptr
<SyncRes
> sr
;
729 std::set
<ComboAddress
> downServers
;
730 size_t queriesCount
= 0;
732 const DNSName
target("www.refused.");
734 SyncRes::AuthDomain ad
;
735 const std::vector
<ComboAddress
> forwardedNSs
{ComboAddress("192.0.2.42:53"), ComboAddress("192.0.2.43:53")};
736 ad
.d_rdForward
= false;
737 ad
.d_servers
= forwardedNSs
;
738 (*SyncRes::t_sstorage
.domainmap
)[DNSName("refused.")] = ad
;
740 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
741 if (isRootServer(address
)) {
742 setLWResult(res
, 0, false, false, true);
743 addRecordToLW(res
, "refused.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
744 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
745 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
746 return LWResult::Result::Success
;
750 downServers
.insert(address
);
752 setLWResult(res
, RCode::ServFail
, false, false, true);
754 return LWResult::Result::Success
;
757 vector
<DNSRecord
> ret
;
758 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
759 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
760 BOOST_CHECK_EQUAL(ret
.size(), 0U);
761 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
762 BOOST_CHECK_EQUAL(queriesCount
, 2U);
764 for (const auto& server
: forwardedNSs
) {
765 BOOST_CHECK_EQUAL(downServers
.count(server
), 1U);
766 /* on servfail from a server we forward to we only increase the NS speed so
767 that a different server might be tried instead, but we don't throttle */
768 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
769 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName(server
.toStringWithPort()), server
), 1000000U);
770 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
774 BOOST_AUTO_TEST_CASE(test_only_one_ns_up_resolving_itself_with_glue
)
776 std::unique_ptr
<SyncRes
> sr
;
781 DNSName
target("www.powerdns.com.");
783 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
784 if (isRootServer(address
)) {
785 setLWResult(res
, 0, false, false, true);
786 if (domain
== target
) {
787 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
788 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.net.", DNSResourceRecord::AUTHORITY
, 172800);
789 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
790 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
792 else if (domain
== DNSName("pdns-public-ns2.powerdns.net.")) {
793 addRecordToLW(res
, "powerdns.net.", QType::NS
, "pdns-public-ns2.powerdns.net.", DNSResourceRecord::AUTHORITY
, 172800);
794 addRecordToLW(res
, "powerdns.net.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
795 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
796 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
798 return LWResult::Result::Success
;
800 if (address
== ComboAddress("192.0.2.3:53")) {
801 setLWResult(res
, 0, true, false, true);
802 if (domain
== DNSName("pdns-public-ns2.powerdns.net.")) {
803 if (type
== QType::A
) {
804 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::A
, "192.0.2.3");
806 else if (type
== QType::AAAA
) {
807 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::AAAA
, "2001:DB8::3");
810 else if (domain
== target
) {
811 if (type
== QType::A
) {
812 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
814 else if (type
== QType::AAAA
) {
815 addRecordToLW(res
, domain
, QType::AAAA
, "2001:DB8::1");
818 return LWResult::Result::Success
;
820 return LWResult::Result::Timeout
;
823 vector
<DNSRecord
> ret
;
824 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
825 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
826 BOOST_CHECK_EQUAL(ret
.size(), 1U);
829 BOOST_AUTO_TEST_CASE(test_os_limit_errors
)
831 std::unique_ptr
<SyncRes
> sr
;
833 std::set
<ComboAddress
> downServers
;
837 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
838 if (isRootServer(address
)) {
839 setLWResult(res
, 0, false, false, true);
840 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
841 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
842 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
843 return LWResult::Result::Success
;
845 if (address
== ComboAddress("192.0.2.1:53") || address
== ComboAddress("[2001:DB8::1]:53")) {
846 setLWResult(res
, 0, false, false, true);
847 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
848 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
849 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
850 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
851 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
852 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
853 return LWResult::Result::Success
;
856 if (downServers
.size() < 3) {
857 /* only the last one will answer */
858 downServers
.insert(address
);
859 res
->d_usec
= g_networkTimeoutMsec
* 1000;
860 return LWResult::Result::OSLimitError
;
862 setLWResult(res
, 0, true, false, true);
863 addRecordToLW(res
, "powerdns.com.", QType::A
, "192.0.2.42");
864 return LWResult::Result::Success
;
868 DNSName
target("powerdns.com.");
870 vector
<DNSRecord
> ret
;
871 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
872 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
873 BOOST_CHECK_EQUAL(ret
.size(), 1U);
874 BOOST_CHECK_EQUAL(downServers
.size(), 3U);
876 /* Error is reported as "OS limit error" (-2) so the servers should _NOT_ be marked down */
877 time_t now
= sr
->getNow().tv_sec
;
878 for (const auto& server
: downServers
) {
879 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 0U);
880 BOOST_CHECK(!SyncRes::isThrottled(now
, server
, target
, QType::A
));
884 BOOST_AUTO_TEST_CASE(test_glued_referral
)
886 std::unique_ptr
<SyncRes
> sr
;
891 const DNSName
target("powerdns.com.");
893 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
894 /* this will cause issue with qname minimization if we ever implement it */
895 if (domain
!= target
) {
896 return LWResult::Result::Timeout
;
899 if (isRootServer(address
)) {
900 setLWResult(res
, 0, false, false, true);
901 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
902 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
903 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
904 return LWResult::Result::Success
;
906 if (address
== ComboAddress("192.0.2.1:53") || address
== ComboAddress("[2001:DB8::1]:53")) {
907 setLWResult(res
, 0, false, false, true);
908 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
909 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
910 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
911 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
912 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
913 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
914 return LWResult::Result::Success
;
916 if (address
== ComboAddress("192.0.2.2:53") || address
== ComboAddress("192.0.2.3:53") || address
== ComboAddress("[2001:DB8::2]:53") || address
== ComboAddress("[2001:DB8::3]:53")) {
917 setLWResult(res
, 0, true, false, true);
918 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
919 return LWResult::Result::Success
;
921 return LWResult::Result::Timeout
;
924 vector
<DNSRecord
> ret
;
925 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
926 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
927 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
928 BOOST_CHECK(ret
[0].d_type
== QType::A
);
929 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
932 BOOST_AUTO_TEST_CASE(test_glueless_referral
)
934 std::unique_ptr
<SyncRes
> sr
;
939 const DNSName
target("powerdns.com.");
941 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
942 if (isRootServer(address
)) {
943 setLWResult(res
, 0, false, false, true);
945 if (domain
.isPartOf(DNSName("com."))) {
946 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
948 else if (domain
.isPartOf(DNSName("org."))) {
949 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
952 setLWResult(res
, RCode::NXDomain
, false, false, true);
953 return LWResult::Result::Success
;
956 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
957 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
958 return LWResult::Result::Success
;
960 if (address
== ComboAddress("192.0.2.1:53") || address
== ComboAddress("[2001:DB8::1]:53")) {
961 if (domain
== target
) {
962 setLWResult(res
, 0, false, false, true);
963 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
964 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
965 return LWResult::Result::Success
;
967 if (domain
== DNSName("pdns-public-ns1.powerdns.org.")) {
968 setLWResult(res
, 0, true, false, true);
969 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2");
970 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::AAAA
, "2001:DB8::2");
971 return LWResult::Result::Success
;
973 if (domain
== DNSName("pdns-public-ns2.powerdns.org.")) {
974 setLWResult(res
, 0, true, false, true);
975 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::A
, "192.0.2.3");
976 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::AAAA
, "2001:DB8::3");
977 return LWResult::Result::Success
;
980 setLWResult(res
, RCode::NXDomain
, false, false, true);
981 return LWResult::Result::Success
;
983 if (address
== ComboAddress("192.0.2.2:53") || address
== ComboAddress("192.0.2.3:53") || address
== ComboAddress("[2001:DB8::2]:53") || address
== ComboAddress("[2001:DB8::3]:53")) {
984 setLWResult(res
, 0, true, false, true);
985 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
986 return LWResult::Result::Success
;
988 return LWResult::Result::Timeout
;
991 vector
<DNSRecord
> ret
;
992 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
993 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
994 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
995 BOOST_CHECK(ret
[0].d_type
== QType::A
);
996 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
999 BOOST_AUTO_TEST_CASE(test_endless_glueless_referral
)
1001 std::unique_ptr
<SyncRes
> sr
;
1006 const DNSName
target("powerdns.com.");
1009 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1010 if (isRootServer(address
)) {
1011 setLWResult(res
, 0, false, false, true);
1013 if (domain
.isPartOf(DNSName("com."))) {
1014 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1016 else if (domain
.isPartOf(DNSName("org."))) {
1017 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1020 setLWResult(res
, RCode::NXDomain
, false, false, true);
1021 return LWResult::Result::Success
;
1024 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1025 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1026 return LWResult::Result::Success
;
1028 if (domain
== target
) {
1029 setLWResult(res
, 0, false, false, true);
1030 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1031 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1032 return LWResult::Result::Success
;
1034 setLWResult(res
, 0, false, false, true);
1035 addRecordToLW(res
, domain
, QType::NS
, std::to_string(count
) + ".ns1.powerdns.org", DNSResourceRecord::AUTHORITY
, 172800);
1036 addRecordToLW(res
, domain
, QType::NS
, std::to_string(count
) + ".ns2.powerdns.org", DNSResourceRecord::AUTHORITY
, 172800);
1038 return LWResult::Result::Success
;
1041 vector
<DNSRecord
> ret
;
1042 BOOST_CHECK_EXCEPTION(sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
),
1043 ImmediateServFailException
,
1044 [&](const ImmediateServFailException
& isfe
) {
1045 return isfe
.reason
.substr(0, 9) == "More than";
1049 BOOST_AUTO_TEST_CASE(test_glueless_referral_aaaa_task
)
1051 std::unique_ptr
<SyncRes
> sr
;
1056 const DNSName
target("powerdns.com.");
1058 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1059 if (isRootServer(address
)) {
1060 setLWResult(res
, 0, false, false, true);
1062 if (domain
.isPartOf(DNSName("com."))) {
1063 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1065 else if (domain
.isPartOf(DNSName("org."))) {
1066 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1069 setLWResult(res
, RCode::NXDomain
, false, false, true);
1070 return LWResult::Result::Success
;
1073 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1074 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1075 return LWResult::Result::Success
;
1077 if (address
== ComboAddress("192.0.2.1:53") || address
== ComboAddress("[2001:DB8::1]:53")) {
1078 if (domain
== target
) {
1079 setLWResult(res
, 0, false, false, true);
1080 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1081 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1082 return LWResult::Result::Success
;
1084 if (domain
== DNSName("pdns-public-ns1.powerdns.org.")) {
1085 setLWResult(res
, 0, true, false, true);
1086 if (type
== QType::A
) {
1087 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2");
1090 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::AAAA
, "2001:DB8::2");
1092 return LWResult::Result::Success
;
1094 if (domain
== DNSName("pdns-public-ns2.powerdns.org.")) {
1095 setLWResult(res
, 0, true, false, true);
1096 if (type
== QType::A
) {
1097 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::A
, "192.0.2.3");
1100 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::AAAA
, "2001:DB8::3");
1102 return LWResult::Result::Success
;
1105 setLWResult(res
, RCode::NXDomain
, false, false, true);
1106 return LWResult::Result::Success
;
1108 if (address
== ComboAddress("192.0.2.2:53") || address
== ComboAddress("192.0.2.3:53") || address
== ComboAddress("[2001:DB8::2]:53") || address
== ComboAddress("[2001:DB8::3]:53")) {
1109 setLWResult(res
, 0, true, false, true);
1110 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
1111 return LWResult::Result::Success
;
1113 return LWResult::Result::Timeout
;
1116 vector
<DNSRecord
> ret
;
1117 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1118 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1119 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1120 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1121 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1123 // One task should be submitted
1124 BOOST_REQUIRE_EQUAL(getTaskSize(), 1U);
1125 auto task
= taskQueuePop();
1126 BOOST_CHECK(task
.d_qname
== DNSName("pdns-public-ns1.powerdns.org") || task
.d_qname
== DNSName("pdns-public-ns2.powerdns.org"));
1127 BOOST_CHECK_EQUAL(task
.d_qtype
, QType::AAAA
);
1130 BOOST_AUTO_TEST_CASE(test_edns_subnet_by_domain
)
1132 std::unique_ptr
<SyncRes
> sr
;
1137 const DNSName
target("powerdns.com.");
1138 SyncRes::addEDNSDomain(target
);
1140 EDNSSubnetOpts incomingECS
;
1141 incomingECS
.source
= Netmask("192.0.2.128/32");
1142 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1144 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& srcmask
, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1145 BOOST_REQUIRE(srcmask
);
1146 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1148 if (isRootServer(address
)) {
1149 setLWResult(res
, 0, false, false, true);
1150 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1151 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1153 /* this one did not use the ECS info */
1154 srcmask
= boost::none
;
1156 return LWResult::Result::Success
;
1158 if (address
== ComboAddress("192.0.2.1:53")) {
1160 setLWResult(res
, 0, true, false, false);
1161 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1163 /* this one did, but only up to a precision of /16, not the full /24 */
1164 srcmask
= Netmask("192.0.0.0/16");
1166 return LWResult::Result::Success
;
1169 return LWResult::Result::Timeout
;
1172 SyncRes::s_ecsqueries
= 0;
1173 SyncRes::s_ecsresponses
= 0;
1174 vector
<DNSRecord
> ret
;
1175 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1176 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1177 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1178 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1179 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1180 BOOST_CHECK_EQUAL(SyncRes::s_ecsqueries
, 2U);
1181 BOOST_CHECK_EQUAL(SyncRes::s_ecsresponses
, 1U);
1182 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize4
) {
1183 BOOST_CHECK_EQUAL(entry
.second
, entry
.first
== 15 ? 1U : 0U);
1185 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize6
) {
1186 BOOST_CHECK_EQUAL(entry
.second
, 0U);
1190 BOOST_AUTO_TEST_CASE(test_edns_subnet_by_addr
)
1192 std::unique_ptr
<SyncRes
> sr
;
1197 const DNSName
target("powerdns.com.");
1198 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1200 EDNSSubnetOpts incomingECS
;
1201 incomingECS
.source
= Netmask("2001:DB8::FF/128");
1202 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1204 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& srcmask
, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1205 if (isRootServer(address
)) {
1206 BOOST_REQUIRE(!srcmask
);
1208 setLWResult(res
, 0, false, false, true);
1209 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1210 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1211 return LWResult::Result::Success
;
1213 if (address
== ComboAddress("192.0.2.1:53")) {
1215 BOOST_REQUIRE(srcmask
);
1216 BOOST_CHECK_EQUAL(srcmask
->toString(), "2001:db8::/56");
1218 setLWResult(res
, 0, true, false, false);
1219 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1220 return LWResult::Result::Success
;
1223 return LWResult::Result::Timeout
;
1226 SyncRes::s_ecsqueries
= 0;
1227 SyncRes::s_ecsresponses
= 0;
1228 vector
<DNSRecord
> ret
;
1229 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1230 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1231 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1232 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1233 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1234 BOOST_CHECK_EQUAL(SyncRes::s_ecsqueries
, 1U);
1235 BOOST_CHECK_EQUAL(SyncRes::s_ecsresponses
, 1U);
1236 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize4
) {
1237 BOOST_CHECK_EQUAL(entry
.second
, 0u);
1239 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize6
) {
1240 BOOST_CHECK_EQUAL(entry
.second
, entry
.first
== 55 ? 1U : 0U);
1244 BOOST_AUTO_TEST_CASE(test_ecs_use_requestor
)
1246 std::unique_ptr
<SyncRes
> sr
;
1251 const DNSName
target("powerdns.com.");
1252 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1253 // No incoming ECS data
1254 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::none
);
1256 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& srcmask
, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1257 if (isRootServer(address
)) {
1258 BOOST_REQUIRE(!srcmask
);
1260 setLWResult(res
, 0, false, false, true);
1261 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1262 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1263 return LWResult::Result::Success
;
1265 if (address
== ComboAddress("192.0.2.1:53")) {
1267 BOOST_REQUIRE(srcmask
);
1268 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1270 setLWResult(res
, 0, true, false, false);
1271 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1272 return LWResult::Result::Success
;
1275 return LWResult::Result::Timeout
;
1278 vector
<DNSRecord
> ret
;
1279 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1280 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1281 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1282 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1283 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1286 BOOST_AUTO_TEST_CASE(test_ecs_use_scope_zero
)
1288 std::unique_ptr
<SyncRes
> sr
;
1293 const DNSName
target("powerdns.com.");
1294 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1295 SyncRes::clearEDNSLocalSubnets();
1296 SyncRes::addEDNSLocalSubnet("192.0.2.254/32");
1297 // No incoming ECS data, Requestor IP not in ecs-add-for
1298 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::none
);
1300 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& srcmask
, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1301 if (isRootServer(address
)) {
1302 BOOST_REQUIRE(!srcmask
);
1304 setLWResult(res
, 0, false, false, true);
1305 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1306 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1307 return LWResult::Result::Success
;
1309 if (address
== ComboAddress("192.0.2.1:53")) {
1311 BOOST_REQUIRE(srcmask
);
1312 BOOST_CHECK_EQUAL(srcmask
->toString(), "127.0.0.1/32");
1314 setLWResult(res
, 0, true, false, false);
1315 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1316 return LWResult::Result::Success
;
1319 return LWResult::Result::Timeout
;
1322 vector
<DNSRecord
> ret
;
1323 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1324 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1325 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1326 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1327 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1330 BOOST_AUTO_TEST_CASE(test_ecs_honor_incoming_mask
)
1332 std::unique_ptr
<SyncRes
> sr
;
1337 const DNSName
target("powerdns.com.");
1338 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1339 SyncRes::clearEDNSLocalSubnets();
1340 SyncRes::addEDNSLocalSubnet("192.0.2.254/32");
1341 EDNSSubnetOpts incomingECS
;
1342 incomingECS
.source
= Netmask("192.0.0.0/16");
1343 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1345 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& srcmask
, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1346 if (isRootServer(address
)) {
1347 BOOST_REQUIRE(!srcmask
);
1349 setLWResult(res
, 0, false, false, true);
1350 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1351 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1352 return LWResult::Result::Success
;
1354 if (address
== ComboAddress("192.0.2.1:53")) {
1356 BOOST_REQUIRE(srcmask
);
1357 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.0.0/16");
1359 setLWResult(res
, 0, true, false, false);
1360 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1361 return LWResult::Result::Success
;
1364 return LWResult::Result::Timeout
;
1367 vector
<DNSRecord
> ret
;
1368 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1369 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1370 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1371 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1372 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1375 BOOST_AUTO_TEST_CASE(test_ecs_honor_incoming_mask_zero
)
1377 std::unique_ptr
<SyncRes
> sr
;
1382 const DNSName
target("powerdns.com.");
1383 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1384 SyncRes::clearEDNSLocalSubnets();
1385 SyncRes::addEDNSLocalSubnet("192.0.2.254/32");
1386 EDNSSubnetOpts incomingECS
;
1387 incomingECS
.source
= Netmask("0.0.0.0/0");
1388 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1390 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& srcmask
, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1391 if (isRootServer(address
)) {
1392 BOOST_REQUIRE(!srcmask
);
1394 setLWResult(res
, 0, false, false, true);
1395 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1396 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1397 return LWResult::Result::Success
;
1399 if (address
== ComboAddress("192.0.2.1:53")) {
1401 BOOST_REQUIRE(srcmask
);
1402 BOOST_CHECK_EQUAL(srcmask
->toString(), "127.0.0.1/32");
1404 setLWResult(res
, 0, true, false, false);
1405 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1406 return LWResult::Result::Success
;
1409 return LWResult::Result::Timeout
;
1412 vector
<DNSRecord
> ret
;
1413 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1414 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1415 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1416 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1417 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1420 BOOST_AUTO_TEST_CASE(test_following_cname
)
1422 std::unique_ptr
<SyncRes
> sr
;
1427 const DNSName
target("cname.powerdns.com.");
1428 const DNSName
cnameTarget("cname-target.powerdns.com");
1430 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1431 if (isRootServer(address
)) {
1432 setLWResult(res
, 0, false, false, true);
1433 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1434 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1435 return LWResult::Result::Success
;
1437 if (address
== ComboAddress("192.0.2.1:53")) {
1439 if (domain
== target
) {
1440 setLWResult(res
, 0, true, false, false);
1441 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1442 return LWResult::Result::Success
;
1444 if (domain
== cnameTarget
) {
1445 setLWResult(res
, 0, true, false, false);
1446 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1449 return LWResult::Result::Success
;
1452 return LWResult::Result::Timeout
;
1455 vector
<DNSRecord
> ret
;
1456 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1457 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1458 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1459 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1460 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1461 BOOST_CHECK(ret
[1].d_type
== QType::A
);
1462 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1465 BOOST_AUTO_TEST_CASE(test_cname_nxdomain
)
1467 std::unique_ptr
<SyncRes
> sr
;
1472 const DNSName
target("cname.powerdns.com.");
1473 const DNSName
cnameTarget("cname-target.powerdns.com");
1475 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1476 if (isRootServer(address
)) {
1477 setLWResult(res
, 0, false, false, true);
1478 addRecordToLW(res
, "powerdns.com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1479 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1480 return LWResult::Result::Success
;
1482 if (address
== ComboAddress("192.0.2.1:53")) {
1484 if (domain
== target
) {
1485 setLWResult(res
, RCode::NXDomain
, true, false, false);
1486 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1487 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1489 else if (domain
== cnameTarget
) {
1490 setLWResult(res
, RCode::NXDomain
, true, false, false);
1491 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1492 return LWResult::Result::Success
;
1495 return LWResult::Result::Success
;
1498 return LWResult::Result::Timeout
;
1501 vector
<DNSRecord
> ret
;
1502 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1503 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1504 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1505 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1506 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1507 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1509 /* a second time, to check the cache */
1511 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1512 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1513 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1514 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1515 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1516 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1519 BOOST_AUTO_TEST_CASE(test_included_poisonous_cname
)
1521 std::unique_ptr
<SyncRes
> sr
;
1526 /* In this test we directly get the NS server for cname.powerdns.com.,
1527 and we don't know whether it's also authoritative for
1528 cname-target.powerdns.com or powerdns.com, so we shouldn't accept
1529 the additional A record for cname-target.powerdns.com. */
1530 const DNSName
target("cname.powerdns.com.");
1531 const DNSName
cnameTarget("cname-target.powerdns.com");
1533 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1534 if (isRootServer(address
)) {
1536 setLWResult(res
, 0, false, false, true);
1538 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1539 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1540 return LWResult::Result::Success
;
1542 if (address
== ComboAddress("192.0.2.1:53")) {
1544 if (domain
== target
) {
1545 setLWResult(res
, 0, true, false, false);
1546 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1547 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
);
1548 return LWResult::Result::Success
;
1550 if (domain
== cnameTarget
) {
1551 setLWResult(res
, 0, true, false, false);
1552 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.3");
1553 return LWResult::Result::Success
;
1556 return LWResult::Result::Success
;
1559 return LWResult::Result::Timeout
;
1562 vector
<DNSRecord
> ret
;
1563 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1564 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1565 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1566 BOOST_REQUIRE(ret
[0].d_type
== QType::CNAME
);
1567 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1568 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget(), cnameTarget
);
1569 BOOST_REQUIRE(ret
[1].d_type
== QType::A
);
1570 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1571 BOOST_CHECK(getRR
<ARecordContent
>(ret
[1])->getCA() == ComboAddress("192.0.2.3"));
1574 BOOST_AUTO_TEST_CASE(test_cname_loop
)
1576 std::unique_ptr
<SyncRes
> sr
;
1582 const DNSName
target("cname.powerdns.com.");
1584 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1587 if (isRootServer(address
)) {
1589 setLWResult(res
, 0, false, false, true);
1590 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1591 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1592 return LWResult::Result::Success
;
1594 if (address
== ComboAddress("192.0.2.1:53")) {
1596 if (domain
== target
) {
1597 setLWResult(res
, 0, true, false, false);
1598 addRecordToLW(res
, domain
, QType::CNAME
, domain
.toString());
1599 return LWResult::Result::Success
;
1602 return LWResult::Result::Success
;
1605 return LWResult::Result::Timeout
;
1608 vector
<DNSRecord
> ret
;
1609 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1610 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1611 BOOST_CHECK_EQUAL(ret
.size(), 0U);
1612 BOOST_CHECK_EQUAL(count
, 2U);
1614 // Again to check cache
1616 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1619 catch (const ImmediateServFailException
& ex
) {
1624 BOOST_AUTO_TEST_CASE(test_cname_loop_forwarder
)
1626 std::unique_ptr
<SyncRes
> resolver
;
1632 const DNSName
target("cname.powerdns.com.");
1633 const DNSName
cname1("cname1.cname.powerdns.com.");
1634 const DNSName
cname2("cname2.cname.powerdns.com.");
1636 SyncRes::AuthDomain ad
;
1637 const std::vector
<ComboAddress
> forwardedNSs
{ComboAddress("192.0.2.42:53")};
1638 ad
.d_rdForward
= true;
1639 ad
.d_servers
= forwardedNSs
;
1640 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
1642 resolver
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1645 if (isRootServer(address
)) {
1647 setLWResult(res
, 0, false, false, true);
1648 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1649 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1650 return LWResult::Result::Success
;
1652 if (address
== ComboAddress("192.0.2.42:53")) {
1654 if (domain
== target
) {
1655 setLWResult(res
, 0, true, false, false);
1656 addRecordToLW(res
, domain
, QType::CNAME
, cname1
.toString());
1657 addRecordToLW(res
, cname1
, QType::CNAME
, cname2
.toString());
1658 addRecordToLW(res
, cname2
, QType::CNAME
, domain
.toString());
1659 return LWResult::Result::Success
;
1662 return LWResult::Result::Success
;
1665 return LWResult::Result::Timeout
;
1668 vector
<DNSRecord
> ret
;
1669 BOOST_REQUIRE_THROW(resolver
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
), ImmediateServFailException
);
1672 BOOST_AUTO_TEST_CASE(test_cname_long_loop
)
1674 std::unique_ptr
<SyncRes
> sr
;
1680 const DNSName
target1("cname1.powerdns.com.");
1681 const DNSName
target2("cname2.powerdns.com.");
1682 const DNSName
target3("cname3.powerdns.com.");
1683 const DNSName
target4("cname4.powerdns.com.");
1685 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1688 if (isRootServer(address
)) {
1690 setLWResult(res
, 0, false, false, true);
1691 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1692 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1693 return LWResult::Result::Success
;
1695 if (address
== ComboAddress("192.0.2.1:53")) {
1697 if (domain
== target1
) {
1698 setLWResult(res
, 0, true, false, false);
1699 addRecordToLW(res
, domain
, QType::CNAME
, target2
.toString());
1700 return LWResult::Result::Success
;
1702 if (domain
== target2
) {
1703 setLWResult(res
, 0, true, false, false);
1704 addRecordToLW(res
, domain
, QType::CNAME
, target3
.toString());
1705 return LWResult::Result::Success
;
1707 if (domain
== target3
) {
1708 setLWResult(res
, 0, true, false, false);
1709 addRecordToLW(res
, domain
, QType::CNAME
, target4
.toString());
1710 return LWResult::Result::Success
;
1712 if (domain
== target4
) {
1713 setLWResult(res
, 0, true, false, false);
1714 addRecordToLW(res
, domain
, QType::CNAME
, target1
.toString());
1715 return LWResult::Result::Success
;
1718 return LWResult::Result::Success
;
1721 return LWResult::Result::Timeout
;
1724 vector
<DNSRecord
> ret
;
1725 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1726 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1727 BOOST_CHECK_EQUAL(ret
.size(), 0U);
1728 BOOST_CHECK_EQUAL(count
, 8U);
1730 // And again to check cache
1732 sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1735 catch (const ImmediateServFailException
& ex
) {
1740 BOOST_AUTO_TEST_CASE(test_cname_length
)
1742 std::unique_ptr
<SyncRes
> sr
;
1748 const DNSName
target("cname.powerdns.com.");
1750 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1751 if (isRootServer(address
)) {
1753 setLWResult(res
, 0, false, false, true);
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 if (address
== ComboAddress("192.0.2.1:53")) {
1760 setLWResult(res
, 0, true, false, false);
1761 addRecordToLW(res
, domain
, QType::CNAME
, std::to_string(length
) + "-cname.powerdns.com");
1763 return LWResult::Result::Success
;
1766 return LWResult::Result::Timeout
;
1769 vector
<DNSRecord
> ret
;
1770 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1771 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1772 BOOST_CHECK_EQUAL(ret
.size(), length
);
1773 BOOST_CHECK_EQUAL(length
, SyncRes::s_max_CNAMES_followed
+ 1);
1776 BOOST_AUTO_TEST_CASE(test_cname_target_servfail
)
1778 std::unique_ptr
<SyncRes
> resolver
;
1783 const DNSName
target("cname.powerdns.com.");
1784 const DNSName
cnameTarget("cname-target.powerdns.com");
1786 resolver
->setAsyncCallback([&](const ComboAddress
& ipAddress
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1787 if (isRootServer(ipAddress
)) {
1788 setLWResult(res
, 0, false, false, true);
1789 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1790 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1791 return LWResult::Result::Success
;
1793 if (ipAddress
== ComboAddress("192.0.2.1:53")) {
1795 if (domain
== target
) {
1796 setLWResult(res
, 0, true, false, false);
1797 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1798 return LWResult::Result::Success
;
1800 if (domain
== cnameTarget
) {
1801 return LWResult::Result::PermanentError
;
1804 return LWResult::Result::Success
;
1807 return LWResult::Result::Timeout
;
1810 vector
<DNSRecord
> ret
;
1811 int res
= resolver
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1812 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1813 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1814 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1815 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1818 BOOST_AUTO_TEST_CASE(test_cname_target_servfail_servestale
)
1820 std::unique_ptr
<SyncRes
> resolver
;
1822 MemRecursorCache::s_maxServedStaleExtensions
= 1440;
1826 const DNSName
target("cname.powerdns.com.");
1827 const DNSName
cnameTarget("cname-target.powerdns.com");
1829 resolver
->setAsyncCallback([&](const ComboAddress
& ipAddress
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1830 if (isRootServer(ipAddress
)) {
1831 setLWResult(res
, 0, false, false, true);
1832 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1833 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1834 return LWResult::Result::Success
;
1836 if (ipAddress
== ComboAddress("192.0.2.1:53")) {
1838 if (domain
== target
) {
1839 setLWResult(res
, 0, true, false, false);
1840 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1841 return LWResult::Result::Success
;
1843 if (domain
== cnameTarget
) {
1844 return LWResult::Result::PermanentError
;
1847 return LWResult::Result::Success
;
1850 return LWResult::Result::Timeout
;
1853 vector
<DNSRecord
> ret
;
1854 int res
= resolver
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1855 // different compared no non-servestale case (returns ServFail), handled by pdns_recursor
1856 BOOST_CHECK_EQUAL(res
, -1);
1857 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1858 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1859 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1862 BOOST_AUTO_TEST_CASE(test_time_limit
)
1864 std::unique_ptr
<SyncRes
> sr
;
1870 const DNSName
target("cname.powerdns.com.");
1872 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1875 if (isRootServer(address
)) {
1876 setLWResult(res
, 0, false, false, true);
1877 /* Pretend that this query took 2000 ms */
1880 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1881 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1882 return LWResult::Result::Success
;
1884 if (address
== ComboAddress("192.0.2.1:53")) {
1886 setLWResult(res
, 0, true, false, false);
1887 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1888 return LWResult::Result::Success
;
1891 return LWResult::Result::Timeout
;
1894 /* Set the maximum time to 1 ms */
1895 SyncRes::s_maxtotusec
= 1000;
1898 vector
<DNSRecord
> ret
;
1899 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1902 catch (const ImmediateServFailException
& e
) {
1904 BOOST_CHECK_EQUAL(queries
, 1U);
1907 BOOST_AUTO_TEST_CASE(test_dname_processing
)
1909 std::unique_ptr
<SyncRes
> sr
;
1914 const DNSName
dnameOwner("powerdns.com");
1915 const DNSName
dnameTarget("powerdns.net");
1917 const DNSName
target("dname.powerdns.com.");
1918 const DNSName
cnameTarget("dname.powerdns.net");
1920 const DNSName
uncachedTarget("dname-uncached.powerdns.com.");
1921 const DNSName
uncachedCNAMETarget("dname-uncached.powerdns.net.");
1923 const DNSName
synthCNAME("cname-uncached.powerdns.com.");
1924 const DNSName
synthCNAMETarget("cname-uncached.powerdns.net.");
1928 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
1931 if (isRootServer(address
)) {
1932 if (domain
.isPartOf(dnameOwner
)) {
1933 setLWResult(res
, 0, false, false, true);
1934 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1935 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1936 return LWResult::Result::Success
;
1938 if (domain
.isPartOf(dnameTarget
)) {
1939 setLWResult(res
, 0, false, false, true);
1940 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1941 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1942 return LWResult::Result::Success
;
1945 else if (address
== ComboAddress("192.0.2.1:53")) {
1946 if (domain
== target
) {
1947 setLWResult(res
, 0, true, false, false);
1948 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
1949 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1950 return LWResult::Result::Success
;
1953 else if (address
== ComboAddress("192.0.2.2:53")) {
1954 if (domain
== cnameTarget
) {
1955 setLWResult(res
, 0, true, false, false);
1956 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1958 if (domain
== uncachedCNAMETarget
) {
1959 setLWResult(res
, 0, true, false, false);
1960 addRecordToLW(res
, domain
, QType::A
, "192.0.2.3");
1962 return LWResult::Result::Success
;
1964 return LWResult::Result::Timeout
;
1967 vector
<DNSRecord
> ret
;
1968 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1970 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1971 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
1973 BOOST_CHECK_EQUAL(queries
, 4u);
1975 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1976 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1977 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1979 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
1980 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
1982 BOOST_CHECK(ret
[2].d_type
== QType::A
);
1983 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
1985 // Now check the cache
1987 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1989 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1990 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
1992 BOOST_CHECK_EQUAL(queries
, 4U);
1994 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1995 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1996 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1998 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
1999 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
2001 BOOST_CHECK(ret
[2].d_type
== QType::A
);
2002 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
2004 // Check if we correctly return a synthesized CNAME, should send out just 1 more query
2006 res
= sr
->beginResolve(uncachedTarget
, QType(QType::A
), QClass::IN
, ret
);
2008 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2009 BOOST_CHECK_EQUAL(queries
, 5U);
2011 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2012 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2013 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2015 BOOST_REQUIRE(ret
[1].d_type
== QType::CNAME
);
2016 BOOST_CHECK_EQUAL(ret
[1].d_name
, uncachedTarget
);
2017 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[1])->getTarget(), uncachedCNAMETarget
);
2019 BOOST_CHECK(ret
[2].d_type
== QType::A
);
2020 BOOST_CHECK_EQUAL(ret
[2].d_name
, uncachedCNAMETarget
);
2022 // Check if we correctly return the DNAME from cache when asked
2024 res
= sr
->beginResolve(dnameOwner
, QType(QType::DNAME
), QClass::IN
, ret
);
2025 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2026 BOOST_CHECK_EQUAL(queries
, 5U);
2028 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2029 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2030 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2032 // Check if we correctly return the synthesized CNAME from cache when asked
2034 res
= sr
->beginResolve(synthCNAME
, QType(QType::CNAME
), QClass::IN
, ret
);
2035 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2036 BOOST_CHECK_EQUAL(queries
, 5U);
2038 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2039 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2040 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2042 BOOST_REQUIRE(ret
[1].d_type
== QType::CNAME
);
2043 BOOST_CHECK(ret
[1].d_name
== synthCNAME
);
2044 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[1])->getTarget(), synthCNAMETarget
);
2047 BOOST_AUTO_TEST_CASE(test_dname_dnssec_secure
)
2049 std::unique_ptr
<SyncRes
> sr
;
2051 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
2055 const DNSName
dnameOwner("powerdns");
2056 const DNSName
dnameTarget("example");
2058 const DNSName
target("dname.powerdns");
2059 const DNSName
cnameTarget("dname.example");
2063 auto luaconfsCopy
= g_luaconfs
.getCopy();
2064 luaconfsCopy
.dsAnchors
.clear();
2065 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2066 generateKeyMaterial(dnameOwner
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2067 generateKeyMaterial(dnameTarget
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2068 g_luaconfs
.setState(luaconfsCopy
);
2072 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
2074 /* 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
2075 * As such, we need to do some more work to make the answers correct.
2078 if (isRootServer(address
)) {
2079 if (domain
.countLabels() == 0 && type
== QType::DNSKEY
) { // .|DNSKEY
2080 setLWResult(res
, 0, true, false, true);
2081 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2082 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2083 return LWResult::Result::Success
;
2085 if (domain
.countLabels() == 1 && type
== QType::DS
) { // powerdns|DS or example|DS
2086 setLWResult(res
, 0, true, false, true);
2087 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
2088 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2089 return LWResult::Result::Success
;
2091 // For the rest, delegate!
2092 if (domain
.isPartOf(dnameOwner
)) {
2093 setLWResult(res
, 0, false, false, true);
2094 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2095 addDS(dnameOwner
, 300, res
->d_records
, keys
);
2096 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2097 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2098 return LWResult::Result::Success
;
2100 if (domain
.isPartOf(dnameTarget
)) {
2101 setLWResult(res
, 0, false, false, true);
2102 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2103 addDS(dnameTarget
, 300, res
->d_records
, keys
);
2104 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2105 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2106 return LWResult::Result::Success
;
2109 else if (address
== ComboAddress("192.0.2.1:53")) {
2110 if (domain
.countLabels() == 1 && type
== QType::DNSKEY
) { // powerdns|DNSKEY
2111 setLWResult(res
, 0, true, false, true);
2112 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2113 addRRSIG(keys
, res
->d_records
, domain
, 300);
2114 return LWResult::Result::Success
;
2116 if (domain
== target
&& type
== QType::DS
) { // dname.powerdns|DS
2117 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
2119 if (domain
== target
) {
2120 setLWResult(res
, 0, true, false, false);
2121 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2122 addRRSIG(keys
, res
->d_records
, dnameOwner
, 300);
2123 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString()); // CNAME from a DNAME is not signed
2124 return LWResult::Result::Success
;
2127 else if (address
== ComboAddress("192.0.2.2:53")) {
2128 if (domain
.countLabels() == 1 && type
== QType::DNSKEY
) { // example|DNSKEY
2129 setLWResult(res
, 0, true, false, true);
2130 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2131 addRRSIG(keys
, res
->d_records
, domain
, 300);
2132 return LWResult::Result::Success
;
2134 if (domain
== cnameTarget
&& type
== QType::DS
) { // dname.example|DS
2135 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
2137 if (domain
== cnameTarget
) {
2138 setLWResult(res
, 0, true, false, false);
2139 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2140 addRRSIG(keys
, res
->d_records
, dnameTarget
, 300);
2142 return LWResult::Result::Success
;
2144 return LWResult::Result::Timeout
;
2147 vector
<DNSRecord
> ret
;
2148 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2150 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2151 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2152 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2154 BOOST_CHECK_EQUAL(queries
, 7U);
2156 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2157 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2158 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2160 BOOST_REQUIRE(ret
[1].d_type
== QType::RRSIG
);
2161 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2163 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2164 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2166 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2167 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2169 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2170 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2174 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2176 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2177 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2178 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2180 BOOST_CHECK_EQUAL(queries
, 7U);
2182 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2183 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2184 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2186 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2187 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2189 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2190 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2192 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2193 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2195 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2196 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2199 BOOST_AUTO_TEST_CASE(test_dname_plus_ns_dnssec_secure
)
2201 std::unique_ptr
<SyncRes
> sr
;
2203 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
2207 const DNSName
dnameOwner("powerdns");
2208 const DNSName
dnameTarget("example");
2210 const DNSName
target("dname.powerdns");
2211 const DNSName
cnameTarget("dname.example");
2215 auto luaconfsCopy
= g_luaconfs
.getCopy();
2216 luaconfsCopy
.dsAnchors
.clear();
2217 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2218 generateKeyMaterial(dnameTarget
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2219 g_luaconfs
.setState(luaconfsCopy
);
2223 sr
->setAsyncCallback([&](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
2226 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
2227 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
2230 if (domain
.isPartOf(dnameOwner
)) {
2231 setLWResult(res
, 0, true, false, true);
2232 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2233 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2234 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString()); // CNAME from a DNAME is not signed
2236 addRecordToLW(res
, dnameTarget
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2237 addDS(dnameTarget
, 300, res
->d_records
, keys
);
2238 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2239 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2240 return LWResult::Result::Success
;
2242 if (domain
== cnameTarget
) {
2243 setLWResult(res
, 0, true, false, true);
2244 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2245 addRRSIG(keys
, res
->d_records
, dnameTarget
, 300);
2246 return LWResult::Result::Success
;
2248 return LWResult::Result::Timeout
;
2251 vector
<DNSRecord
> ret
;
2252 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2254 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2255 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2256 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2258 BOOST_CHECK_EQUAL(queries
, 4U);
2260 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2261 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2262 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2264 BOOST_REQUIRE(ret
[1].d_type
== QType::RRSIG
);
2265 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2267 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2268 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2270 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2271 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2273 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2274 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2278 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2280 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2281 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2282 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2284 BOOST_CHECK_EQUAL(queries
, 4U);
2286 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2287 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2288 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2290 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2291 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2293 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2294 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2296 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2297 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2299 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2300 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2303 BOOST_AUTO_TEST_CASE(test_dname_dnssec_insecure
)
2306 * The DNAME itself is signed, but the final A record is not
2308 std::unique_ptr
<SyncRes
> sr
;
2310 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
2314 const DNSName
dnameOwner("powerdns");
2315 const DNSName
dnameTarget("example");
2317 const DNSName
target("dname.powerdns");
2318 const DNSName
cnameTarget("dname.example");
2322 auto luaconfsCopy
= g_luaconfs
.getCopy();
2323 luaconfsCopy
.dsAnchors
.clear();
2324 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2325 generateKeyMaterial(dnameOwner
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2326 g_luaconfs
.setState(luaconfsCopy
);
2330 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
2333 if (isRootServer(address
)) {
2334 if (domain
.countLabels() == 0 && type
== QType::DNSKEY
) { // .|DNSKEY
2335 setLWResult(res
, 0, true, false, true);
2336 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2337 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2338 return LWResult::Result::Success
;
2340 if (domain
== dnameOwner
&& type
== QType::DS
) { // powerdns|DS
2341 setLWResult(res
, 0, true, false, true);
2342 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
2343 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2344 return LWResult::Result::Success
;
2346 if (domain
== dnameTarget
&& type
== QType::DS
) { // example|DS
2347 return genericDSAndDNSKEYHandler(res
, domain
, DNSName("."), type
, keys
);
2349 // For the rest, delegate!
2350 if (domain
.isPartOf(dnameOwner
)) {
2351 setLWResult(res
, 0, false, false, true);
2352 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2353 addDS(dnameOwner
, 300, res
->d_records
, keys
);
2354 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2355 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2356 return LWResult::Result::Success
;
2358 if (domain
.isPartOf(dnameTarget
)) {
2359 setLWResult(res
, 0, false, false, true);
2360 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2361 addDS(dnameTarget
, 300, res
->d_records
, keys
);
2362 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2363 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2364 return LWResult::Result::Success
;
2367 else if (address
== ComboAddress("192.0.2.1:53")) {
2368 if (domain
.countLabels() == 1 && type
== QType::DNSKEY
) { // powerdns|DNSKEY
2369 setLWResult(res
, 0, true, false, true);
2370 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2371 addRRSIG(keys
, res
->d_records
, domain
, 300);
2372 return LWResult::Result::Success
;
2374 if (domain
== target
&& type
== QType::DS
) { // dname.powerdns|DS
2375 return genericDSAndDNSKEYHandler(res
, domain
, dnameOwner
, type
, keys
, false);
2377 if (domain
== target
) {
2378 setLWResult(res
, 0, true, false, false);
2379 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2380 addRRSIG(keys
, res
->d_records
, dnameOwner
, 300);
2381 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString()); // CNAME from a DNAME is not signed
2382 return LWResult::Result::Success
;
2385 else if (address
== ComboAddress("192.0.2.2:53")) {
2386 if (domain
== target
&& type
== QType::DS
) { // dname.example|DS
2387 return genericDSAndDNSKEYHandler(res
, domain
, dnameTarget
, type
, keys
, false);
2389 if (domain
== cnameTarget
) {
2390 setLWResult(res
, 0, true, false, false);
2391 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2393 return LWResult::Result::Success
;
2395 return LWResult::Result::Timeout
;
2398 vector
<DNSRecord
> ret
;
2399 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2401 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2402 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
2403 BOOST_REQUIRE_EQUAL(ret
.size(), 4U); /* DNAME + RRSIG(DNAME) + CNAME + A */
2405 BOOST_CHECK_EQUAL(queries
, 7U);
2407 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2408 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2409 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2411 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2412 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2414 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2415 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2417 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2418 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2422 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2424 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2425 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
2426 BOOST_REQUIRE_EQUAL(ret
.size(), 4U); /* DNAME + RRSIG(DNAME) + CNAME + A */
2428 BOOST_CHECK_EQUAL(queries
, 7U);
2430 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2431 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2432 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2434 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2435 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2437 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2438 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2440 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2441 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2444 BOOST_AUTO_TEST_CASE(test_dname_processing_no_CNAME
)
2446 std::unique_ptr
<SyncRes
> sr
;
2451 const DNSName
dnameOwner("powerdns.com");
2452 const DNSName
dnameTarget("powerdns.net");
2454 const DNSName
target("dname.powerdns.com.");
2455 const DNSName
cnameTarget("dname.powerdns.net");
2459 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
2462 if (isRootServer(address
)) {
2463 if (domain
.isPartOf(dnameOwner
)) {
2464 setLWResult(res
, 0, false, false, true);
2465 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2466 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2467 return LWResult::Result::Success
;
2469 if (domain
.isPartOf(dnameTarget
)) {
2470 setLWResult(res
, 0, false, false, true);
2471 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2472 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2473 return LWResult::Result::Success
;
2476 else if (address
== ComboAddress("192.0.2.1:53")) {
2477 if (domain
== target
) {
2478 setLWResult(res
, 0, true, false, false);
2479 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2480 // No CNAME, recursor should synth
2481 return LWResult::Result::Success
;
2484 else if (address
== ComboAddress("192.0.2.2:53")) {
2485 if (domain
== cnameTarget
) {
2486 setLWResult(res
, 0, true, false, false);
2487 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2489 return LWResult::Result::Success
;
2491 return LWResult::Result::Timeout
;
2494 vector
<DNSRecord
> ret
;
2495 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2497 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2498 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
2500 BOOST_CHECK_EQUAL(queries
, 4U);
2502 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2503 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2504 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2506 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
2507 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
2509 BOOST_CHECK(ret
[2].d_type
== QType::A
);
2510 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
2512 // Now check the cache
2514 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2516 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2517 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
2519 BOOST_CHECK_EQUAL(queries
, 4U);
2521 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2522 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2523 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2525 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
2526 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
2528 BOOST_CHECK(ret
[2].d_type
== QType::A
);
2529 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
2533 // cerr<<"asyncresolve called to ask "<<ip.toStringWithPort()<<" about "<<domain.toString()<<" / "<<QType(type).getName()<<" over "<<(doTCP ? "TCP" : "UDP")<<" (rd: "<<sendRDQuery<<", EDNS0 level: "<<EDNS0Level<<")"<<endl;
2535 - check out of band support
2541 BOOST_AUTO_TEST_CASE(test_glued_referral_child_ns_set_wrong
)
2543 std::unique_ptr
<SyncRes
> sr
;
2548 const DNSName
target("powerdns.com.");
2550 sr
->setAsyncCallback([&](const ComboAddress
& address
, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const ResolveContext
& /* context */, LWResult
* res
, bool* /* chained */) {
2551 /* this will cause issue with qname minimization if we ever implement it */
2552 if (domain
!= target
) {
2553 return LWResult::Result::Timeout
;
2556 if (isRootServer(address
)) {
2557 setLWResult(res
, 0, false, false, true);
2558 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2559 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2560 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
2561 return LWResult::Result::Success
;
2563 if (address
== ComboAddress("192.0.2.1:53") || address
== ComboAddress("[2001:DB8::1]:53")) {
2564 setLWResult(res
, 0, false, false, true);
2565 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
2566 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
2567 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
2568 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
2569 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
2570 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
2571 return LWResult::Result::Success
;
2573 if (address
== ComboAddress("192.0.2.2:53") || address
== ComboAddress("192.0.2.3:53") || address
== ComboAddress("[2001:DB8::2]:53") || address
== ComboAddress("[2001:DB8::3]:53")) {
2575 if (type
== QType::A
) {
2576 setLWResult(res
, 0, true, false, true);
2577 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
2578 return LWResult::Result::Success
;
2580 if (type
== QType::NS
) {
2581 setLWResult(res
, 0, true, false, true);
2582 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-nsX1.powerdns.com.", DNSResourceRecord::ANSWER
, 172800);
2583 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-nsX2.powerdns.com.", DNSResourceRecord::ANSWER
, 172800);
2584 addRecordToLW(res
, "pdns-public-nsX1.powerdns.com.", QType::A
, "192.0.2.11", DNSResourceRecord::ADDITIONAL
, 172800);
2585 addRecordToLW(res
, "pdns-public-nsX1.powerdns.com.", QType::AAAA
, "2001:DB8::11", DNSResourceRecord::ADDITIONAL
, 172800);
2586 addRecordToLW(res
, "pdns-public-nsX2.powerdns.com.", QType::A
, "192.0.2.12", DNSResourceRecord::ADDITIONAL
, 172800);
2587 addRecordToLW(res
, "pdns-public-nsX2.powerdns.com.", QType::AAAA
, "2001:DB8::12", DNSResourceRecord::ADDITIONAL
, 172800);
2588 return LWResult::Result::Success
;
2590 return LWResult::Result::Timeout
;
2592 return LWResult::Result::Timeout
;
2595 vector
<DNSRecord
> ret
;
2596 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2597 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2598 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
2599 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2600 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
2602 // Now resolve NS to get auth NS set in cache and save the parent NS set
2604 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
2605 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2606 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
2607 BOOST_CHECK(ret
[0].d_type
== QType::NS
);
2608 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
2609 BOOST_CHECK_EQUAL(SyncRes::getSaveParentsNSSetsSize(), 1U);
2611 g_recCache
->doWipeCache(target
, false, QType::A
);
2612 SyncRes::s_save_parent_ns_set
= false;
2614 // Try to resolve now via the broken child NS set... should not work
2616 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2617 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
2618 BOOST_REQUIRE_EQUAL(ret
.size(), 0U);
2620 SyncRes::s_save_parent_ns_set
= true;
2622 // Try to resolve now via the broken child... should work now via fallback to parent NS set
2624 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2625 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2626 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
2627 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2628 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
2631 BOOST_AUTO_TEST_SUITE_END()