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 return LWResult::Result::Timeout
;
477 DNSName
target("powerdns.com.");
479 vector
<DNSRecord
> ret
;
480 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
481 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
482 BOOST_CHECK_EQUAL(ret
.size(), 0U);
483 BOOST_CHECK_EQUAL(downServers
.size(), 4U);
485 time_t now
= sr
->getNow().tv_sec
;
486 for (const auto& server
: downServers
) {
487 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1U);
488 BOOST_CHECK(SyncRes::isThrottled(now
, server
, target
, QType::A
));
492 BOOST_AUTO_TEST_CASE(test_all_nss_network_error
)
494 std::unique_ptr
<SyncRes
> sr
;
496 std::set
<ComboAddress
> downServers
;
500 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 */) {
501 if (isRootServer(address
)) {
502 setLWResult(res
, 0, false, false, true);
503 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
504 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
505 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
506 return LWResult::Result::Success
;
508 if (address
== ComboAddress("192.0.2.1:53") || address
== ComboAddress("[2001:DB8::1]:53")) {
509 setLWResult(res
, 0, false, false, true);
510 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
511 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
512 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
513 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
514 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
515 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
516 return LWResult::Result::Success
;
518 downServers
.insert(address
);
519 return LWResult::Result::Timeout
;
522 /* exact same test than the previous one, except instead of a time out we fake a network error */
523 DNSName
target("powerdns.com.");
525 vector
<DNSRecord
> ret
;
526 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
527 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
528 BOOST_CHECK_EQUAL(ret
.size(), 0U);
529 BOOST_CHECK_EQUAL(downServers
.size(), 4U);
531 time_t now
= sr
->getNow().tv_sec
;
532 for (const auto& server
: downServers
) {
533 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1U);
534 BOOST_CHECK(SyncRes::isThrottled(now
, server
, target
, QType::A
));
538 BOOST_AUTO_TEST_CASE(test_all_nss_send_tc_then_garbage_over_tcp
)
540 std::unique_ptr
<SyncRes
> sr
;
545 std::set
<ComboAddress
> downServers
;
547 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 */) {
548 if (isRootServer(address
)) {
549 setLWResult(res
, 0, false, false, true);
550 addRecordToLW(res
, "lock-up.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
551 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
552 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
553 return LWResult::Result::Success
;
557 setLWResult(res
, 0, false, true, false);
558 return LWResult::Result::Success
;
560 downServers
.insert(address
);
562 setLWResult(res
, RCode::FormErr
, false, false, false);
563 res
->d_validpacket
= false;
564 return LWResult::Result::Success
;
567 DNSName
target("www.lock-up.");
569 vector
<DNSRecord
> ret
;
570 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
571 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
572 BOOST_CHECK_EQUAL(ret
.size(), 0U);
573 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
575 for (const auto& server
: downServers
) {
576 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
577 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 1000000U);
581 BOOST_AUTO_TEST_CASE(test_all_nss_send_garbage_over_udp
)
583 std::unique_ptr
<SyncRes
> sr
;
588 std::set
<ComboAddress
> downServers
;
589 size_t queriesCount
= 0;
591 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 */) {
592 if (isRootServer(address
)) {
593 setLWResult(res
, 0, false, false, true);
594 addRecordToLW(res
, "lock-up.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
595 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
596 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
597 return LWResult::Result::Success
;
601 downServers
.insert(address
);
603 setLWResult(res
, RCode::FormErr
, false, false, false);
604 res
->d_validpacket
= false;
605 return LWResult::Result::Success
;
608 DNSName
target("www.lock-up.");
610 vector
<DNSRecord
> ret
;
611 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
612 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
613 BOOST_CHECK_EQUAL(ret
.size(), 0U);
614 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
615 /* two queries with EDNS, that's it */
616 BOOST_CHECK_EQUAL(queriesCount
, 2U);
618 for (const auto& server
: downServers
) {
619 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
620 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 1000000U);
621 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSIGNORANT
);
625 BOOST_AUTO_TEST_CASE(test_regular_ns_send_refused
)
627 std::unique_ptr
<SyncRes
> sr
;
632 std::set
<ComboAddress
> downServers
;
633 size_t queriesCount
= 0;
635 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 */) {
636 if (isRootServer(address
)) {
637 setLWResult(res
, 0, false, false, true);
638 addRecordToLW(res
, "refused.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
639 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
640 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
641 return LWResult::Result::Success
;
645 downServers
.insert(address
);
647 setLWResult(res
, RCode::Refused
, false, false, true);
649 return LWResult::Result::Success
;
652 DNSName
target("www.refused.");
654 vector
<DNSRecord
> ret
;
655 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
656 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
657 BOOST_CHECK_EQUAL(ret
.size(), 0U);
658 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
659 BOOST_CHECK_EQUAL(queriesCount
, 2U);
661 for (const auto& server
: downServers
) {
662 /* same as any other server */
663 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
664 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 0U);
665 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
669 BOOST_AUTO_TEST_CASE(test_forward_ns_send_refused
)
671 std::unique_ptr
<SyncRes
> sr
;
676 std::set
<ComboAddress
> downServers
;
677 size_t queriesCount
= 0;
679 const DNSName
target("www.refused.");
681 SyncRes::AuthDomain ad
;
682 const std::vector
<ComboAddress
> forwardedNSs
{ComboAddress("192.0.2.42:53"), ComboAddress("192.0.2.43:53")};
683 ad
.d_rdForward
= false;
684 ad
.d_servers
= forwardedNSs
;
685 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
687 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 */) {
688 if (isRootServer(address
)) {
689 setLWResult(res
, 0, false, false, true);
690 addRecordToLW(res
, "refused.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
691 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
692 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
693 return LWResult::Result::Success
;
697 downServers
.insert(address
);
699 setLWResult(res
, RCode::Refused
, false, false, true);
701 return LWResult::Result::Success
;
704 vector
<DNSRecord
> ret
;
705 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
706 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
707 BOOST_CHECK_EQUAL(ret
.size(), 0U);
708 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
709 BOOST_CHECK_EQUAL(queriesCount
, 2U);
711 for (const auto& server
: forwardedNSs
) {
712 BOOST_CHECK_EQUAL(downServers
.count(server
), 1U);
713 /* same as any other server */
714 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
715 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 0U);
716 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
720 BOOST_AUTO_TEST_CASE(test_forward_ns_send_servfail
)
722 std::unique_ptr
<SyncRes
> sr
;
727 std::set
<ComboAddress
> downServers
;
728 size_t queriesCount
= 0;
730 const DNSName
target("www.refused.");
732 SyncRes::AuthDomain ad
;
733 const std::vector
<ComboAddress
> forwardedNSs
{ComboAddress("192.0.2.42:53"), ComboAddress("192.0.2.43:53")};
734 ad
.d_rdForward
= false;
735 ad
.d_servers
= forwardedNSs
;
736 (*SyncRes::t_sstorage
.domainmap
)[DNSName("refused.")] = ad
;
738 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 */) {
739 if (isRootServer(address
)) {
740 setLWResult(res
, 0, false, false, true);
741 addRecordToLW(res
, "refused.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
742 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
743 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
744 return LWResult::Result::Success
;
748 downServers
.insert(address
);
750 setLWResult(res
, RCode::ServFail
, false, false, true);
752 return LWResult::Result::Success
;
755 vector
<DNSRecord
> ret
;
756 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
757 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
758 BOOST_CHECK_EQUAL(ret
.size(), 0U);
759 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
760 BOOST_CHECK_EQUAL(queriesCount
, 2U);
762 for (const auto& server
: forwardedNSs
) {
763 BOOST_CHECK_EQUAL(downServers
.count(server
), 1U);
764 /* on servfail from a server we forward to we only increase the NS speed so
765 that a different server might be tried instead, but we don't throttle */
766 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
767 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName(server
.toStringWithPort()), server
), 1000000U);
768 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
772 BOOST_AUTO_TEST_CASE(test_only_one_ns_up_resolving_itself_with_glue
)
774 std::unique_ptr
<SyncRes
> sr
;
779 DNSName
target("www.powerdns.com.");
781 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 */) {
782 if (isRootServer(address
)) {
783 setLWResult(res
, 0, false, false, true);
784 if (domain
== target
) {
785 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
786 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.net.", DNSResourceRecord::AUTHORITY
, 172800);
787 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
788 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
790 else if (domain
== DNSName("pdns-public-ns2.powerdns.net.")) {
791 addRecordToLW(res
, "powerdns.net.", QType::NS
, "pdns-public-ns2.powerdns.net.", DNSResourceRecord::AUTHORITY
, 172800);
792 addRecordToLW(res
, "powerdns.net.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
793 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
794 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
796 return LWResult::Result::Success
;
798 if (address
== ComboAddress("192.0.2.3:53")) {
799 setLWResult(res
, 0, true, false, true);
800 if (domain
== DNSName("pdns-public-ns2.powerdns.net.")) {
801 if (type
== QType::A
) {
802 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::A
, "192.0.2.3");
804 else if (type
== QType::AAAA
) {
805 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::AAAA
, "2001:DB8::3");
808 else if (domain
== target
) {
809 if (type
== QType::A
) {
810 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
812 else if (type
== QType::AAAA
) {
813 addRecordToLW(res
, domain
, QType::AAAA
, "2001:DB8::1");
816 return LWResult::Result::Success
;
818 return LWResult::Result::Timeout
;
821 vector
<DNSRecord
> ret
;
822 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
823 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
824 BOOST_CHECK_EQUAL(ret
.size(), 1U);
827 BOOST_AUTO_TEST_CASE(test_os_limit_errors
)
829 std::unique_ptr
<SyncRes
> sr
;
831 std::set
<ComboAddress
> downServers
;
835 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 */) {
836 if (isRootServer(address
)) {
837 setLWResult(res
, 0, false, false, true);
838 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
839 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
840 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
841 return LWResult::Result::Success
;
843 if (address
== ComboAddress("192.0.2.1:53") || address
== ComboAddress("[2001:DB8::1]:53")) {
844 setLWResult(res
, 0, false, false, true);
845 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
846 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
847 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
848 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
849 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
850 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
851 return LWResult::Result::Success
;
854 if (downServers
.size() < 3) {
855 /* only the last one will answer */
856 downServers
.insert(address
);
857 return LWResult::Result::OSLimitError
;
859 setLWResult(res
, 0, true, false, true);
860 addRecordToLW(res
, "powerdns.com.", QType::A
, "192.0.2.42");
861 return LWResult::Result::Success
;
865 DNSName
target("powerdns.com.");
867 vector
<DNSRecord
> ret
;
868 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
869 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
870 BOOST_CHECK_EQUAL(ret
.size(), 1U);
871 BOOST_CHECK_EQUAL(downServers
.size(), 3U);
873 /* Error is reported as "OS limit error" (-2) so the servers should _NOT_ be marked down */
874 time_t now
= sr
->getNow().tv_sec
;
875 for (const auto& server
: downServers
) {
876 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 0U);
877 BOOST_CHECK(!SyncRes::isThrottled(now
, server
, target
, QType::A
));
881 BOOST_AUTO_TEST_CASE(test_glued_referral
)
883 std::unique_ptr
<SyncRes
> sr
;
888 const DNSName
target("powerdns.com.");
890 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 */) {
891 /* this will cause issue with qname minimization if we ever implement it */
892 if (domain
!= target
) {
893 return LWResult::Result::Timeout
;
896 if (isRootServer(address
)) {
897 setLWResult(res
, 0, false, false, true);
898 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
899 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
900 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
901 return LWResult::Result::Success
;
903 if (address
== ComboAddress("192.0.2.1:53") || address
== ComboAddress("[2001:DB8::1]:53")) {
904 setLWResult(res
, 0, false, false, true);
905 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
906 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
907 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
908 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
909 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
910 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
911 return LWResult::Result::Success
;
913 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")) {
914 setLWResult(res
, 0, true, false, true);
915 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
916 return LWResult::Result::Success
;
918 return LWResult::Result::Timeout
;
921 vector
<DNSRecord
> ret
;
922 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
923 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
924 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
925 BOOST_CHECK(ret
[0].d_type
== QType::A
);
926 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
929 BOOST_AUTO_TEST_CASE(test_glueless_referral
)
931 std::unique_ptr
<SyncRes
> sr
;
936 const DNSName
target("powerdns.com.");
938 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 */) {
939 if (isRootServer(address
)) {
940 setLWResult(res
, 0, false, false, true);
942 if (domain
.isPartOf(DNSName("com."))) {
943 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
945 else if (domain
.isPartOf(DNSName("org."))) {
946 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
949 setLWResult(res
, RCode::NXDomain
, false, false, true);
950 return LWResult::Result::Success
;
953 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
954 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
955 return LWResult::Result::Success
;
957 if (address
== ComboAddress("192.0.2.1:53") || address
== ComboAddress("[2001:DB8::1]:53")) {
958 if (domain
== target
) {
959 setLWResult(res
, 0, false, false, true);
960 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
961 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
962 return LWResult::Result::Success
;
964 if (domain
== DNSName("pdns-public-ns1.powerdns.org.")) {
965 setLWResult(res
, 0, true, false, true);
966 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2");
967 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::AAAA
, "2001:DB8::2");
968 return LWResult::Result::Success
;
970 if (domain
== DNSName("pdns-public-ns2.powerdns.org.")) {
971 setLWResult(res
, 0, true, false, true);
972 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::A
, "192.0.2.3");
973 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::AAAA
, "2001:DB8::3");
974 return LWResult::Result::Success
;
977 setLWResult(res
, RCode::NXDomain
, false, false, true);
978 return LWResult::Result::Success
;
980 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")) {
981 setLWResult(res
, 0, true, false, true);
982 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
983 return LWResult::Result::Success
;
985 return LWResult::Result::Timeout
;
988 vector
<DNSRecord
> ret
;
989 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
990 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
991 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
992 BOOST_CHECK(ret
[0].d_type
== QType::A
);
993 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
996 BOOST_AUTO_TEST_CASE(test_endless_glueless_referral
)
998 std::unique_ptr
<SyncRes
> sr
;
1003 const DNSName
target("powerdns.com.");
1006 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 */) {
1007 if (isRootServer(address
)) {
1008 setLWResult(res
, 0, false, false, true);
1010 if (domain
.isPartOf(DNSName("com."))) {
1011 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1013 else if (domain
.isPartOf(DNSName("org."))) {
1014 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1017 setLWResult(res
, RCode::NXDomain
, false, false, true);
1018 return LWResult::Result::Success
;
1021 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1022 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1023 return LWResult::Result::Success
;
1025 if (domain
== target
) {
1026 setLWResult(res
, 0, false, false, true);
1027 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1028 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1029 return LWResult::Result::Success
;
1031 setLWResult(res
, 0, false, false, true);
1032 addRecordToLW(res
, domain
, QType::NS
, std::to_string(count
) + ".ns1.powerdns.org", DNSResourceRecord::AUTHORITY
, 172800);
1033 addRecordToLW(res
, domain
, QType::NS
, std::to_string(count
) + ".ns2.powerdns.org", DNSResourceRecord::AUTHORITY
, 172800);
1035 return LWResult::Result::Success
;
1038 vector
<DNSRecord
> ret
;
1039 BOOST_CHECK_EXCEPTION(sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
),
1040 ImmediateServFailException
,
1041 [&](const ImmediateServFailException
& isfe
) {
1042 return isfe
.reason
.substr(0, 9) == "More than";
1046 BOOST_AUTO_TEST_CASE(test_glueless_referral_aaaa_task
)
1048 std::unique_ptr
<SyncRes
> sr
;
1053 const DNSName
target("powerdns.com.");
1055 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 */) {
1056 if (isRootServer(address
)) {
1057 setLWResult(res
, 0, false, false, true);
1059 if (domain
.isPartOf(DNSName("com."))) {
1060 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1062 else if (domain
.isPartOf(DNSName("org."))) {
1063 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1066 setLWResult(res
, RCode::NXDomain
, false, false, true);
1067 return LWResult::Result::Success
;
1070 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1071 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1072 return LWResult::Result::Success
;
1074 if (address
== ComboAddress("192.0.2.1:53") || address
== ComboAddress("[2001:DB8::1]:53")) {
1075 if (domain
== target
) {
1076 setLWResult(res
, 0, false, false, true);
1077 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1078 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1079 return LWResult::Result::Success
;
1081 if (domain
== DNSName("pdns-public-ns1.powerdns.org.")) {
1082 setLWResult(res
, 0, true, false, true);
1083 if (type
== QType::A
) {
1084 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2");
1087 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::AAAA
, "2001:DB8::2");
1089 return LWResult::Result::Success
;
1091 if (domain
== DNSName("pdns-public-ns2.powerdns.org.")) {
1092 setLWResult(res
, 0, true, false, true);
1093 if (type
== QType::A
) {
1094 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::A
, "192.0.2.3");
1097 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::AAAA
, "2001:DB8::3");
1099 return LWResult::Result::Success
;
1102 setLWResult(res
, RCode::NXDomain
, false, false, true);
1103 return LWResult::Result::Success
;
1105 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")) {
1106 setLWResult(res
, 0, true, false, true);
1107 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
1108 return LWResult::Result::Success
;
1110 return LWResult::Result::Timeout
;
1113 vector
<DNSRecord
> ret
;
1114 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1115 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1116 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1117 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1118 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1120 // One task should be submitted
1121 BOOST_REQUIRE_EQUAL(getTaskSize(), 1U);
1122 auto task
= taskQueuePop();
1123 BOOST_CHECK(task
.d_qname
== DNSName("pdns-public-ns1.powerdns.org") || task
.d_qname
== DNSName("pdns-public-ns2.powerdns.org"));
1124 BOOST_CHECK_EQUAL(task
.d_qtype
, QType::AAAA
);
1127 BOOST_AUTO_TEST_CASE(test_edns_subnet_by_domain
)
1129 std::unique_ptr
<SyncRes
> sr
;
1134 const DNSName
target("powerdns.com.");
1135 SyncRes::addEDNSDomain(target
);
1137 EDNSSubnetOpts incomingECS
;
1138 incomingECS
.source
= Netmask("192.0.2.128/32");
1139 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1141 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 */) {
1142 BOOST_REQUIRE(srcmask
);
1143 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1145 if (isRootServer(address
)) {
1146 setLWResult(res
, 0, false, false, true);
1147 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1148 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1150 /* this one did not use the ECS info */
1151 srcmask
= boost::none
;
1153 return LWResult::Result::Success
;
1155 if (address
== ComboAddress("192.0.2.1:53")) {
1157 setLWResult(res
, 0, true, false, false);
1158 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1160 /* this one did, but only up to a precision of /16, not the full /24 */
1161 srcmask
= Netmask("192.0.0.0/16");
1163 return LWResult::Result::Success
;
1166 return LWResult::Result::Timeout
;
1169 SyncRes::s_ecsqueries
= 0;
1170 SyncRes::s_ecsresponses
= 0;
1171 vector
<DNSRecord
> ret
;
1172 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1173 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1174 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1175 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1176 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1177 BOOST_CHECK_EQUAL(SyncRes::s_ecsqueries
, 2U);
1178 BOOST_CHECK_EQUAL(SyncRes::s_ecsresponses
, 1U);
1179 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize4
) {
1180 BOOST_CHECK_EQUAL(entry
.second
, entry
.first
== 15 ? 1U : 0U);
1182 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize6
) {
1183 BOOST_CHECK_EQUAL(entry
.second
, 0U);
1187 BOOST_AUTO_TEST_CASE(test_edns_subnet_by_addr
)
1189 std::unique_ptr
<SyncRes
> sr
;
1194 const DNSName
target("powerdns.com.");
1195 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1197 EDNSSubnetOpts incomingECS
;
1198 incomingECS
.source
= Netmask("2001:DB8::FF/128");
1199 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1201 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 */) {
1202 if (isRootServer(address
)) {
1203 BOOST_REQUIRE(!srcmask
);
1205 setLWResult(res
, 0, false, false, true);
1206 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1207 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1208 return LWResult::Result::Success
;
1210 if (address
== ComboAddress("192.0.2.1:53")) {
1212 BOOST_REQUIRE(srcmask
);
1213 BOOST_CHECK_EQUAL(srcmask
->toString(), "2001:db8::/56");
1215 setLWResult(res
, 0, true, false, false);
1216 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1217 return LWResult::Result::Success
;
1220 return LWResult::Result::Timeout
;
1223 SyncRes::s_ecsqueries
= 0;
1224 SyncRes::s_ecsresponses
= 0;
1225 vector
<DNSRecord
> ret
;
1226 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1227 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1228 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1229 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1230 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1231 BOOST_CHECK_EQUAL(SyncRes::s_ecsqueries
, 1U);
1232 BOOST_CHECK_EQUAL(SyncRes::s_ecsresponses
, 1U);
1233 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize4
) {
1234 BOOST_CHECK_EQUAL(entry
.second
, 0u);
1236 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize6
) {
1237 BOOST_CHECK_EQUAL(entry
.second
, entry
.first
== 55 ? 1U : 0U);
1241 BOOST_AUTO_TEST_CASE(test_ecs_use_requestor
)
1243 std::unique_ptr
<SyncRes
> sr
;
1248 const DNSName
target("powerdns.com.");
1249 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1250 // No incoming ECS data
1251 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::none
);
1253 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 */) {
1254 if (isRootServer(address
)) {
1255 BOOST_REQUIRE(!srcmask
);
1257 setLWResult(res
, 0, false, false, true);
1258 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1259 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1260 return LWResult::Result::Success
;
1262 if (address
== ComboAddress("192.0.2.1:53")) {
1264 BOOST_REQUIRE(srcmask
);
1265 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1267 setLWResult(res
, 0, true, false, false);
1268 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1269 return LWResult::Result::Success
;
1272 return LWResult::Result::Timeout
;
1275 vector
<DNSRecord
> ret
;
1276 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1277 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1278 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1279 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1280 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1283 BOOST_AUTO_TEST_CASE(test_ecs_use_scope_zero
)
1285 std::unique_ptr
<SyncRes
> sr
;
1290 const DNSName
target("powerdns.com.");
1291 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1292 SyncRes::clearEDNSLocalSubnets();
1293 SyncRes::addEDNSLocalSubnet("192.0.2.254/32");
1294 // No incoming ECS data, Requestor IP not in ecs-add-for
1295 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::none
);
1297 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 */) {
1298 if (isRootServer(address
)) {
1299 BOOST_REQUIRE(!srcmask
);
1301 setLWResult(res
, 0, false, false, true);
1302 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1303 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1304 return LWResult::Result::Success
;
1306 if (address
== ComboAddress("192.0.2.1:53")) {
1308 BOOST_REQUIRE(srcmask
);
1309 BOOST_CHECK_EQUAL(srcmask
->toString(), "127.0.0.1/32");
1311 setLWResult(res
, 0, true, false, false);
1312 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1313 return LWResult::Result::Success
;
1316 return LWResult::Result::Timeout
;
1319 vector
<DNSRecord
> ret
;
1320 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1321 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1322 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1323 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1324 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1327 BOOST_AUTO_TEST_CASE(test_ecs_honor_incoming_mask
)
1329 std::unique_ptr
<SyncRes
> sr
;
1334 const DNSName
target("powerdns.com.");
1335 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1336 SyncRes::clearEDNSLocalSubnets();
1337 SyncRes::addEDNSLocalSubnet("192.0.2.254/32");
1338 EDNSSubnetOpts incomingECS
;
1339 incomingECS
.source
= Netmask("192.0.0.0/16");
1340 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1342 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 */) {
1343 if (isRootServer(address
)) {
1344 BOOST_REQUIRE(!srcmask
);
1346 setLWResult(res
, 0, false, false, true);
1347 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1348 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1349 return LWResult::Result::Success
;
1351 if (address
== ComboAddress("192.0.2.1:53")) {
1353 BOOST_REQUIRE(srcmask
);
1354 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.0.0/16");
1356 setLWResult(res
, 0, true, false, false);
1357 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1358 return LWResult::Result::Success
;
1361 return LWResult::Result::Timeout
;
1364 vector
<DNSRecord
> ret
;
1365 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1366 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1367 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1368 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1369 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1372 BOOST_AUTO_TEST_CASE(test_ecs_honor_incoming_mask_zero
)
1374 std::unique_ptr
<SyncRes
> sr
;
1379 const DNSName
target("powerdns.com.");
1380 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1381 SyncRes::clearEDNSLocalSubnets();
1382 SyncRes::addEDNSLocalSubnet("192.0.2.254/32");
1383 EDNSSubnetOpts incomingECS
;
1384 incomingECS
.source
= Netmask("0.0.0.0/0");
1385 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1387 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 */) {
1388 if (isRootServer(address
)) {
1389 BOOST_REQUIRE(!srcmask
);
1391 setLWResult(res
, 0, false, false, true);
1392 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1393 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1394 return LWResult::Result::Success
;
1396 if (address
== ComboAddress("192.0.2.1:53")) {
1398 BOOST_REQUIRE(srcmask
);
1399 BOOST_CHECK_EQUAL(srcmask
->toString(), "127.0.0.1/32");
1401 setLWResult(res
, 0, true, false, false);
1402 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1403 return LWResult::Result::Success
;
1406 return LWResult::Result::Timeout
;
1409 vector
<DNSRecord
> ret
;
1410 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1411 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1412 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1413 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1414 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1417 BOOST_AUTO_TEST_CASE(test_following_cname
)
1419 std::unique_ptr
<SyncRes
> sr
;
1424 const DNSName
target("cname.powerdns.com.");
1425 const DNSName
cnameTarget("cname-target.powerdns.com");
1427 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 */) {
1428 if (isRootServer(address
)) {
1429 setLWResult(res
, 0, false, false, true);
1430 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1431 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1432 return LWResult::Result::Success
;
1434 if (address
== ComboAddress("192.0.2.1:53")) {
1436 if (domain
== target
) {
1437 setLWResult(res
, 0, true, false, false);
1438 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1439 return LWResult::Result::Success
;
1441 if (domain
== cnameTarget
) {
1442 setLWResult(res
, 0, true, false, false);
1443 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1446 return LWResult::Result::Success
;
1449 return LWResult::Result::Timeout
;
1452 vector
<DNSRecord
> ret
;
1453 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1454 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1455 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1456 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1457 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1458 BOOST_CHECK(ret
[1].d_type
== QType::A
);
1459 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1462 BOOST_AUTO_TEST_CASE(test_cname_nxdomain
)
1464 std::unique_ptr
<SyncRes
> sr
;
1469 const DNSName
target("cname.powerdns.com.");
1470 const DNSName
cnameTarget("cname-target.powerdns.com");
1472 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 */) {
1473 if (isRootServer(address
)) {
1474 setLWResult(res
, 0, false, false, true);
1475 addRecordToLW(res
, "powerdns.com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1476 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1477 return LWResult::Result::Success
;
1479 if (address
== ComboAddress("192.0.2.1:53")) {
1481 if (domain
== target
) {
1482 setLWResult(res
, RCode::NXDomain
, true, false, false);
1483 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1484 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1486 else if (domain
== cnameTarget
) {
1487 setLWResult(res
, RCode::NXDomain
, true, false, false);
1488 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1489 return LWResult::Result::Success
;
1492 return LWResult::Result::Success
;
1495 return LWResult::Result::Timeout
;
1498 vector
<DNSRecord
> ret
;
1499 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1500 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1501 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1502 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1503 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1504 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1506 /* a second time, to check the cache */
1508 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1509 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1510 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1511 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1512 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1513 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1516 BOOST_AUTO_TEST_CASE(test_included_poisonous_cname
)
1518 std::unique_ptr
<SyncRes
> sr
;
1523 /* In this test we directly get the NS server for cname.powerdns.com.,
1524 and we don't know whether it's also authoritative for
1525 cname-target.powerdns.com or powerdns.com, so we shouldn't accept
1526 the additional A record for cname-target.powerdns.com. */
1527 const DNSName
target("cname.powerdns.com.");
1528 const DNSName
cnameTarget("cname-target.powerdns.com");
1530 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 */) {
1531 if (isRootServer(address
)) {
1533 setLWResult(res
, 0, false, false, true);
1535 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1536 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1537 return LWResult::Result::Success
;
1539 if (address
== ComboAddress("192.0.2.1:53")) {
1541 if (domain
== target
) {
1542 setLWResult(res
, 0, true, false, false);
1543 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1544 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
);
1545 return LWResult::Result::Success
;
1547 if (domain
== cnameTarget
) {
1548 setLWResult(res
, 0, true, false, false);
1549 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.3");
1550 return LWResult::Result::Success
;
1553 return LWResult::Result::Success
;
1556 return LWResult::Result::Timeout
;
1559 vector
<DNSRecord
> ret
;
1560 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1561 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1562 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1563 BOOST_REQUIRE(ret
[0].d_type
== QType::CNAME
);
1564 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1565 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget(), cnameTarget
);
1566 BOOST_REQUIRE(ret
[1].d_type
== QType::A
);
1567 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1568 BOOST_CHECK(getRR
<ARecordContent
>(ret
[1])->getCA() == ComboAddress("192.0.2.3"));
1571 BOOST_AUTO_TEST_CASE(test_cname_loop
)
1573 std::unique_ptr
<SyncRes
> sr
;
1579 const DNSName
target("cname.powerdns.com.");
1581 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 */) {
1584 if (isRootServer(address
)) {
1586 setLWResult(res
, 0, false, false, true);
1587 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1588 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1589 return LWResult::Result::Success
;
1591 if (address
== ComboAddress("192.0.2.1:53")) {
1593 if (domain
== target
) {
1594 setLWResult(res
, 0, true, false, false);
1595 addRecordToLW(res
, domain
, QType::CNAME
, domain
.toString());
1596 return LWResult::Result::Success
;
1599 return LWResult::Result::Success
;
1602 return LWResult::Result::Timeout
;
1605 vector
<DNSRecord
> ret
;
1606 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1607 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1608 BOOST_CHECK_EQUAL(ret
.size(), 0U);
1609 BOOST_CHECK_EQUAL(count
, 2U);
1611 // Again to check cache
1613 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1616 catch (const ImmediateServFailException
& ex
) {
1621 BOOST_AUTO_TEST_CASE(test_cname_loop_forwarder
)
1623 std::unique_ptr
<SyncRes
> resolver
;
1629 const DNSName
target("cname.powerdns.com.");
1630 const DNSName
cname1("cname1.cname.powerdns.com.");
1631 const DNSName
cname2("cname2.cname.powerdns.com.");
1633 SyncRes::AuthDomain ad
;
1634 const std::vector
<ComboAddress
> forwardedNSs
{ComboAddress("192.0.2.42:53")};
1635 ad
.d_rdForward
= true;
1636 ad
.d_servers
= forwardedNSs
;
1637 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
1639 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 */) {
1642 if (isRootServer(address
)) {
1644 setLWResult(res
, 0, false, false, true);
1645 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1646 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1647 return LWResult::Result::Success
;
1649 if (address
== ComboAddress("192.0.2.42:53")) {
1651 if (domain
== target
) {
1652 setLWResult(res
, 0, true, false, false);
1653 addRecordToLW(res
, domain
, QType::CNAME
, cname1
.toString());
1654 addRecordToLW(res
, cname1
, QType::CNAME
, cname2
.toString());
1655 addRecordToLW(res
, cname2
, QType::CNAME
, domain
.toString());
1656 return LWResult::Result::Success
;
1659 return LWResult::Result::Success
;
1662 return LWResult::Result::Timeout
;
1665 vector
<DNSRecord
> ret
;
1666 BOOST_REQUIRE_THROW(resolver
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
), ImmediateServFailException
);
1669 BOOST_AUTO_TEST_CASE(test_cname_long_loop
)
1671 std::unique_ptr
<SyncRes
> sr
;
1677 const DNSName
target1("cname1.powerdns.com.");
1678 const DNSName
target2("cname2.powerdns.com.");
1679 const DNSName
target3("cname3.powerdns.com.");
1680 const DNSName
target4("cname4.powerdns.com.");
1682 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 */) {
1685 if (isRootServer(address
)) {
1687 setLWResult(res
, 0, false, false, true);
1688 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1689 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1690 return LWResult::Result::Success
;
1692 if (address
== ComboAddress("192.0.2.1:53")) {
1694 if (domain
== target1
) {
1695 setLWResult(res
, 0, true, false, false);
1696 addRecordToLW(res
, domain
, QType::CNAME
, target2
.toString());
1697 return LWResult::Result::Success
;
1699 if (domain
== target2
) {
1700 setLWResult(res
, 0, true, false, false);
1701 addRecordToLW(res
, domain
, QType::CNAME
, target3
.toString());
1702 return LWResult::Result::Success
;
1704 if (domain
== target3
) {
1705 setLWResult(res
, 0, true, false, false);
1706 addRecordToLW(res
, domain
, QType::CNAME
, target4
.toString());
1707 return LWResult::Result::Success
;
1709 if (domain
== target4
) {
1710 setLWResult(res
, 0, true, false, false);
1711 addRecordToLW(res
, domain
, QType::CNAME
, target1
.toString());
1712 return LWResult::Result::Success
;
1715 return LWResult::Result::Success
;
1718 return LWResult::Result::Timeout
;
1721 vector
<DNSRecord
> ret
;
1722 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1723 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1724 BOOST_CHECK_EQUAL(ret
.size(), 0U);
1725 BOOST_CHECK_EQUAL(count
, 8U);
1727 // And again to check cache
1729 sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1732 catch (const ImmediateServFailException
& ex
) {
1737 BOOST_AUTO_TEST_CASE(test_cname_length
)
1739 std::unique_ptr
<SyncRes
> sr
;
1745 const DNSName
target("cname.powerdns.com.");
1747 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 */) {
1748 if (isRootServer(address
)) {
1750 setLWResult(res
, 0, false, false, true);
1751 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1752 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1753 return LWResult::Result::Success
;
1755 if (address
== ComboAddress("192.0.2.1:53")) {
1757 setLWResult(res
, 0, true, false, false);
1758 addRecordToLW(res
, domain
, QType::CNAME
, std::to_string(length
) + "-cname.powerdns.com");
1760 return LWResult::Result::Success
;
1763 return LWResult::Result::Timeout
;
1766 vector
<DNSRecord
> ret
;
1767 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1768 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1769 BOOST_CHECK_EQUAL(ret
.size(), length
);
1770 BOOST_CHECK_EQUAL(length
, SyncRes::s_max_CNAMES_followed
+ 1);
1773 BOOST_AUTO_TEST_CASE(test_cname_target_servfail
)
1775 std::unique_ptr
<SyncRes
> resolver
;
1780 const DNSName
target("cname.powerdns.com.");
1781 const DNSName
cnameTarget("cname-target.powerdns.com");
1783 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 */) {
1784 if (isRootServer(ipAddress
)) {
1785 setLWResult(res
, 0, false, false, true);
1786 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1787 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1788 return LWResult::Result::Success
;
1790 if (ipAddress
== ComboAddress("192.0.2.1:53")) {
1792 if (domain
== target
) {
1793 setLWResult(res
, 0, true, false, false);
1794 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1795 return LWResult::Result::Success
;
1797 if (domain
== cnameTarget
) {
1798 return LWResult::Result::PermanentError
;
1801 return LWResult::Result::Success
;
1804 return LWResult::Result::Timeout
;
1807 vector
<DNSRecord
> ret
;
1808 int res
= resolver
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1809 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1810 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1811 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1812 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1815 BOOST_AUTO_TEST_CASE(test_cname_target_servfail_servestale
)
1817 std::unique_ptr
<SyncRes
> resolver
;
1819 MemRecursorCache::s_maxServedStaleExtensions
= 1440;
1823 const DNSName
target("cname.powerdns.com.");
1824 const DNSName
cnameTarget("cname-target.powerdns.com");
1826 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 */) {
1827 if (isRootServer(ipAddress
)) {
1828 setLWResult(res
, 0, false, false, true);
1829 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1830 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1831 return LWResult::Result::Success
;
1833 if (ipAddress
== ComboAddress("192.0.2.1:53")) {
1835 if (domain
== target
) {
1836 setLWResult(res
, 0, true, false, false);
1837 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1838 return LWResult::Result::Success
;
1840 if (domain
== cnameTarget
) {
1841 return LWResult::Result::PermanentError
;
1844 return LWResult::Result::Success
;
1847 return LWResult::Result::Timeout
;
1850 vector
<DNSRecord
> ret
;
1851 int res
= resolver
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1852 // different compared no non-servestale case (returns ServFail), handled by pdns_recursor
1853 BOOST_CHECK_EQUAL(res
, -1);
1854 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1855 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1856 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1859 BOOST_AUTO_TEST_CASE(test_time_limit
)
1861 std::unique_ptr
<SyncRes
> sr
;
1867 const DNSName
target("cname.powerdns.com.");
1869 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 */) {
1872 if (isRootServer(address
)) {
1873 setLWResult(res
, 0, false, false, true);
1874 /* Pretend that this query took 2000 ms */
1877 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1878 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1879 return LWResult::Result::Success
;
1881 if (address
== ComboAddress("192.0.2.1:53")) {
1883 setLWResult(res
, 0, true, false, false);
1884 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1885 return LWResult::Result::Success
;
1888 return LWResult::Result::Timeout
;
1891 /* Set the maximum time to 1 ms */
1892 SyncRes::s_maxtotusec
= 1000;
1895 vector
<DNSRecord
> ret
;
1896 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1899 catch (const ImmediateServFailException
& e
) {
1901 BOOST_CHECK_EQUAL(queries
, 1U);
1904 BOOST_AUTO_TEST_CASE(test_dname_processing
)
1906 std::unique_ptr
<SyncRes
> sr
;
1911 const DNSName
dnameOwner("powerdns.com");
1912 const DNSName
dnameTarget("powerdns.net");
1914 const DNSName
target("dname.powerdns.com.");
1915 const DNSName
cnameTarget("dname.powerdns.net");
1917 const DNSName
uncachedTarget("dname-uncached.powerdns.com.");
1918 const DNSName
uncachedCNAMETarget("dname-uncached.powerdns.net.");
1920 const DNSName
synthCNAME("cname-uncached.powerdns.com.");
1921 const DNSName
synthCNAMETarget("cname-uncached.powerdns.net.");
1925 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 */) {
1928 if (isRootServer(address
)) {
1929 if (domain
.isPartOf(dnameOwner
)) {
1930 setLWResult(res
, 0, false, false, true);
1931 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1932 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1933 return LWResult::Result::Success
;
1935 if (domain
.isPartOf(dnameTarget
)) {
1936 setLWResult(res
, 0, false, false, true);
1937 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1938 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1939 return LWResult::Result::Success
;
1942 else if (address
== ComboAddress("192.0.2.1:53")) {
1943 if (domain
== target
) {
1944 setLWResult(res
, 0, true, false, false);
1945 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
1946 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1947 return LWResult::Result::Success
;
1950 else if (address
== ComboAddress("192.0.2.2:53")) {
1951 if (domain
== cnameTarget
) {
1952 setLWResult(res
, 0, true, false, false);
1953 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1955 if (domain
== uncachedCNAMETarget
) {
1956 setLWResult(res
, 0, true, false, false);
1957 addRecordToLW(res
, domain
, QType::A
, "192.0.2.3");
1959 return LWResult::Result::Success
;
1961 return LWResult::Result::Timeout
;
1964 vector
<DNSRecord
> ret
;
1965 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1967 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1968 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
1970 BOOST_CHECK_EQUAL(queries
, 4u);
1972 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1973 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1974 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1976 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
1977 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
1979 BOOST_CHECK(ret
[2].d_type
== QType::A
);
1980 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
1982 // Now check the cache
1984 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1986 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1987 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
1989 BOOST_CHECK_EQUAL(queries
, 4U);
1991 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1992 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1993 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1995 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
1996 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
1998 BOOST_CHECK(ret
[2].d_type
== QType::A
);
1999 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
2001 // Check if we correctly return a synthesized CNAME, should send out just 1 more query
2003 res
= sr
->beginResolve(uncachedTarget
, QType(QType::A
), QClass::IN
, ret
);
2005 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2006 BOOST_CHECK_EQUAL(queries
, 5U);
2008 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2009 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2010 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2012 BOOST_REQUIRE(ret
[1].d_type
== QType::CNAME
);
2013 BOOST_CHECK_EQUAL(ret
[1].d_name
, uncachedTarget
);
2014 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[1])->getTarget(), uncachedCNAMETarget
);
2016 BOOST_CHECK(ret
[2].d_type
== QType::A
);
2017 BOOST_CHECK_EQUAL(ret
[2].d_name
, uncachedCNAMETarget
);
2019 // Check if we correctly return the DNAME from cache when asked
2021 res
= sr
->beginResolve(dnameOwner
, QType(QType::DNAME
), QClass::IN
, ret
);
2022 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2023 BOOST_CHECK_EQUAL(queries
, 5U);
2025 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2026 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2027 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2029 // Check if we correctly return the synthesized CNAME from cache when asked
2031 res
= sr
->beginResolve(synthCNAME
, QType(QType::CNAME
), QClass::IN
, ret
);
2032 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2033 BOOST_CHECK_EQUAL(queries
, 5U);
2035 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2036 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2037 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2039 BOOST_REQUIRE(ret
[1].d_type
== QType::CNAME
);
2040 BOOST_CHECK(ret
[1].d_name
== synthCNAME
);
2041 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[1])->getTarget(), synthCNAMETarget
);
2044 BOOST_AUTO_TEST_CASE(test_dname_dnssec_secure
)
2046 std::unique_ptr
<SyncRes
> sr
;
2048 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
2052 const DNSName
dnameOwner("powerdns");
2053 const DNSName
dnameTarget("example");
2055 const DNSName
target("dname.powerdns");
2056 const DNSName
cnameTarget("dname.example");
2060 auto luaconfsCopy
= g_luaconfs
.getCopy();
2061 luaconfsCopy
.dsAnchors
.clear();
2062 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2063 generateKeyMaterial(dnameOwner
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2064 generateKeyMaterial(dnameTarget
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2065 g_luaconfs
.setState(luaconfsCopy
);
2069 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 */) {
2071 /* 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
2072 * As such, we need to do some more work to make the answers correct.
2075 if (isRootServer(address
)) {
2076 if (domain
.countLabels() == 0 && type
== QType::DNSKEY
) { // .|DNSKEY
2077 setLWResult(res
, 0, true, false, true);
2078 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2079 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2080 return LWResult::Result::Success
;
2082 if (domain
.countLabels() == 1 && type
== QType::DS
) { // powerdns|DS or example|DS
2083 setLWResult(res
, 0, true, false, true);
2084 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
2085 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2086 return LWResult::Result::Success
;
2088 // For the rest, delegate!
2089 if (domain
.isPartOf(dnameOwner
)) {
2090 setLWResult(res
, 0, false, false, true);
2091 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2092 addDS(dnameOwner
, 300, res
->d_records
, keys
);
2093 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2094 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2095 return LWResult::Result::Success
;
2097 if (domain
.isPartOf(dnameTarget
)) {
2098 setLWResult(res
, 0, false, false, true);
2099 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2100 addDS(dnameTarget
, 300, res
->d_records
, keys
);
2101 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2102 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2103 return LWResult::Result::Success
;
2106 else if (address
== ComboAddress("192.0.2.1:53")) {
2107 if (domain
.countLabels() == 1 && type
== QType::DNSKEY
) { // powerdns|DNSKEY
2108 setLWResult(res
, 0, true, false, true);
2109 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2110 addRRSIG(keys
, res
->d_records
, domain
, 300);
2111 return LWResult::Result::Success
;
2113 if (domain
== target
&& type
== QType::DS
) { // dname.powerdns|DS
2114 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
2116 if (domain
== target
) {
2117 setLWResult(res
, 0, true, false, false);
2118 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2119 addRRSIG(keys
, res
->d_records
, dnameOwner
, 300);
2120 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString()); // CNAME from a DNAME is not signed
2121 return LWResult::Result::Success
;
2124 else if (address
== ComboAddress("192.0.2.2:53")) {
2125 if (domain
.countLabels() == 1 && type
== QType::DNSKEY
) { // example|DNSKEY
2126 setLWResult(res
, 0, true, false, true);
2127 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2128 addRRSIG(keys
, res
->d_records
, domain
, 300);
2129 return LWResult::Result::Success
;
2131 if (domain
== cnameTarget
&& type
== QType::DS
) { // dname.example|DS
2132 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
2134 if (domain
== cnameTarget
) {
2135 setLWResult(res
, 0, true, false, false);
2136 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2137 addRRSIG(keys
, res
->d_records
, dnameTarget
, 300);
2139 return LWResult::Result::Success
;
2141 return LWResult::Result::Timeout
;
2144 vector
<DNSRecord
> ret
;
2145 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2147 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2148 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2149 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2151 BOOST_CHECK_EQUAL(queries
, 7U);
2153 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2154 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2155 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2157 BOOST_REQUIRE(ret
[1].d_type
== QType::RRSIG
);
2158 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2160 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2161 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2163 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2164 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2166 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2167 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2171 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2173 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2174 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2175 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2177 BOOST_CHECK_EQUAL(queries
, 7U);
2179 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2180 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2181 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2183 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2184 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2186 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2187 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2189 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2190 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2192 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2193 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2196 BOOST_AUTO_TEST_CASE(test_dname_plus_ns_dnssec_secure
)
2198 std::unique_ptr
<SyncRes
> sr
;
2200 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
2204 const DNSName
dnameOwner("powerdns");
2205 const DNSName
dnameTarget("example");
2207 const DNSName
target("dname.powerdns");
2208 const DNSName
cnameTarget("dname.example");
2212 auto luaconfsCopy
= g_luaconfs
.getCopy();
2213 luaconfsCopy
.dsAnchors
.clear();
2214 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2215 generateKeyMaterial(dnameTarget
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2216 g_luaconfs
.setState(luaconfsCopy
);
2220 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 */) {
2223 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
2224 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
2227 if (domain
.isPartOf(dnameOwner
)) {
2228 setLWResult(res
, 0, true, false, true);
2229 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2230 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2231 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString()); // CNAME from a DNAME is not signed
2233 addRecordToLW(res
, dnameTarget
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2234 addDS(dnameTarget
, 300, res
->d_records
, keys
);
2235 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2236 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2237 return LWResult::Result::Success
;
2239 if (domain
== cnameTarget
) {
2240 setLWResult(res
, 0, true, false, true);
2241 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2242 addRRSIG(keys
, res
->d_records
, dnameTarget
, 300);
2243 return LWResult::Result::Success
;
2245 return LWResult::Result::Timeout
;
2248 vector
<DNSRecord
> ret
;
2249 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2251 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2252 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2253 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2255 BOOST_CHECK_EQUAL(queries
, 4U);
2257 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2258 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2259 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2261 BOOST_REQUIRE(ret
[1].d_type
== QType::RRSIG
);
2262 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2264 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2265 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2267 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2268 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2270 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2271 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2275 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2277 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2278 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2279 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2281 BOOST_CHECK_EQUAL(queries
, 4U);
2283 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2284 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2285 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2287 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2288 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2290 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2291 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2293 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2294 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2296 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2297 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2300 BOOST_AUTO_TEST_CASE(test_dname_dnssec_insecure
)
2303 * The DNAME itself is signed, but the final A record is not
2305 std::unique_ptr
<SyncRes
> sr
;
2307 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
2311 const DNSName
dnameOwner("powerdns");
2312 const DNSName
dnameTarget("example");
2314 const DNSName
target("dname.powerdns");
2315 const DNSName
cnameTarget("dname.example");
2319 auto luaconfsCopy
= g_luaconfs
.getCopy();
2320 luaconfsCopy
.dsAnchors
.clear();
2321 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2322 generateKeyMaterial(dnameOwner
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2323 g_luaconfs
.setState(luaconfsCopy
);
2327 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 */) {
2330 if (isRootServer(address
)) {
2331 if (domain
.countLabels() == 0 && type
== QType::DNSKEY
) { // .|DNSKEY
2332 setLWResult(res
, 0, true, false, true);
2333 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2334 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2335 return LWResult::Result::Success
;
2337 if (domain
== dnameOwner
&& type
== QType::DS
) { // powerdns|DS
2338 setLWResult(res
, 0, true, false, true);
2339 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
2340 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2341 return LWResult::Result::Success
;
2343 if (domain
== dnameTarget
&& type
== QType::DS
) { // example|DS
2344 return genericDSAndDNSKEYHandler(res
, domain
, DNSName("."), type
, keys
);
2346 // For the rest, delegate!
2347 if (domain
.isPartOf(dnameOwner
)) {
2348 setLWResult(res
, 0, false, false, true);
2349 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2350 addDS(dnameOwner
, 300, res
->d_records
, keys
);
2351 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2352 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2353 return LWResult::Result::Success
;
2355 if (domain
.isPartOf(dnameTarget
)) {
2356 setLWResult(res
, 0, false, false, true);
2357 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2358 addDS(dnameTarget
, 300, res
->d_records
, keys
);
2359 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2360 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2361 return LWResult::Result::Success
;
2364 else if (address
== ComboAddress("192.0.2.1:53")) {
2365 if (domain
.countLabels() == 1 && type
== QType::DNSKEY
) { // powerdns|DNSKEY
2366 setLWResult(res
, 0, true, false, true);
2367 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2368 addRRSIG(keys
, res
->d_records
, domain
, 300);
2369 return LWResult::Result::Success
;
2371 if (domain
== target
&& type
== QType::DS
) { // dname.powerdns|DS
2372 return genericDSAndDNSKEYHandler(res
, domain
, dnameOwner
, type
, keys
, false);
2374 if (domain
== target
) {
2375 setLWResult(res
, 0, true, false, false);
2376 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2377 addRRSIG(keys
, res
->d_records
, dnameOwner
, 300);
2378 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString()); // CNAME from a DNAME is not signed
2379 return LWResult::Result::Success
;
2382 else if (address
== ComboAddress("192.0.2.2:53")) {
2383 if (domain
== target
&& type
== QType::DS
) { // dname.example|DS
2384 return genericDSAndDNSKEYHandler(res
, domain
, dnameTarget
, type
, keys
, false);
2386 if (domain
== cnameTarget
) {
2387 setLWResult(res
, 0, true, false, false);
2388 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2390 return LWResult::Result::Success
;
2392 return LWResult::Result::Timeout
;
2395 vector
<DNSRecord
> ret
;
2396 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2398 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2399 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
2400 BOOST_REQUIRE_EQUAL(ret
.size(), 4U); /* DNAME + RRSIG(DNAME) + CNAME + A */
2402 BOOST_CHECK_EQUAL(queries
, 7U);
2404 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2405 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2406 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2408 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2409 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2411 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2412 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2414 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2415 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2419 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2421 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2422 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
2423 BOOST_REQUIRE_EQUAL(ret
.size(), 4U); /* DNAME + RRSIG(DNAME) + CNAME + A */
2425 BOOST_CHECK_EQUAL(queries
, 7U);
2427 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2428 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2429 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2431 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2432 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2434 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2435 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2437 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2438 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2441 BOOST_AUTO_TEST_CASE(test_dname_processing_no_CNAME
)
2443 std::unique_ptr
<SyncRes
> sr
;
2448 const DNSName
dnameOwner("powerdns.com");
2449 const DNSName
dnameTarget("powerdns.net");
2451 const DNSName
target("dname.powerdns.com.");
2452 const DNSName
cnameTarget("dname.powerdns.net");
2456 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 */) {
2459 if (isRootServer(address
)) {
2460 if (domain
.isPartOf(dnameOwner
)) {
2461 setLWResult(res
, 0, false, false, true);
2462 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2463 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2464 return LWResult::Result::Success
;
2466 if (domain
.isPartOf(dnameTarget
)) {
2467 setLWResult(res
, 0, false, false, true);
2468 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2469 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2470 return LWResult::Result::Success
;
2473 else if (address
== ComboAddress("192.0.2.1:53")) {
2474 if (domain
== target
) {
2475 setLWResult(res
, 0, true, false, false);
2476 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2477 // No CNAME, recursor should synth
2478 return LWResult::Result::Success
;
2481 else if (address
== ComboAddress("192.0.2.2:53")) {
2482 if (domain
== cnameTarget
) {
2483 setLWResult(res
, 0, true, false, false);
2484 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2486 return LWResult::Result::Success
;
2488 return LWResult::Result::Timeout
;
2491 vector
<DNSRecord
> ret
;
2492 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2494 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2495 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
2497 BOOST_CHECK_EQUAL(queries
, 4U);
2499 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2500 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2501 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2503 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
2504 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
2506 BOOST_CHECK(ret
[2].d_type
== QType::A
);
2507 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
2509 // Now check the cache
2511 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2513 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2514 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
2516 BOOST_CHECK_EQUAL(queries
, 4U);
2518 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2519 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2520 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2522 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
2523 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
2525 BOOST_CHECK(ret
[2].d_type
== QType::A
);
2526 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
2530 // cerr<<"asyncresolve called to ask "<<ip.toStringWithPort()<<" about "<<domain.toString()<<" / "<<QType(type).getName()<<" over "<<(doTCP ? "TCP" : "UDP")<<" (rd: "<<sendRDQuery<<", EDNS0 level: "<<EDNS0Level<<")"<<endl;
2532 - check out of band support
2538 BOOST_AUTO_TEST_CASE(test_glued_referral_child_ns_set_wrong
)
2540 std::unique_ptr
<SyncRes
> sr
;
2545 const DNSName
target("powerdns.com.");
2547 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 */) {
2548 /* this will cause issue with qname minimization if we ever implement it */
2549 if (domain
!= target
) {
2550 return LWResult::Result::Timeout
;
2553 if (isRootServer(address
)) {
2554 setLWResult(res
, 0, false, false, true);
2555 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2556 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2557 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
2558 return LWResult::Result::Success
;
2560 if (address
== ComboAddress("192.0.2.1:53") || address
== ComboAddress("[2001:DB8::1]:53")) {
2561 setLWResult(res
, 0, false, false, true);
2562 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
2563 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
2564 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
2565 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
2566 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
2567 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
2568 return LWResult::Result::Success
;
2570 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")) {
2572 if (type
== QType::A
) {
2573 setLWResult(res
, 0, true, false, true);
2574 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
2575 return LWResult::Result::Success
;
2577 if (type
== QType::NS
) {
2578 setLWResult(res
, 0, true, false, true);
2579 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-nsX1.powerdns.com.", DNSResourceRecord::ANSWER
, 172800);
2580 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-nsX2.powerdns.com.", DNSResourceRecord::ANSWER
, 172800);
2581 addRecordToLW(res
, "pdns-public-nsX1.powerdns.com.", QType::A
, "192.0.2.11", DNSResourceRecord::ADDITIONAL
, 172800);
2582 addRecordToLW(res
, "pdns-public-nsX1.powerdns.com.", QType::AAAA
, "2001:DB8::11", DNSResourceRecord::ADDITIONAL
, 172800);
2583 addRecordToLW(res
, "pdns-public-nsX2.powerdns.com.", QType::A
, "192.0.2.12", DNSResourceRecord::ADDITIONAL
, 172800);
2584 addRecordToLW(res
, "pdns-public-nsX2.powerdns.com.", QType::AAAA
, "2001:DB8::12", DNSResourceRecord::ADDITIONAL
, 172800);
2585 return LWResult::Result::Success
;
2587 return LWResult::Result::Timeout
;
2589 return LWResult::Result::Timeout
;
2592 vector
<DNSRecord
> ret
;
2593 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2594 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2595 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
2596 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2597 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
2599 // Now resolve NS to get auth NS set in cache and save the parent NS set
2601 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
2602 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2603 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
2604 BOOST_CHECK(ret
[0].d_type
== QType::NS
);
2605 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
2606 BOOST_CHECK_EQUAL(SyncRes::getSaveParentsNSSetsSize(), 1U);
2608 g_recCache
->doWipeCache(target
, false, QType::A
);
2609 SyncRes::s_save_parent_ns_set
= false;
2611 // Try to resolve now via the broken child NS set... should not work
2613 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2614 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
2615 BOOST_REQUIRE_EQUAL(ret
.size(), 0U);
2617 SyncRes::s_save_parent_ns_set
= true;
2619 // Try to resolve now via the broken child... should work now via fallback to parent NS set
2621 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2622 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2623 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
2624 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2625 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
2628 BOOST_AUTO_TEST_SUITE_END()