1 #define BOOST_TEST_DYN_LINK
2 #include <boost/test/unit_test.hpp>
4 #include "test-syncres_cc.hh"
5 #include "taskqueue.hh"
6 #include "rec-taskqueue.hh"
8 BOOST_AUTO_TEST_SUITE(syncres_cc1
)
10 BOOST_AUTO_TEST_CASE(test_root_primed
)
12 std::unique_ptr
<SyncRes
> sr
;
17 const DNSName
target("a.root-servers.net.");
19 /* we are primed, but only with non-auth data so we cannot resolve A a.root-servers.net. without any query */
20 vector
<DNSRecord
> ret
;
21 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
22 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
23 BOOST_REQUIRE_EQUAL(ret
.size(), 0U);
26 res
= sr
->beginResolve(target
, QType(QType::AAAA
), QClass::IN
, ret
);
27 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
28 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Indeterminate
);
29 BOOST_REQUIRE_EQUAL(ret
.size(), 0U);
32 catch (const ImmediateServFailException
) {
37 BOOST_AUTO_TEST_CASE(test_root_primed_ns
)
39 std::unique_ptr
<SyncRes
> sr
;
43 const DNSName
target(".");
45 /* we are primed, but we should not be able to NS . without any query
46 because the . NS entry is not stored as authoritative */
48 size_t queriesCount
= 0;
50 sr
->setAsyncCallback([target
, &queriesCount
](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
53 if (domain
== target
&& type
== QType::NS
) {
55 setLWResult(res
, 0, true, false, true);
56 char addr
[] = "a.root-servers.net.";
57 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
59 addRecordToLW(res
, g_rootdnsname
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
62 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
63 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
65 return LWResult::Result::Success
;
68 return LWResult::Result::Timeout
;
71 vector
<DNSRecord
> ret
;
72 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
73 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
74 BOOST_REQUIRE_EQUAL(ret
.size(), 13U);
75 BOOST_CHECK_EQUAL(queriesCount
, 1U);
78 BOOST_AUTO_TEST_CASE(test_root_not_primed
)
80 std::unique_ptr
<SyncRes
> sr
;
83 size_t queriesCount
= 0;
85 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
88 if (domain
== g_rootdnsname
&& type
== QType::NS
) {
89 setLWResult(res
, 0, true, false, true);
90 addRecordToLW(res
, g_rootdnsname
, QType::NS
, "a.root-servers.net.", DNSResourceRecord::ANSWER
, 3600);
91 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
92 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
94 return LWResult::Result::Success
;
97 return LWResult::Result::Timeout
;
100 /* we are not primed yet, so SyncRes will have to call primeHints()
101 then call getRootNS(), for which at least one of the root servers needs to answer */
102 vector
<DNSRecord
> ret
;
103 int res
= sr
->beginResolve(DNSName("."), QType(QType::NS
), QClass::IN
, ret
);
104 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
105 BOOST_CHECK_EQUAL(ret
.size(), 1U);
106 BOOST_CHECK_EQUAL(queriesCount
, 2U);
109 BOOST_AUTO_TEST_CASE(test_root_not_primed_and_no_response
)
111 std::unique_ptr
<SyncRes
> sr
;
113 // We expect an error, do not log it
114 g_log
.toConsole(Logger::Critical
);
115 std::set
<ComboAddress
> downServers
;
117 /* we are not primed yet, so SyncRes will have to call primeHints()
118 then call getRootNS(), for which at least one of the root servers needs to answer.
119 None will, so it should ServFail.
121 sr
->setAsyncCallback([&downServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* /* res */, bool* /* chained */) {
122 downServers
.insert(ip
);
123 return LWResult::Result::Timeout
;
126 vector
<DNSRecord
> ret
;
127 int res
= sr
->beginResolve(DNSName("."), QType(QType::NS
), QClass::IN
, ret
);
128 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
129 BOOST_CHECK_EQUAL(ret
.size(), 0U);
130 BOOST_CHECK(downServers
.size() > 0);
131 /* we explicitly refuse to mark the root servers down */
132 for (const auto& server
: downServers
) {
133 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 0U);
137 BOOST_AUTO_TEST_CASE(test_root_ns_poison_resistance
)
139 std::unique_ptr
<SyncRes
> sr
;
143 const DNSName
target("www.example.com.");
145 sr
->setAsyncCallback([target
](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
146 if (domain
== g_rootdnsname
&& type
== QType::NS
) {
148 setLWResult(res
, 0, true, false, true);
149 char addr
[] = "a.root-servers.net.";
150 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
152 addRecordToLW(res
, g_rootdnsname
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
155 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
156 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
158 return LWResult::Result::Success
;
161 if (domain
== target
&& type
== QType::A
) {
163 setLWResult(res
, 0, true, false, true);
164 addRecordToLW(res
, target
, QType::A
, "1.2.3.4", DNSResourceRecord::ANSWER
, 3600);
166 addRecordToLW(res
, ".", QType::NS
, "poison.name.", DNSResourceRecord::AUTHORITY
, 3600);
167 addRecordToLW(res
, "poison.name", QType::A
, "4.5.6.7", DNSResourceRecord::ADDITIONAL
, 3600);
169 return LWResult::Result::Success
;
172 return LWResult::Result::Timeout
;
175 vector
<DNSRecord
> ret
;
176 // Check we have 13 root servers
177 int res
= sr
->beginResolve(g_rootdnsname
, QType(QType::NS
), QClass::IN
, ret
);
178 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
179 BOOST_REQUIRE_EQUAL(ret
.size(), 13U);
183 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
184 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
185 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
187 // Still should have 13
189 res
= sr
->beginResolve(g_rootdnsname
, QType(QType::NS
), QClass::IN
, ret
);
190 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
191 BOOST_REQUIRE_EQUAL(ret
.size(), 13U);
194 BOOST_AUTO_TEST_CASE(test_root_primed_ns_update
)
196 std::unique_ptr
<SyncRes
> sr
;
200 const DNSName
target(".");
201 const DNSName
aroot("a.root-servers.net.");
202 const string newA
= "1.2.3.4";
203 const string newAAAA
= "1::2";
205 /* we are primed, but we should not be able to NS . without any query
206 because the . NS entry is not stored as authoritative */
208 size_t queriesCount
= 0;
210 auto asynccb
= [target
, &queriesCount
, aroot
, newA
, newAAAA
](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
213 if (domain
== target
&& type
== QType::NS
) {
215 setLWResult(res
, 0, true, false, true);
216 char addr
[] = "a.root-servers.net.";
217 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
219 addRecordToLW(res
, g_rootdnsname
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
222 addRecordToLW(res
, aroot
.toString(), QType::A
, newA
, DNSResourceRecord::ADDITIONAL
, 3600);
223 addRecordToLW(res
, aroot
.toString(), QType::AAAA
, newAAAA
, DNSResourceRecord::ADDITIONAL
, 3600);
225 return LWResult::Result::Success
;
227 return LWResult::Result::Timeout
;
230 sr
->setAsyncCallback(asynccb
);
233 Utility::gettimeofday(&now
, nullptr);
235 vector
<DNSRecord
> ret
;
236 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
237 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
238 BOOST_REQUIRE_EQUAL(ret
.size(), 13U);
239 BOOST_CHECK_EQUAL(queriesCount
, 1U);
242 time_t cached
= g_recCache
->get(now
.tv_sec
, aroot
, QType::A
, MemRecursorCache::None
, &ret
, ComboAddress());
243 BOOST_CHECK(cached
> 0);
244 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
245 BOOST_CHECK(getRR
<ARecordContent
>(ret
[0])->getCA() == ComboAddress(newA
));
248 cached
= g_recCache
->get(now
.tv_sec
, aroot
, QType::AAAA
, MemRecursorCache::None
, &ret
, ComboAddress());
249 BOOST_CHECK(cached
> 0);
250 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
251 BOOST_CHECK(getRR
<AAAARecordContent
>(ret
[0])->getCA() == ComboAddress(newAAAA
));
254 static void test_edns_formerr_fallback_f(bool sample
)
256 std::unique_ptr
<SyncRes
> sr
;
259 sr
->setQNameMinimization();
261 ComboAddress noEDNSServer
;
262 size_t queriesWithEDNS
= 0;
263 size_t queriesWithoutEDNS
= 0;
265 sr
->setAsyncCallback([&queriesWithEDNS
, &queriesWithoutEDNS
, &noEDNSServer
, sample
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool /* sendRDQuery */, int EDNS0Level
, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
266 if (EDNS0Level
!= 0) {
270 setLWResult(res
, RCode::FormErr
);
271 return LWResult::Result::Success
;
274 queriesWithoutEDNS
++;
276 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& !doTCP
) {
277 setLWResult(res
, 0, true, false, false);
278 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
279 return LWResult::Result::Success
;
282 return sample
? basicRecordsForQnameMinimization(res
, domain
, type
) : LWResult::Result::Timeout
;
287 /* fake that the root NS doesn't handle EDNS, check that we fallback */
288 vector
<DNSRecord
> ret
;
289 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
290 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
291 BOOST_CHECK_EQUAL(ret
.size(), 1U);
292 BOOST_CHECK_EQUAL(queriesWithEDNS
, sample
? 3U : 1U);
293 BOOST_CHECK_EQUAL(queriesWithoutEDNS
, sample
? 4U : 1U);
294 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), sample
? 3U : 1U);
295 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(noEDNSServer
), SyncRes::EDNSStatus::NOEDNS
);
298 BOOST_AUTO_TEST_CASE(test_edns_formerr_fallback
)
300 test_edns_formerr_fallback_f(false);
303 BOOST_AUTO_TEST_CASE(test_edns_formerr_fallback_qmin
)
305 // DISABLED UNTIL QNAME MINIMIZATION IS THERE
307 test_edns_formerr_fallback_f(true);
310 BOOST_AUTO_TEST_CASE(test_edns_formerr_but_edns_enabled
)
312 std::unique_ptr
<SyncRes
> sr
;
315 /* in this test, the auth answers with FormErr to an EDNS-enabled
316 query, but the response does contain EDNS so we should not mark
317 it as EDNS ignorant or intolerant.
319 size_t queriesWithEDNS
= 0;
320 size_t queriesWithoutEDNS
= 0;
321 std::set
<ComboAddress
> usedServers
;
323 sr
->setAsyncCallback([&queriesWithEDNS
, &queriesWithoutEDNS
, &usedServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int type
, bool /* doTCP */, bool /* sendRDQuery */, int EDNS0Level
, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
324 if (EDNS0Level
> 0) {
328 queriesWithoutEDNS
++;
330 usedServers
.insert(ip
);
332 if (type
== QType::DNAME
) {
333 setLWResult(res
, RCode::FormErr
);
334 if (EDNS0Level
> 0) {
335 res
->d_haveEDNS
= true;
337 return LWResult::Result::Success
;
340 return LWResult::Result::Timeout
;
345 vector
<DNSRecord
> ret
;
346 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::DNAME
), QClass::IN
, ret
);
347 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
348 BOOST_CHECK_EQUAL(ret
.size(), 0U);
349 BOOST_CHECK_EQUAL(queriesWithEDNS
, 26U);
350 BOOST_CHECK_EQUAL(queriesWithoutEDNS
, 0U);
351 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), 0U);
352 BOOST_CHECK_EQUAL(usedServers
.size(), 26U);
353 for (const auto& server
: usedServers
) {
354 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
358 BOOST_AUTO_TEST_CASE(test_meta_types
)
360 std::unique_ptr
<SyncRes
> sr
;
363 static const std::set
<uint16_t> invalidTypes
= {128, QType::AXFR
, QType::IXFR
, QType::RRSIG
, QType::NSEC3
, QType::OPT
, QType::TSIG
, QType::TKEY
, QType::MAILA
, QType::MAILB
, 65535};
365 for (const auto qtype
: invalidTypes
) {
366 size_t queriesCount
= 0;
368 sr
->setAsyncCallback([&queriesCount
](const ComboAddress
& /* ip */, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* /* res */, bool* /* chained */) {
370 return LWResult::Result::Timeout
;
375 vector
<DNSRecord
> ret
;
376 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(qtype
), QClass::IN
, ret
);
377 BOOST_CHECK_EQUAL(res
, -1);
378 BOOST_CHECK_EQUAL(ret
.size(), 0U);
379 BOOST_CHECK_EQUAL(queriesCount
, 0U);
383 BOOST_AUTO_TEST_CASE(test_tc_fallback_to_tcp
)
385 std::unique_ptr
<SyncRes
> sr
;
388 sr
->setAsyncCallback([](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool doTCP
, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
390 setLWResult(res
, 0, false, true, false);
391 return LWResult::Result::Success
;
393 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& doTCP
) {
394 setLWResult(res
, 0, true, false, false);
395 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
396 return LWResult::Result::Success
;
399 return LWResult::Result::Timeout
;
404 /* fake that the NS truncates every request over UDP, we should fallback to TCP */
405 vector
<DNSRecord
> ret
;
406 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
407 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
410 BOOST_AUTO_TEST_CASE(test_tc_over_tcp
)
412 std::unique_ptr
<SyncRes
> sr
;
415 size_t tcpQueriesCount
= 0;
417 sr
->setAsyncCallback([&tcpQueriesCount
](const ComboAddress
& /* ip */, const DNSName
& domain
, int /* type */, bool doTCP
, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
419 setLWResult(res
, 0, true, true, false);
420 return LWResult::Result::Success
;
423 /* first TCP query is answered with a TC response */
425 if (tcpQueriesCount
== 1) {
426 setLWResult(res
, 0, true, true, false);
429 setLWResult(res
, 0, true, false, false);
432 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
433 return LWResult::Result::Success
;
438 vector
<DNSRecord
> ret
;
439 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
440 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
441 BOOST_CHECK_EQUAL(tcpQueriesCount
, 2U);
444 BOOST_AUTO_TEST_CASE(test_all_nss_down
)
446 std::unique_ptr
<SyncRes
> sr
;
448 std::set
<ComboAddress
> downServers
;
452 sr
->setAsyncCallback([&downServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
453 if (isRootServer(ip
)) {
454 setLWResult(res
, 0, false, false, true);
455 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
456 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
457 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
458 return LWResult::Result::Success
;
460 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
461 setLWResult(res
, 0, false, false, true);
462 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
463 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
464 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
465 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
466 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
467 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
468 return LWResult::Result::Success
;
471 downServers
.insert(ip
);
472 return LWResult::Result::Timeout
;
476 DNSName
target("powerdns.com.");
478 vector
<DNSRecord
> ret
;
479 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
480 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
481 BOOST_CHECK_EQUAL(ret
.size(), 0U);
482 BOOST_CHECK_EQUAL(downServers
.size(), 4U);
484 time_t now
= sr
->getNow().tv_sec
;
485 for (const auto& server
: downServers
) {
486 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1U);
487 BOOST_CHECK(SyncRes::isThrottled(now
, server
, target
, QType::A
));
491 BOOST_AUTO_TEST_CASE(test_all_nss_network_error
)
493 std::unique_ptr
<SyncRes
> sr
;
495 std::set
<ComboAddress
> downServers
;
499 sr
->setAsyncCallback([&downServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
500 if (isRootServer(ip
)) {
501 setLWResult(res
, 0, false, false, true);
502 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
503 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
504 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
505 return LWResult::Result::Success
;
507 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
508 setLWResult(res
, 0, false, false, true);
509 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
510 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
511 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
512 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
513 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
514 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
515 return LWResult::Result::Success
;
518 downServers
.insert(ip
);
519 return LWResult::Result::Timeout
;
523 /* exact same test than the previous one, except instead of a time out we fake a network error */
524 DNSName
target("powerdns.com.");
526 vector
<DNSRecord
> ret
;
527 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
528 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
529 BOOST_CHECK_EQUAL(ret
.size(), 0U);
530 BOOST_CHECK_EQUAL(downServers
.size(), 4U);
532 time_t now
= sr
->getNow().tv_sec
;
533 for (const auto& server
: downServers
) {
534 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1U);
535 BOOST_CHECK(SyncRes::isThrottled(now
, server
, target
, QType::A
));
539 BOOST_AUTO_TEST_CASE(test_all_nss_send_tc_then_garbage_over_tcp
)
541 std::unique_ptr
<SyncRes
> sr
;
546 std::set
<ComboAddress
> downServers
;
548 sr
->setAsyncCallback([&downServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int /* type */, bool doTCP
, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
549 if (isRootServer(ip
)) {
550 setLWResult(res
, 0, false, false, true);
551 addRecordToLW(res
, "lock-up.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
552 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
553 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
554 return LWResult::Result::Success
;
558 setLWResult(res
, 0, false, true, false);
559 return LWResult::Result::Success
;
562 downServers
.insert(ip
);
564 setLWResult(res
, RCode::FormErr
, false, false, false);
565 res
->d_validpacket
= false;
566 return LWResult::Result::Success
;
570 DNSName
target("www.lock-up.");
572 vector
<DNSRecord
> ret
;
573 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
574 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
575 BOOST_CHECK_EQUAL(ret
.size(), 0U);
576 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
578 for (const auto& server
: downServers
) {
579 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
580 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 1000000U);
584 BOOST_AUTO_TEST_CASE(test_all_nss_send_garbage_over_udp
)
586 std::unique_ptr
<SyncRes
> sr
;
591 std::set
<ComboAddress
> downServers
;
592 size_t queriesCount
= 0;
594 sr
->setAsyncCallback([&queriesCount
, &downServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
595 if (isRootServer(ip
)) {
596 setLWResult(res
, 0, false, false, true);
597 addRecordToLW(res
, "lock-up.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
598 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
599 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
600 return LWResult::Result::Success
;
604 downServers
.insert(ip
);
606 setLWResult(res
, RCode::FormErr
, false, false, false);
607 res
->d_validpacket
= false;
608 return LWResult::Result::Success
;
611 DNSName
target("www.lock-up.");
613 vector
<DNSRecord
> ret
;
614 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
615 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
616 BOOST_CHECK_EQUAL(ret
.size(), 0U);
617 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
618 /* two queries with EDNS, that's it */
619 BOOST_CHECK_EQUAL(queriesCount
, 2U);
621 for (const auto& server
: downServers
) {
622 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
623 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 1000000U);
624 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSIGNORANT
);
628 BOOST_AUTO_TEST_CASE(test_regular_ns_send_refused
)
630 std::unique_ptr
<SyncRes
> sr
;
635 std::set
<ComboAddress
> downServers
;
636 size_t queriesCount
= 0;
638 sr
->setAsyncCallback([&queriesCount
, &downServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
639 if (isRootServer(ip
)) {
640 setLWResult(res
, 0, false, false, true);
641 addRecordToLW(res
, "refused.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
642 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
643 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
644 return LWResult::Result::Success
;
648 downServers
.insert(ip
);
650 setLWResult(res
, RCode::Refused
, false, false, true);
652 return LWResult::Result::Success
;
655 DNSName
target("www.refused.");
657 vector
<DNSRecord
> ret
;
658 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
659 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
660 BOOST_CHECK_EQUAL(ret
.size(), 0U);
661 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
662 BOOST_CHECK_EQUAL(queriesCount
, 2U);
664 for (const auto& server
: downServers
) {
665 /* same as any other server */
666 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
667 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 0U);
668 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
672 BOOST_AUTO_TEST_CASE(test_forward_ns_send_refused
)
674 std::unique_ptr
<SyncRes
> sr
;
679 std::set
<ComboAddress
> downServers
;
680 size_t queriesCount
= 0;
682 const DNSName
target("www.refused.");
684 SyncRes::AuthDomain ad
;
685 const std::vector
<ComboAddress
> forwardedNSs
{ComboAddress("192.0.2.42:53"), ComboAddress("192.0.2.43:53")};
686 ad
.d_rdForward
= false;
687 ad
.d_servers
= forwardedNSs
;
688 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
690 sr
->setAsyncCallback([&queriesCount
, &downServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
691 if (isRootServer(ip
)) {
692 setLWResult(res
, 0, false, false, true);
693 addRecordToLW(res
, "refused.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
694 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
695 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
696 return LWResult::Result::Success
;
700 downServers
.insert(ip
);
702 setLWResult(res
, RCode::Refused
, false, false, true);
704 return LWResult::Result::Success
;
707 vector
<DNSRecord
> ret
;
708 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
709 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
710 BOOST_CHECK_EQUAL(ret
.size(), 0U);
711 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
712 BOOST_CHECK_EQUAL(queriesCount
, 2U);
714 for (const auto& server
: forwardedNSs
) {
715 BOOST_CHECK_EQUAL(downServers
.count(server
), 1U);
716 /* same as any other server */
717 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
718 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 0U);
719 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
723 BOOST_AUTO_TEST_CASE(test_forward_ns_send_servfail
)
725 std::unique_ptr
<SyncRes
> sr
;
730 std::set
<ComboAddress
> downServers
;
731 size_t queriesCount
= 0;
733 const DNSName
target("www.refused.");
735 SyncRes::AuthDomain ad
;
736 const std::vector
<ComboAddress
> forwardedNSs
{ComboAddress("192.0.2.42:53"), ComboAddress("192.0.2.43:53")};
737 ad
.d_rdForward
= false;
738 ad
.d_servers
= forwardedNSs
;
739 (*SyncRes::t_sstorage
.domainmap
)[DNSName("refused.")] = ad
;
741 sr
->setAsyncCallback([&queriesCount
, &downServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
742 if (isRootServer(ip
)) {
743 setLWResult(res
, 0, false, false, true);
744 addRecordToLW(res
, "refused.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
745 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
746 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
747 return LWResult::Result::Success
;
751 downServers
.insert(ip
);
753 setLWResult(res
, RCode::ServFail
, false, false, true);
755 return LWResult::Result::Success
;
758 vector
<DNSRecord
> ret
;
759 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
760 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
761 BOOST_CHECK_EQUAL(ret
.size(), 0U);
762 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
763 BOOST_CHECK_EQUAL(queriesCount
, 2U);
765 for (const auto& server
: forwardedNSs
) {
766 BOOST_CHECK_EQUAL(downServers
.count(server
), 1U);
767 /* on servfail from a server we forward to we only increase the NS speed so
768 that a different server might be tried instead, but we don't throttle */
769 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
770 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName(server
.toStringWithPort()), server
), 1000000U);
771 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
775 BOOST_AUTO_TEST_CASE(test_only_one_ns_up_resolving_itself_with_glue
)
777 std::unique_ptr
<SyncRes
> sr
;
782 DNSName
target("www.powerdns.com.");
784 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
785 if (isRootServer(ip
)) {
786 setLWResult(res
, 0, false, false, true);
787 if (domain
== target
) {
788 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
789 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.net.", DNSResourceRecord::AUTHORITY
, 172800);
790 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
791 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
793 else if (domain
== DNSName("pdns-public-ns2.powerdns.net.")) {
794 addRecordToLW(res
, "powerdns.net.", QType::NS
, "pdns-public-ns2.powerdns.net.", DNSResourceRecord::AUTHORITY
, 172800);
795 addRecordToLW(res
, "powerdns.net.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
796 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
797 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
799 return LWResult::Result::Success
;
801 else if (ip
== ComboAddress("192.0.2.3:53")) {
802 setLWResult(res
, 0, true, false, true);
803 if (domain
== DNSName("pdns-public-ns2.powerdns.net.")) {
804 if (type
== QType::A
) {
805 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::A
, "192.0.2.3");
807 else if (type
== QType::AAAA
) {
808 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::AAAA
, "2001:DB8::3");
811 else if (domain
== target
) {
812 if (type
== QType::A
) {
813 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
815 else if (type
== QType::AAAA
) {
816 addRecordToLW(res
, domain
, QType::AAAA
, "2001:DB8::1");
819 return LWResult::Result::Success
;
821 return LWResult::Result::Timeout
;
824 vector
<DNSRecord
> ret
;
825 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
826 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
827 BOOST_CHECK_EQUAL(ret
.size(), 1U);
830 BOOST_AUTO_TEST_CASE(test_os_limit_errors
)
832 std::unique_ptr
<SyncRes
> sr
;
834 std::set
<ComboAddress
> downServers
;
838 sr
->setAsyncCallback([&downServers
](const ComboAddress
& ip
, const DNSName
& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
839 if (isRootServer(ip
)) {
840 setLWResult(res
, 0, false, false, true);
841 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
842 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
843 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
844 return LWResult::Result::Success
;
846 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
847 setLWResult(res
, 0, false, false, true);
848 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
849 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
850 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
851 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
852 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
853 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
854 return LWResult::Result::Success
;
857 if (downServers
.size() < 3) {
858 /* only the last one will answer */
859 downServers
.insert(ip
);
860 return LWResult::Result::OSLimitError
;
863 setLWResult(res
, 0, true, false, true);
864 addRecordToLW(res
, "powerdns.com.", QType::A
, "192.0.2.42");
865 return LWResult::Result::Success
;
870 DNSName
target("powerdns.com.");
872 vector
<DNSRecord
> ret
;
873 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
874 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
875 BOOST_CHECK_EQUAL(ret
.size(), 1U);
876 BOOST_CHECK_EQUAL(downServers
.size(), 3U);
878 /* Error is reported as "OS limit error" (-2) so the servers should _NOT_ be marked down */
879 time_t now
= sr
->getNow().tv_sec
;
880 for (const auto& server
: downServers
) {
881 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 0U);
882 BOOST_CHECK(!SyncRes::isThrottled(now
, server
, target
, QType::A
));
886 BOOST_AUTO_TEST_CASE(test_glued_referral
)
888 std::unique_ptr
<SyncRes
> sr
;
893 const DNSName
target("powerdns.com.");
895 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
896 /* this will cause issue with qname minimization if we ever implement it */
897 if (domain
!= target
) {
898 return LWResult::Result::Timeout
;
901 if (isRootServer(ip
)) {
902 setLWResult(res
, 0, false, false, true);
903 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
904 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
905 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
906 return LWResult::Result::Success
;
908 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
909 setLWResult(res
, 0, false, false, true);
910 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
911 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
912 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
913 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
914 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
915 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
916 return LWResult::Result::Success
;
918 else if (ip
== ComboAddress("192.0.2.2:53") || ip
== ComboAddress("192.0.2.3:53") || ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("[2001:DB8::3]:53")) {
919 setLWResult(res
, 0, true, false, true);
920 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
921 return LWResult::Result::Success
;
924 return LWResult::Result::Timeout
;
928 vector
<DNSRecord
> ret
;
929 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
930 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
931 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
932 BOOST_CHECK(ret
[0].d_type
== QType::A
);
933 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
936 BOOST_AUTO_TEST_CASE(test_glueless_referral
)
938 std::unique_ptr
<SyncRes
> sr
;
943 const DNSName
target("powerdns.com.");
945 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
946 if (isRootServer(ip
)) {
947 setLWResult(res
, 0, false, false, true);
949 if (domain
.isPartOf(DNSName("com."))) {
950 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
952 else if (domain
.isPartOf(DNSName("org."))) {
953 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
956 setLWResult(res
, RCode::NXDomain
, false, false, true);
957 return LWResult::Result::Success
;
960 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
961 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
962 return LWResult::Result::Success
;
964 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
965 if (domain
== target
) {
966 setLWResult(res
, 0, false, false, true);
967 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
968 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
969 return LWResult::Result::Success
;
971 else if (domain
== DNSName("pdns-public-ns1.powerdns.org.")) {
972 setLWResult(res
, 0, true, false, true);
973 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2");
974 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::AAAA
, "2001:DB8::2");
975 return LWResult::Result::Success
;
977 else if (domain
== DNSName("pdns-public-ns2.powerdns.org.")) {
978 setLWResult(res
, 0, true, false, true);
979 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::A
, "192.0.2.3");
980 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::AAAA
, "2001:DB8::3");
981 return LWResult::Result::Success
;
984 setLWResult(res
, RCode::NXDomain
, false, false, true);
985 return LWResult::Result::Success
;
987 else if (ip
== ComboAddress("192.0.2.2:53") || ip
== ComboAddress("192.0.2.3:53") || ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("[2001:DB8::3]:53")) {
988 setLWResult(res
, 0, true, false, true);
989 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
990 return LWResult::Result::Success
;
993 return LWResult::Result::Timeout
;
997 vector
<DNSRecord
> ret
;
998 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
999 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1000 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1001 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1002 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1005 BOOST_AUTO_TEST_CASE(test_endless_glueless_referral
)
1007 std::unique_ptr
<SyncRes
> sr
;
1012 const DNSName
target("powerdns.com.");
1015 sr
->setAsyncCallback([target
, &count
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const boost::optional
<const ResolveContext
&>& /* context */, LWResult
* res
, bool* /* chained */) {
1016 if (isRootServer(ip
)) {
1017 setLWResult(res
, 0, false, false, true);
1019 if (domain
.isPartOf(DNSName("com."))) {
1020 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1022 else if (domain
.isPartOf(DNSName("org."))) {
1023 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1026 setLWResult(res
, RCode::NXDomain
, false, false, true);
1027 return LWResult::Result::Success
;
1030 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1031 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1032 return LWResult::Result::Success
;
1034 if (domain
== target
) {
1035 setLWResult(res
, 0, false, false, true);
1036 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1037 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1038 return LWResult::Result::Success
;
1040 setLWResult(res
, 0, false, false, true);
1041 addRecordToLW(res
, domain
, QType::NS
, std::to_string(count
) + ".ns1.powerdns.org", DNSResourceRecord::AUTHORITY
, 172800);
1042 addRecordToLW(res
, domain
, QType::NS
, std::to_string(count
) + ".ns2.powerdns.org", DNSResourceRecord::AUTHORITY
, 172800);
1044 return LWResult::Result::Success
;
1047 vector
<DNSRecord
> ret
;
1048 BOOST_CHECK_EXCEPTION(sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
),
1049 ImmediateServFailException
,
1050 [](const ImmediateServFailException
& isfe
) {
1051 return isfe
.reason
.substr(0, 9) == "More than";
1055 BOOST_AUTO_TEST_CASE(test_glueless_referral_aaaa_task
)
1057 std::unique_ptr
<SyncRes
> sr
;
1062 const DNSName
target("powerdns.com.");
1064 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1065 if (isRootServer(ip
)) {
1066 setLWResult(res
, 0, false, false, true);
1068 if (domain
.isPartOf(DNSName("com."))) {
1069 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1071 else if (domain
.isPartOf(DNSName("org."))) {
1072 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1075 setLWResult(res
, RCode::NXDomain
, false, false, true);
1076 return LWResult::Result::Success
;
1079 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1080 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1081 return LWResult::Result::Success
;
1083 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
1084 if (domain
== target
) {
1085 setLWResult(res
, 0, false, false, true);
1086 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1087 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1088 return LWResult::Result::Success
;
1090 else if (domain
== DNSName("pdns-public-ns1.powerdns.org.")) {
1091 setLWResult(res
, 0, true, false, true);
1092 if (type
== QType::A
) {
1093 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2");
1096 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::AAAA
, "2001:DB8::2");
1098 return LWResult::Result::Success
;
1100 else if (domain
== DNSName("pdns-public-ns2.powerdns.org.")) {
1101 setLWResult(res
, 0, true, false, true);
1102 if (type
== QType::A
) {
1103 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::A
, "192.0.2.3");
1106 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::AAAA
, "2001:DB8::3");
1108 return LWResult::Result::Success
;
1111 setLWResult(res
, RCode::NXDomain
, false, false, true);
1112 return LWResult::Result::Success
;
1114 else if (ip
== ComboAddress("192.0.2.2:53") || ip
== ComboAddress("192.0.2.3:53") || ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("[2001:DB8::3]:53")) {
1115 setLWResult(res
, 0, true, false, true);
1116 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
1117 return LWResult::Result::Success
;
1120 return LWResult::Result::Timeout
;
1124 vector
<DNSRecord
> ret
;
1125 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1126 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1127 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1128 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1129 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1131 // One task should be submitted
1132 BOOST_REQUIRE_EQUAL(getTaskSize(), 1U);
1133 auto task
= taskQueuePop();
1134 BOOST_CHECK(task
.d_qname
== DNSName("pdns-public-ns1.powerdns.org") || task
.d_qname
== DNSName("pdns-public-ns2.powerdns.org"));
1135 BOOST_CHECK_EQUAL(task
.d_qtype
, QType::AAAA
);
1138 BOOST_AUTO_TEST_CASE(test_edns_subnet_by_domain
)
1140 std::unique_ptr
<SyncRes
> sr
;
1145 const DNSName
target("powerdns.com.");
1146 SyncRes::addEDNSDomain(target
);
1148 EDNSSubnetOpts incomingECS
;
1149 incomingECS
.source
= Netmask("192.0.2.128/32");
1150 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1152 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1153 BOOST_REQUIRE(srcmask
);
1154 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1156 if (isRootServer(ip
)) {
1157 setLWResult(res
, 0, false, false, true);
1158 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1159 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1161 /* this one did not use the ECS info */
1162 srcmask
= boost::none
;
1164 return LWResult::Result::Success
;
1166 else if (ip
== ComboAddress("192.0.2.1:53")) {
1168 setLWResult(res
, 0, true, false, false);
1169 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1171 /* this one did, but only up to a precision of /16, not the full /24 */
1172 srcmask
= Netmask("192.0.0.0/16");
1174 return LWResult::Result::Success
;
1177 return LWResult::Result::Timeout
;
1180 SyncRes::s_ecsqueries
= 0;
1181 SyncRes::s_ecsresponses
= 0;
1182 vector
<DNSRecord
> ret
;
1183 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1184 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1185 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1186 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1187 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1188 BOOST_CHECK_EQUAL(SyncRes::s_ecsqueries
, 2U);
1189 BOOST_CHECK_EQUAL(SyncRes::s_ecsresponses
, 1U);
1190 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize4
) {
1191 BOOST_CHECK_EQUAL(entry
.second
, entry
.first
== 15 ? 1U : 0U);
1193 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize6
) {
1194 BOOST_CHECK_EQUAL(entry
.second
, 0U);
1198 BOOST_AUTO_TEST_CASE(test_edns_subnet_by_addr
)
1200 std::unique_ptr
<SyncRes
> sr
;
1205 const DNSName
target("powerdns.com.");
1206 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1208 EDNSSubnetOpts incomingECS
;
1209 incomingECS
.source
= Netmask("2001:DB8::FF/128");
1210 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1212 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1213 if (isRootServer(ip
)) {
1214 BOOST_REQUIRE(!srcmask
);
1216 setLWResult(res
, 0, false, false, true);
1217 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1218 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1219 return LWResult::Result::Success
;
1221 else if (ip
== ComboAddress("192.0.2.1:53")) {
1223 BOOST_REQUIRE(srcmask
);
1224 BOOST_CHECK_EQUAL(srcmask
->toString(), "2001:db8::/56");
1226 setLWResult(res
, 0, true, false, false);
1227 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1228 return LWResult::Result::Success
;
1231 return LWResult::Result::Timeout
;
1234 SyncRes::s_ecsqueries
= 0;
1235 SyncRes::s_ecsresponses
= 0;
1236 vector
<DNSRecord
> ret
;
1237 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1238 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1239 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1240 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1241 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1242 BOOST_CHECK_EQUAL(SyncRes::s_ecsqueries
, 1U);
1243 BOOST_CHECK_EQUAL(SyncRes::s_ecsresponses
, 1U);
1244 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize4
) {
1245 BOOST_CHECK_EQUAL(entry
.second
, 0u);
1247 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize6
) {
1248 BOOST_CHECK_EQUAL(entry
.second
, entry
.first
== 55 ? 1U : 0U);
1252 BOOST_AUTO_TEST_CASE(test_ecs_use_requestor
)
1254 std::unique_ptr
<SyncRes
> sr
;
1259 const DNSName
target("powerdns.com.");
1260 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1261 // No incoming ECS data
1262 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::none
);
1264 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1265 if (isRootServer(ip
)) {
1266 BOOST_REQUIRE(!srcmask
);
1268 setLWResult(res
, 0, false, false, true);
1269 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1270 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1271 return LWResult::Result::Success
;
1273 else if (ip
== ComboAddress("192.0.2.1:53")) {
1275 BOOST_REQUIRE(srcmask
);
1276 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1278 setLWResult(res
, 0, true, false, false);
1279 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1280 return LWResult::Result::Success
;
1283 return LWResult::Result::Timeout
;
1286 vector
<DNSRecord
> ret
;
1287 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1288 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1289 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1290 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1291 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1294 BOOST_AUTO_TEST_CASE(test_ecs_use_scope_zero
)
1296 std::unique_ptr
<SyncRes
> sr
;
1301 const DNSName
target("powerdns.com.");
1302 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1303 SyncRes::clearEDNSLocalSubnets();
1304 SyncRes::addEDNSLocalSubnet("192.0.2.254/32");
1305 // No incoming ECS data, Requestor IP not in ecs-add-for
1306 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::none
);
1308 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1309 if (isRootServer(ip
)) {
1310 BOOST_REQUIRE(!srcmask
);
1312 setLWResult(res
, 0, false, false, true);
1313 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1314 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1315 return LWResult::Result::Success
;
1317 else if (ip
== ComboAddress("192.0.2.1:53")) {
1319 BOOST_REQUIRE(srcmask
);
1320 BOOST_CHECK_EQUAL(srcmask
->toString(), "127.0.0.1/32");
1322 setLWResult(res
, 0, true, false, false);
1323 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1324 return LWResult::Result::Success
;
1327 return LWResult::Result::Timeout
;
1330 vector
<DNSRecord
> ret
;
1331 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1332 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1333 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1334 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1335 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1338 BOOST_AUTO_TEST_CASE(test_ecs_honor_incoming_mask
)
1340 std::unique_ptr
<SyncRes
> sr
;
1345 const DNSName
target("powerdns.com.");
1346 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1347 SyncRes::clearEDNSLocalSubnets();
1348 SyncRes::addEDNSLocalSubnet("192.0.2.254/32");
1349 EDNSSubnetOpts incomingECS
;
1350 incomingECS
.source
= Netmask("192.0.0.0/16");
1351 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1353 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1354 if (isRootServer(ip
)) {
1355 BOOST_REQUIRE(!srcmask
);
1357 setLWResult(res
, 0, false, false, true);
1358 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1359 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1360 return LWResult::Result::Success
;
1362 else if (ip
== ComboAddress("192.0.2.1:53")) {
1364 BOOST_REQUIRE(srcmask
);
1365 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.0.0/16");
1367 setLWResult(res
, 0, true, false, false);
1368 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1369 return LWResult::Result::Success
;
1372 return LWResult::Result::Timeout
;
1375 vector
<DNSRecord
> ret
;
1376 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1377 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1378 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1379 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1380 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1383 BOOST_AUTO_TEST_CASE(test_ecs_honor_incoming_mask_zero
)
1385 std::unique_ptr
<SyncRes
> sr
;
1390 const DNSName
target("powerdns.com.");
1391 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1392 SyncRes::clearEDNSLocalSubnets();
1393 SyncRes::addEDNSLocalSubnet("192.0.2.254/32");
1394 EDNSSubnetOpts incomingECS
;
1395 incomingECS
.source
= Netmask("0.0.0.0/0");
1396 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1398 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1399 if (isRootServer(ip
)) {
1400 BOOST_REQUIRE(!srcmask
);
1402 setLWResult(res
, 0, false, false, true);
1403 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1404 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1405 return LWResult::Result::Success
;
1407 else if (ip
== ComboAddress("192.0.2.1:53")) {
1409 BOOST_REQUIRE(srcmask
);
1410 BOOST_CHECK_EQUAL(srcmask
->toString(), "127.0.0.1/32");
1412 setLWResult(res
, 0, true, false, false);
1413 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1414 return LWResult::Result::Success
;
1417 return LWResult::Result::Timeout
;
1420 vector
<DNSRecord
> ret
;
1421 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1422 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1423 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1424 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1425 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1428 BOOST_AUTO_TEST_CASE(test_following_cname
)
1430 std::unique_ptr
<SyncRes
> sr
;
1435 const DNSName
target("cname.powerdns.com.");
1436 const DNSName
cnameTarget("cname-target.powerdns.com");
1438 sr
->setAsyncCallback([target
, cnameTarget
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1439 if (isRootServer(ip
)) {
1440 setLWResult(res
, 0, false, false, true);
1441 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1442 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1443 return LWResult::Result::Success
;
1445 else if (ip
== ComboAddress("192.0.2.1:53")) {
1447 if (domain
== target
) {
1448 setLWResult(res
, 0, true, false, false);
1449 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1450 return LWResult::Result::Success
;
1452 else if (domain
== cnameTarget
) {
1453 setLWResult(res
, 0, true, false, false);
1454 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1457 return LWResult::Result::Success
;
1460 return LWResult::Result::Timeout
;
1463 vector
<DNSRecord
> ret
;
1464 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1465 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1466 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1467 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1468 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1469 BOOST_CHECK(ret
[1].d_type
== QType::A
);
1470 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1473 BOOST_AUTO_TEST_CASE(test_cname_nxdomain
)
1475 std::unique_ptr
<SyncRes
> sr
;
1480 const DNSName
target("cname.powerdns.com.");
1481 const DNSName
cnameTarget("cname-target.powerdns.com");
1483 sr
->setAsyncCallback([target
, cnameTarget
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1484 if (isRootServer(ip
)) {
1485 setLWResult(res
, 0, false, false, true);
1486 addRecordToLW(res
, "powerdns.com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1487 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1488 return LWResult::Result::Success
;
1490 else if (ip
== ComboAddress("192.0.2.1:53")) {
1492 if (domain
== target
) {
1493 setLWResult(res
, RCode::NXDomain
, true, false, false);
1494 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1495 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1497 else if (domain
== cnameTarget
) {
1498 setLWResult(res
, RCode::NXDomain
, true, false, false);
1499 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1500 return LWResult::Result::Success
;
1503 return LWResult::Result::Success
;
1506 return LWResult::Result::Timeout
;
1509 vector
<DNSRecord
> ret
;
1510 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1511 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1512 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1513 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1514 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1515 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1517 /* a second time, to check the cache */
1519 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1520 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1521 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1522 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1523 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1524 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1527 BOOST_AUTO_TEST_CASE(test_included_poisonous_cname
)
1529 std::unique_ptr
<SyncRes
> sr
;
1534 /* In this test we directly get the NS server for cname.powerdns.com.,
1535 and we don't know whether it's also authoritative for
1536 cname-target.powerdns.com or powerdns.com, so we shouldn't accept
1537 the additional A record for cname-target.powerdns.com. */
1538 const DNSName
target("cname.powerdns.com.");
1539 const DNSName
cnameTarget("cname-target.powerdns.com");
1541 sr
->setAsyncCallback([target
, cnameTarget
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1542 if (isRootServer(ip
)) {
1544 setLWResult(res
, 0, false, false, true);
1546 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1547 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1548 return LWResult::Result::Success
;
1550 else if (ip
== ComboAddress("192.0.2.1:53")) {
1552 if (domain
== target
) {
1553 setLWResult(res
, 0, true, false, false);
1554 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1555 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
);
1556 return LWResult::Result::Success
;
1558 else if (domain
== cnameTarget
) {
1559 setLWResult(res
, 0, true, false, false);
1560 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.3");
1561 return LWResult::Result::Success
;
1564 return LWResult::Result::Success
;
1567 return LWResult::Result::Timeout
;
1570 vector
<DNSRecord
> ret
;
1571 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1572 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1573 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1574 BOOST_REQUIRE(ret
[0].d_type
== QType::CNAME
);
1575 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1576 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget(), cnameTarget
);
1577 BOOST_REQUIRE(ret
[1].d_type
== QType::A
);
1578 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1579 BOOST_CHECK(getRR
<ARecordContent
>(ret
[1])->getCA() == ComboAddress("192.0.2.3"));
1582 BOOST_AUTO_TEST_CASE(test_cname_loop
)
1584 std::unique_ptr
<SyncRes
> sr
;
1590 const DNSName
target("cname.powerdns.com.");
1592 sr
->setAsyncCallback([target
, &count
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1595 if (isRootServer(ip
)) {
1597 setLWResult(res
, 0, false, false, true);
1598 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1599 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1600 return LWResult::Result::Success
;
1602 else if (ip
== ComboAddress("192.0.2.1:53")) {
1604 if (domain
== target
) {
1605 setLWResult(res
, 0, true, false, false);
1606 addRecordToLW(res
, domain
, QType::CNAME
, domain
.toString());
1607 return LWResult::Result::Success
;
1610 return LWResult::Result::Success
;
1613 return LWResult::Result::Timeout
;
1616 vector
<DNSRecord
> ret
;
1617 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1618 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1619 BOOST_CHECK_EQUAL(ret
.size(), 0U);
1620 BOOST_CHECK_EQUAL(count
, 2U);
1622 // Again to check cache
1624 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1627 catch (const ImmediateServFailException
& ex
) {
1632 BOOST_AUTO_TEST_CASE(test_cname_long_loop
)
1634 std::unique_ptr
<SyncRes
> sr
;
1640 const DNSName
target1("cname1.powerdns.com.");
1641 const DNSName
target2("cname2.powerdns.com.");
1642 const DNSName
target3("cname3.powerdns.com.");
1643 const DNSName
target4("cname4.powerdns.com.");
1645 sr
->setAsyncCallback([target1
, target2
, target3
, target4
, &count
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const boost::optional
<const ResolveContext
&>& /* context */, LWResult
* res
, bool* /* chained */) {
1648 if (isRootServer(ip
)) {
1650 setLWResult(res
, 0, false, false, true);
1651 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1652 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1653 return LWResult::Result::Success
;
1655 else if (ip
== ComboAddress("192.0.2.1:53")) {
1657 if (domain
== target1
) {
1658 setLWResult(res
, 0, true, false, false);
1659 addRecordToLW(res
, domain
, QType::CNAME
, target2
.toString());
1660 return LWResult::Result::Success
;
1662 else if (domain
== target2
) {
1663 setLWResult(res
, 0, true, false, false);
1664 addRecordToLW(res
, domain
, QType::CNAME
, target3
.toString());
1665 return LWResult::Result::Success
;
1667 else if (domain
== target3
) {
1668 setLWResult(res
, 0, true, false, false);
1669 addRecordToLW(res
, domain
, QType::CNAME
, target4
.toString());
1670 return LWResult::Result::Success
;
1672 else if (domain
== target4
) {
1673 setLWResult(res
, 0, true, false, false);
1674 addRecordToLW(res
, domain
, QType::CNAME
, target1
.toString());
1675 return LWResult::Result::Success
;
1678 return LWResult::Result::Success
;
1681 return LWResult::Result::Timeout
;
1684 vector
<DNSRecord
> ret
;
1685 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1686 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1687 BOOST_CHECK_EQUAL(ret
.size(), 0U);
1688 BOOST_CHECK_EQUAL(count
, 8U);
1690 // And again to check cache
1692 sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1695 catch (const ImmediateServFailException
& ex
) {
1700 BOOST_AUTO_TEST_CASE(test_cname_length
)
1702 std::unique_ptr
<SyncRes
> sr
;
1708 const DNSName
target("cname.powerdns.com.");
1710 sr
->setAsyncCallback([target
, &length
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const boost::optional
<const ResolveContext
&>& /* context */, LWResult
* res
, bool* /* chained */) {
1711 if (isRootServer(ip
)) {
1713 setLWResult(res
, 0, false, false, true);
1714 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1715 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1716 return LWResult::Result::Success
;
1718 else if (ip
== ComboAddress("192.0.2.1:53")) {
1720 setLWResult(res
, 0, true, false, false);
1721 addRecordToLW(res
, domain
, QType::CNAME
, std::to_string(length
) + "-cname.powerdns.com");
1723 return LWResult::Result::Success
;
1726 return LWResult::Result::Timeout
;
1729 vector
<DNSRecord
> ret
;
1730 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1731 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1732 BOOST_CHECK_EQUAL(ret
.size(), length
);
1733 BOOST_CHECK_EQUAL(length
, SyncRes::s_max_CNAMES_followed
+ 1);
1736 BOOST_AUTO_TEST_CASE(test_cname_target_servfail
)
1738 std::unique_ptr
<SyncRes
> resolver
;
1743 const DNSName
target("cname.powerdns.com.");
1744 const DNSName
cnameTarget("cname-target.powerdns.com");
1746 resolver
->setAsyncCallback([target
, cnameTarget
](const ComboAddress
& ipAddress
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const boost::optional
<const ResolveContext
&>& /* context */, LWResult
* res
, bool* /* chained */) {
1747 if (isRootServer(ipAddress
)) {
1748 setLWResult(res
, 0, false, false, true);
1749 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1750 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1751 return LWResult::Result::Success
;
1753 if (ipAddress
== ComboAddress("192.0.2.1:53")) {
1755 if (domain
== target
) {
1756 setLWResult(res
, 0, true, false, false);
1757 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1758 return LWResult::Result::Success
;
1760 if (domain
== cnameTarget
) {
1761 return LWResult::Result::PermanentError
;
1764 return LWResult::Result::Success
;
1767 return LWResult::Result::Timeout
;
1770 vector
<DNSRecord
> ret
;
1771 int res
= resolver
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1772 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1773 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1774 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1775 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1778 BOOST_AUTO_TEST_CASE(test_cname_target_servfail_servestale
)
1780 std::unique_ptr
<SyncRes
> resolver
;
1782 MemRecursorCache::s_maxServedStaleExtensions
= 1440;
1786 const DNSName
target("cname.powerdns.com.");
1787 const DNSName
cnameTarget("cname-target.powerdns.com");
1789 resolver
->setAsyncCallback([target
, cnameTarget
](const ComboAddress
& ipAddress
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, const boost::optional
<const ResolveContext
&>& /* context */, LWResult
* res
, bool* /* chained */) {
1790 if (isRootServer(ipAddress
)) {
1791 setLWResult(res
, 0, false, false, true);
1792 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1793 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1794 return LWResult::Result::Success
;
1796 if (ipAddress
== ComboAddress("192.0.2.1:53")) {
1798 if (domain
== target
) {
1799 setLWResult(res
, 0, true, false, false);
1800 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1801 return LWResult::Result::Success
;
1803 if (domain
== cnameTarget
) {
1804 return LWResult::Result::PermanentError
;
1807 return LWResult::Result::Success
;
1810 return LWResult::Result::Timeout
;
1813 vector
<DNSRecord
> ret
;
1814 int res
= resolver
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1815 // different compared no non-servestale case (returns ServFail), handled by pdns_recursor
1816 BOOST_CHECK_EQUAL(res
, -1);
1817 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1818 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1819 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1822 BOOST_AUTO_TEST_CASE(test_time_limit
)
1824 std::unique_ptr
<SyncRes
> sr
;
1830 const DNSName
target("cname.powerdns.com.");
1832 sr
->setAsyncCallback([target
, &queries
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1835 if (isRootServer(ip
)) {
1836 setLWResult(res
, 0, false, false, true);
1837 /* Pretend that this query took 2000 ms */
1840 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1841 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1842 return LWResult::Result::Success
;
1844 else if (ip
== ComboAddress("192.0.2.1:53")) {
1846 setLWResult(res
, 0, true, false, false);
1847 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1848 return LWResult::Result::Success
;
1851 return LWResult::Result::Timeout
;
1854 /* Set the maximum time to 1 ms */
1855 SyncRes::s_maxtotusec
= 1000;
1858 vector
<DNSRecord
> ret
;
1859 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1862 catch (const ImmediateServFailException
& e
) {
1864 BOOST_CHECK_EQUAL(queries
, 1U);
1867 BOOST_AUTO_TEST_CASE(test_dname_processing
)
1869 std::unique_ptr
<SyncRes
> sr
;
1874 const DNSName
dnameOwner("powerdns.com");
1875 const DNSName
dnameTarget("powerdns.net");
1877 const DNSName
target("dname.powerdns.com.");
1878 const DNSName
cnameTarget("dname.powerdns.net");
1880 const DNSName
uncachedTarget("dname-uncached.powerdns.com.");
1881 const DNSName
uncachedCNAMETarget("dname-uncached.powerdns.net.");
1883 const DNSName
synthCNAME("cname-uncached.powerdns.com.");
1884 const DNSName
synthCNAMETarget("cname-uncached.powerdns.net.");
1888 sr
->setAsyncCallback([dnameOwner
, dnameTarget
, target
, cnameTarget
, uncachedTarget
, uncachedCNAMETarget
, &queries
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
1891 if (isRootServer(ip
)) {
1892 if (domain
.isPartOf(dnameOwner
)) {
1893 setLWResult(res
, 0, false, false, true);
1894 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1895 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1896 return LWResult::Result::Success
;
1898 if (domain
.isPartOf(dnameTarget
)) {
1899 setLWResult(res
, 0, false, false, true);
1900 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1901 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1902 return LWResult::Result::Success
;
1905 else if (ip
== ComboAddress("192.0.2.1:53")) {
1906 if (domain
== target
) {
1907 setLWResult(res
, 0, true, false, false);
1908 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
1909 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1910 return LWResult::Result::Success
;
1913 else if (ip
== ComboAddress("192.0.2.2:53")) {
1914 if (domain
== cnameTarget
) {
1915 setLWResult(res
, 0, true, false, false);
1916 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1918 if (domain
== uncachedCNAMETarget
) {
1919 setLWResult(res
, 0, true, false, false);
1920 addRecordToLW(res
, domain
, QType::A
, "192.0.2.3");
1922 return LWResult::Result::Success
;
1924 return LWResult::Result::Timeout
;
1927 vector
<DNSRecord
> ret
;
1928 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1930 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1931 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
1933 BOOST_CHECK_EQUAL(queries
, 4u);
1935 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1936 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1937 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1939 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
1940 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
1942 BOOST_CHECK(ret
[2].d_type
== QType::A
);
1943 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
1945 // Now check the cache
1947 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1949 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1950 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
1952 BOOST_CHECK_EQUAL(queries
, 4U);
1954 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1955 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1956 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1958 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
1959 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
1961 BOOST_CHECK(ret
[2].d_type
== QType::A
);
1962 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
1964 // Check if we correctly return a synthesized CNAME, should send out just 1 more query
1966 res
= sr
->beginResolve(uncachedTarget
, QType(QType::A
), QClass::IN
, ret
);
1968 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1969 BOOST_CHECK_EQUAL(queries
, 5U);
1971 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1972 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1973 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1975 BOOST_REQUIRE(ret
[1].d_type
== QType::CNAME
);
1976 BOOST_CHECK_EQUAL(ret
[1].d_name
, uncachedTarget
);
1977 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[1])->getTarget(), uncachedCNAMETarget
);
1979 BOOST_CHECK(ret
[2].d_type
== QType::A
);
1980 BOOST_CHECK_EQUAL(ret
[2].d_name
, uncachedCNAMETarget
);
1982 // Check if we correctly return the DNAME from cache when asked
1984 res
= sr
->beginResolve(dnameOwner
, QType(QType::DNAME
), QClass::IN
, ret
);
1985 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1986 BOOST_CHECK_EQUAL(queries
, 5U);
1988 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1989 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1990 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1992 // Check if we correctly return the synthesized CNAME from cache when asked
1994 res
= sr
->beginResolve(synthCNAME
, QType(QType::CNAME
), QClass::IN
, ret
);
1995 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1996 BOOST_CHECK_EQUAL(queries
, 5U);
1998 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1999 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2000 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2002 BOOST_REQUIRE(ret
[1].d_type
== QType::CNAME
);
2003 BOOST_CHECK(ret
[1].d_name
== synthCNAME
);
2004 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[1])->getTarget(), synthCNAMETarget
);
2007 BOOST_AUTO_TEST_CASE(test_dname_dnssec_secure
)
2009 std::unique_ptr
<SyncRes
> sr
;
2011 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
2015 const DNSName
dnameOwner("powerdns");
2016 const DNSName
dnameTarget("example");
2018 const DNSName
target("dname.powerdns");
2019 const DNSName
cnameTarget("dname.example");
2023 auto luaconfsCopy
= g_luaconfs
.getCopy();
2024 luaconfsCopy
.dsAnchors
.clear();
2025 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2026 generateKeyMaterial(dnameOwner
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2027 generateKeyMaterial(dnameTarget
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2028 g_luaconfs
.setState(luaconfsCopy
);
2032 sr
->setAsyncCallback([dnameOwner
, dnameTarget
, target
, cnameTarget
, keys
, &queries
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
2034 /* 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
2035 * As such, we need to do some more work to make the answers correct.
2038 if (isRootServer(ip
)) {
2039 if (domain
.countLabels() == 0 && type
== QType::DNSKEY
) { // .|DNSKEY
2040 setLWResult(res
, 0, true, false, true);
2041 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2042 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2043 return LWResult::Result::Success
;
2045 if (domain
.countLabels() == 1 && type
== QType::DS
) { // powerdns|DS or example|DS
2046 setLWResult(res
, 0, true, false, true);
2047 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
2048 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2049 return LWResult::Result::Success
;
2051 // For the rest, delegate!
2052 if (domain
.isPartOf(dnameOwner
)) {
2053 setLWResult(res
, 0, false, false, true);
2054 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2055 addDS(dnameOwner
, 300, res
->d_records
, keys
);
2056 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2057 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2058 return LWResult::Result::Success
;
2060 if (domain
.isPartOf(dnameTarget
)) {
2061 setLWResult(res
, 0, false, false, true);
2062 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2063 addDS(dnameTarget
, 300, res
->d_records
, keys
);
2064 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2065 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2066 return LWResult::Result::Success
;
2069 else if (ip
== ComboAddress("192.0.2.1:53")) {
2070 if (domain
.countLabels() == 1 && type
== QType::DNSKEY
) { // powerdns|DNSKEY
2071 setLWResult(res
, 0, true, false, true);
2072 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2073 addRRSIG(keys
, res
->d_records
, domain
, 300);
2074 return LWResult::Result::Success
;
2076 if (domain
== target
&& type
== QType::DS
) { // dname.powerdns|DS
2077 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
2079 if (domain
== target
) {
2080 setLWResult(res
, 0, true, false, false);
2081 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2082 addRRSIG(keys
, res
->d_records
, dnameOwner
, 300);
2083 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString()); // CNAME from a DNAME is not signed
2084 return LWResult::Result::Success
;
2087 else if (ip
== ComboAddress("192.0.2.2:53")) {
2088 if (domain
.countLabels() == 1 && type
== QType::DNSKEY
) { // example|DNSKEY
2089 setLWResult(res
, 0, true, false, true);
2090 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2091 addRRSIG(keys
, res
->d_records
, domain
, 300);
2092 return LWResult::Result::Success
;
2094 if (domain
== cnameTarget
&& type
== QType::DS
) { // dname.example|DS
2095 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
2097 if (domain
== cnameTarget
) {
2098 setLWResult(res
, 0, true, false, false);
2099 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2100 addRRSIG(keys
, res
->d_records
, dnameTarget
, 300);
2102 return LWResult::Result::Success
;
2104 return LWResult::Result::Timeout
;
2107 vector
<DNSRecord
> ret
;
2108 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2110 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2111 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2112 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2114 BOOST_CHECK_EQUAL(queries
, 7U);
2116 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2117 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2118 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2120 BOOST_REQUIRE(ret
[1].d_type
== QType::RRSIG
);
2121 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2123 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2124 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2126 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2127 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2129 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2130 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2134 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2136 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2137 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2138 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2140 BOOST_CHECK_EQUAL(queries
, 7U);
2142 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2143 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2144 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2146 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2147 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2149 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2150 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2152 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2153 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2155 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2156 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2159 BOOST_AUTO_TEST_CASE(test_dname_plus_ns_dnssec_secure
)
2161 std::unique_ptr
<SyncRes
> sr
;
2163 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
2167 const DNSName
dnameOwner("powerdns");
2168 const DNSName
dnameTarget("example");
2170 const DNSName
target("dname.powerdns");
2171 const DNSName
cnameTarget("dname.example");
2175 auto luaconfsCopy
= g_luaconfs
.getCopy();
2176 luaconfsCopy
.dsAnchors
.clear();
2177 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2178 generateKeyMaterial(dnameTarget
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2179 g_luaconfs
.setState(luaconfsCopy
);
2183 sr
->setAsyncCallback([dnameOwner
, dnameTarget
, target
, cnameTarget
, keys
, &queries
](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
2186 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
2187 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
2190 if (domain
.isPartOf(dnameOwner
)) {
2191 setLWResult(res
, 0, true, false, true);
2192 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2193 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2194 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString()); // CNAME from a DNAME is not signed
2196 addRecordToLW(res
, dnameTarget
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2197 addDS(dnameTarget
, 300, res
->d_records
, keys
);
2198 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2199 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2200 return LWResult::Result::Success
;
2202 else if (domain
== cnameTarget
) {
2203 setLWResult(res
, 0, true, false, true);
2204 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2205 addRRSIG(keys
, res
->d_records
, dnameTarget
, 300);
2206 return LWResult::Result::Success
;
2208 return LWResult::Result::Timeout
;
2211 vector
<DNSRecord
> ret
;
2212 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2214 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2215 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2216 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2218 BOOST_CHECK_EQUAL(queries
, 4U);
2220 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2221 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2222 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2224 BOOST_REQUIRE(ret
[1].d_type
== QType::RRSIG
);
2225 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2227 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2228 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2230 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2231 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2233 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2234 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2238 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2240 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2241 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2242 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2244 BOOST_CHECK_EQUAL(queries
, 4U);
2246 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2247 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2248 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2250 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2251 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2253 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2254 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2256 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2257 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2259 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2260 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2263 BOOST_AUTO_TEST_CASE(test_dname_dnssec_insecure
)
2266 * The DNAME itself is signed, but the final A record is not
2268 std::unique_ptr
<SyncRes
> sr
;
2270 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
2274 const DNSName
dnameOwner("powerdns");
2275 const DNSName
dnameTarget("example");
2277 const DNSName
target("dname.powerdns");
2278 const DNSName
cnameTarget("dname.example");
2282 auto luaconfsCopy
= g_luaconfs
.getCopy();
2283 luaconfsCopy
.dsAnchors
.clear();
2284 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2285 generateKeyMaterial(dnameOwner
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2286 g_luaconfs
.setState(luaconfsCopy
);
2290 sr
->setAsyncCallback([dnameOwner
, dnameTarget
, target
, cnameTarget
, keys
, &queries
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
2293 if (isRootServer(ip
)) {
2294 if (domain
.countLabels() == 0 && type
== QType::DNSKEY
) { // .|DNSKEY
2295 setLWResult(res
, 0, true, false, true);
2296 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2297 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2298 return LWResult::Result::Success
;
2300 if (domain
== dnameOwner
&& type
== QType::DS
) { // powerdns|DS
2301 setLWResult(res
, 0, true, false, true);
2302 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
2303 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2304 return LWResult::Result::Success
;
2306 if (domain
== dnameTarget
&& type
== QType::DS
) { // example|DS
2307 return genericDSAndDNSKEYHandler(res
, domain
, DNSName("."), type
, keys
);
2309 // For the rest, delegate!
2310 if (domain
.isPartOf(dnameOwner
)) {
2311 setLWResult(res
, 0, false, false, true);
2312 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2313 addDS(dnameOwner
, 300, res
->d_records
, keys
);
2314 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2315 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2316 return LWResult::Result::Success
;
2318 if (domain
.isPartOf(dnameTarget
)) {
2319 setLWResult(res
, 0, false, false, true);
2320 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2321 addDS(dnameTarget
, 300, res
->d_records
, keys
);
2322 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2323 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2324 return LWResult::Result::Success
;
2327 else if (ip
== ComboAddress("192.0.2.1:53")) {
2328 if (domain
.countLabels() == 1 && type
== QType::DNSKEY
) { // powerdns|DNSKEY
2329 setLWResult(res
, 0, true, false, true);
2330 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2331 addRRSIG(keys
, res
->d_records
, domain
, 300);
2332 return LWResult::Result::Success
;
2334 if (domain
== target
&& type
== QType::DS
) { // dname.powerdns|DS
2335 return genericDSAndDNSKEYHandler(res
, domain
, dnameOwner
, type
, keys
, false);
2337 if (domain
== target
) {
2338 setLWResult(res
, 0, true, false, false);
2339 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2340 addRRSIG(keys
, res
->d_records
, dnameOwner
, 300);
2341 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString()); // CNAME from a DNAME is not signed
2342 return LWResult::Result::Success
;
2345 else if (ip
== ComboAddress("192.0.2.2:53")) {
2346 if (domain
== target
&& type
== QType::DS
) { // dname.example|DS
2347 return genericDSAndDNSKEYHandler(res
, domain
, dnameTarget
, type
, keys
, false);
2349 if (domain
== cnameTarget
) {
2350 setLWResult(res
, 0, true, false, false);
2351 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2353 return LWResult::Result::Success
;
2355 return LWResult::Result::Timeout
;
2358 vector
<DNSRecord
> ret
;
2359 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2361 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2362 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
2363 BOOST_REQUIRE_EQUAL(ret
.size(), 4U); /* DNAME + RRSIG(DNAME) + CNAME + A */
2365 BOOST_CHECK_EQUAL(queries
, 7U);
2367 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2368 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2369 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2371 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2372 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2374 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2375 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2377 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2378 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2382 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2384 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2385 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
2386 BOOST_REQUIRE_EQUAL(ret
.size(), 4U); /* DNAME + RRSIG(DNAME) + CNAME + A */
2388 BOOST_CHECK_EQUAL(queries
, 7U);
2390 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2391 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2392 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2394 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2395 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2397 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2398 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2400 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2401 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2404 BOOST_AUTO_TEST_CASE(test_dname_processing_no_CNAME
)
2406 std::unique_ptr
<SyncRes
> sr
;
2411 const DNSName
dnameOwner("powerdns.com");
2412 const DNSName
dnameTarget("powerdns.net");
2414 const DNSName
target("dname.powerdns.com.");
2415 const DNSName
cnameTarget("dname.powerdns.net");
2419 sr
->setAsyncCallback([dnameOwner
, dnameTarget
, target
, cnameTarget
, &queries
](const ComboAddress
& ip
, const DNSName
& domain
, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
2422 if (isRootServer(ip
)) {
2423 if (domain
.isPartOf(dnameOwner
)) {
2424 setLWResult(res
, 0, false, false, true);
2425 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2426 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2427 return LWResult::Result::Success
;
2429 if (domain
.isPartOf(dnameTarget
)) {
2430 setLWResult(res
, 0, false, false, true);
2431 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2432 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2433 return LWResult::Result::Success
;
2436 else if (ip
== ComboAddress("192.0.2.1:53")) {
2437 if (domain
== target
) {
2438 setLWResult(res
, 0, true, false, false);
2439 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2440 // No CNAME, recursor should synth
2441 return LWResult::Result::Success
;
2444 else if (ip
== ComboAddress("192.0.2.2:53")) {
2445 if (domain
== cnameTarget
) {
2446 setLWResult(res
, 0, true, false, false);
2447 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2449 return LWResult::Result::Success
;
2451 return LWResult::Result::Timeout
;
2454 vector
<DNSRecord
> ret
;
2455 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2457 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2458 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
2460 BOOST_CHECK_EQUAL(queries
, 4U);
2462 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2463 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2464 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2466 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
2467 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
2469 BOOST_CHECK(ret
[2].d_type
== QType::A
);
2470 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
2472 // Now check the cache
2474 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2476 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2477 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
2479 BOOST_CHECK_EQUAL(queries
, 4U);
2481 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2482 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2483 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2485 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
2486 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
2488 BOOST_CHECK(ret
[2].d_type
== QType::A
);
2489 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
2493 // cerr<<"asyncresolve called to ask "<<ip.toStringWithPort()<<" about "<<domain.toString()<<" / "<<QType(type).getName()<<" over "<<(doTCP ? "TCP" : "UDP")<<" (rd: "<<sendRDQuery<<", EDNS0 level: "<<EDNS0Level<<")"<<endl;
2495 - check out of band support
2501 BOOST_AUTO_TEST_CASE(test_glued_referral_child_ns_set_wrong
)
2503 std::unique_ptr
<SyncRes
> sr
;
2508 const DNSName
target("powerdns.com.");
2510 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
2511 /* this will cause issue with qname minimization if we ever implement it */
2512 if (domain
!= target
) {
2513 return LWResult::Result::Timeout
;
2516 if (isRootServer(ip
)) {
2517 setLWResult(res
, 0, false, false, true);
2518 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2519 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2520 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
2521 return LWResult::Result::Success
;
2523 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
2524 setLWResult(res
, 0, false, false, true);
2525 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
2526 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
2527 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
2528 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
2529 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
2530 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
2531 return LWResult::Result::Success
;
2533 else if (ip
== ComboAddress("192.0.2.2:53") || ip
== ComboAddress("192.0.2.3:53") || ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("[2001:DB8::3]:53")) {
2535 if (type
== QType::A
) {
2536 setLWResult(res
, 0, true, false, true);
2537 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
2538 return LWResult::Result::Success
;
2540 else if (type
== QType::NS
) {
2541 setLWResult(res
, 0, true, false, true);
2542 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-nsX1.powerdns.com.", DNSResourceRecord::ANSWER
, 172800);
2543 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-nsX2.powerdns.com.", DNSResourceRecord::ANSWER
, 172800);
2544 addRecordToLW(res
, "pdns-public-nsX1.powerdns.com.", QType::A
, "192.0.2.11", DNSResourceRecord::ADDITIONAL
, 172800);
2545 addRecordToLW(res
, "pdns-public-nsX1.powerdns.com.", QType::AAAA
, "2001:DB8::11", DNSResourceRecord::ADDITIONAL
, 172800);
2546 addRecordToLW(res
, "pdns-public-nsX2.powerdns.com.", QType::A
, "192.0.2.12", DNSResourceRecord::ADDITIONAL
, 172800);
2547 addRecordToLW(res
, "pdns-public-nsX2.powerdns.com.", QType::AAAA
, "2001:DB8::12", DNSResourceRecord::ADDITIONAL
, 172800);
2548 return LWResult::Result::Success
;
2551 return LWResult::Result::Timeout
;
2555 return LWResult::Result::Timeout
;
2559 vector
<DNSRecord
> ret
;
2560 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2561 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2562 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
2563 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2564 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
2566 // Now resolve NS to get auth NS set in cache and save the parent NS set
2568 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
2569 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2570 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
2571 BOOST_CHECK(ret
[0].d_type
== QType::NS
);
2572 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
2573 BOOST_CHECK_EQUAL(SyncRes::getSaveParentsNSSetsSize(), 1U);
2575 g_recCache
->doWipeCache(target
, false, QType::A
);
2576 SyncRes::s_save_parent_ns_set
= false;
2578 // Try to resolve now via the broken child NS set... should not work
2580 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2581 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
2582 BOOST_REQUIRE_EQUAL(ret
.size(), 0U);
2584 SyncRes::s_save_parent_ns_set
= true;
2586 // Try to resolve now via the broken child... should work now via fallback to parent NS set
2588 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2589 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2590 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
2591 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2592 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
2595 BOOST_AUTO_TEST_SUITE_END()