1 #ifndef BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_DYN_LINK
5 #include <boost/test/unit_test.hpp>
7 #include "test-syncres_cc.hh"
8 #include "taskqueue.hh"
9 #include "rec-taskqueue.hh"
11 BOOST_AUTO_TEST_SUITE(syncres_cc1
)
13 BOOST_AUTO_TEST_CASE(test_root_primed
)
15 std::unique_ptr
<SyncRes
> sr
;
20 const DNSName
target("a.root-servers.net.");
22 /* we are primed, but only with non-auth data so we cannot resolve A a.root-servers.net. without any query */
23 vector
<DNSRecord
> ret
;
24 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
25 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
26 BOOST_REQUIRE_EQUAL(ret
.size(), 0U);
29 res
= sr
->beginResolve(target
, QType(QType::AAAA
), QClass::IN
, ret
);
30 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
31 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Indeterminate
);
32 BOOST_REQUIRE_EQUAL(ret
.size(), 0U);
35 catch (const ImmediateServFailException
) {
40 BOOST_AUTO_TEST_CASE(test_root_primed_ns
)
42 std::unique_ptr
<SyncRes
> sr
;
46 const DNSName
target(".");
48 /* we are primed, but we should not be able to NS . without any query
49 because the . NS entry is not stored as authoritative */
51 size_t queriesCount
= 0;
53 sr
->setAsyncCallback([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 */) {
56 if (domain
== target
&& type
== QType::NS
) {
58 setLWResult(res
, 0, true, false, true);
59 char addr
[] = "a.root-servers.net.";
60 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
62 addRecordToLW(res
, g_rootdnsname
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
65 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
66 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
68 return LWResult::Result::Success
;
71 return LWResult::Result::Timeout
;
74 vector
<DNSRecord
> ret
;
75 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
76 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
77 BOOST_REQUIRE_EQUAL(ret
.size(), 13U);
78 BOOST_CHECK_EQUAL(queriesCount
, 1U);
81 BOOST_AUTO_TEST_CASE(test_root_not_primed
)
83 std::unique_ptr
<SyncRes
> sr
;
86 size_t queriesCount
= 0;
88 sr
->setAsyncCallback([&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 */) {
91 if (domain
== g_rootdnsname
&& type
== QType::NS
) {
92 setLWResult(res
, 0, true, false, true);
93 addRecordToLW(res
, g_rootdnsname
, QType::NS
, "a.root-servers.net.", DNSResourceRecord::ANSWER
, 3600);
94 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
95 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
97 return LWResult::Result::Success
;
100 return LWResult::Result::Timeout
;
103 /* we are not primed yet, so SyncRes will have to call primeHints()
104 then call getRootNS(), for which at least one of the root servers needs to answer */
105 vector
<DNSRecord
> ret
;
106 int res
= sr
->beginResolve(DNSName("."), QType(QType::NS
), QClass::IN
, ret
);
107 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
108 BOOST_CHECK_EQUAL(ret
.size(), 1U);
109 BOOST_CHECK_EQUAL(queriesCount
, 2U);
112 BOOST_AUTO_TEST_CASE(test_root_not_primed_and_no_response
)
114 std::unique_ptr
<SyncRes
> sr
;
116 // We expect an error, do not log it
117 g_log
.toConsole(Logger::Critical
);
118 std::set
<ComboAddress
> downServers
;
120 /* we are not primed yet, so SyncRes will have to call primeHints()
121 then call getRootNS(), for which at least one of the root servers needs to answer.
122 None will, so it should ServFail.
124 sr
->setAsyncCallback([&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 */) {
125 downServers
.insert(ip
);
126 return LWResult::Result::Timeout
;
129 vector
<DNSRecord
> ret
;
130 int res
= sr
->beginResolve(DNSName("."), QType(QType::NS
), QClass::IN
, ret
);
131 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
132 BOOST_CHECK_EQUAL(ret
.size(), 0U);
133 BOOST_CHECK(downServers
.size() > 0);
134 /* we explicitly refuse to mark the root servers down */
135 for (const auto& server
: downServers
) {
136 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 0U);
140 BOOST_AUTO_TEST_CASE(test_root_ns_poison_resistance
)
142 std::unique_ptr
<SyncRes
> sr
;
146 const DNSName
target("www.example.com.");
148 sr
->setAsyncCallback([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 */) {
149 if (domain
== g_rootdnsname
&& type
== QType::NS
) {
151 setLWResult(res
, 0, true, false, true);
152 char addr
[] = "a.root-servers.net.";
153 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
155 addRecordToLW(res
, g_rootdnsname
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
158 addRecordToLW(res
, "a.root-servers.net.", QType::A
, "198.41.0.4", DNSResourceRecord::ADDITIONAL
, 3600);
159 addRecordToLW(res
, "a.root-servers.net.", QType::AAAA
, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL
, 3600);
161 return LWResult::Result::Success
;
164 if (domain
== target
&& type
== QType::A
) {
166 setLWResult(res
, 0, true, false, true);
167 addRecordToLW(res
, target
, QType::A
, "1.2.3.4", DNSResourceRecord::ANSWER
, 3600);
169 addRecordToLW(res
, ".", QType::NS
, "poison.name.", DNSResourceRecord::AUTHORITY
, 3600);
170 addRecordToLW(res
, "poison.name", QType::A
, "4.5.6.7", DNSResourceRecord::ADDITIONAL
, 3600);
172 return LWResult::Result::Success
;
175 return LWResult::Result::Timeout
;
178 vector
<DNSRecord
> ret
;
179 // Check we have 13 root servers
180 int res
= sr
->beginResolve(g_rootdnsname
, QType(QType::NS
), QClass::IN
, ret
);
181 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
182 BOOST_REQUIRE_EQUAL(ret
.size(), 13U);
186 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
187 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
188 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
190 // Still should have 13
192 res
= sr
->beginResolve(g_rootdnsname
, QType(QType::NS
), QClass::IN
, ret
);
193 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
194 BOOST_REQUIRE_EQUAL(ret
.size(), 13U);
197 BOOST_AUTO_TEST_CASE(test_root_primed_ns_update
)
199 std::unique_ptr
<SyncRes
> sr
;
203 const DNSName
target(".");
204 const DNSName
aroot("a.root-servers.net.");
205 const string newA
= "1.2.3.4";
206 const string newAAAA
= "1::2";
208 /* we are primed, but we should not be able to NS . without any query
209 because the . NS entry is not stored as authoritative */
211 size_t queriesCount
= 0;
213 auto asynccb
= [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 */) {
216 if (domain
== target
&& type
== QType::NS
) {
218 setLWResult(res
, 0, true, false, true);
219 char addr
[] = "a.root-servers.net.";
220 for (char idx
= 'a'; idx
<= 'm'; idx
++) {
222 addRecordToLW(res
, g_rootdnsname
, QType::NS
, std::string(addr
), DNSResourceRecord::ANSWER
, 3600);
225 addRecordToLW(res
, aroot
.toString(), QType::A
, newA
, DNSResourceRecord::ADDITIONAL
, 3600);
226 addRecordToLW(res
, aroot
.toString(), QType::AAAA
, newAAAA
, DNSResourceRecord::ADDITIONAL
, 3600);
228 return LWResult::Result::Success
;
230 return LWResult::Result::Timeout
;
233 sr
->setAsyncCallback(asynccb
);
236 Utility::gettimeofday(&now
, nullptr);
238 vector
<DNSRecord
> ret
;
239 int res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
240 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
241 BOOST_REQUIRE_EQUAL(ret
.size(), 13U);
242 BOOST_CHECK_EQUAL(queriesCount
, 1U);
245 time_t cached
= g_recCache
->get(now
.tv_sec
, aroot
, QType::A
, MemRecursorCache::None
, &ret
, ComboAddress());
246 BOOST_CHECK(cached
> 0);
247 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
248 BOOST_CHECK(getRR
<ARecordContent
>(ret
[0])->getCA() == ComboAddress(newA
));
251 cached
= g_recCache
->get(now
.tv_sec
, aroot
, QType::AAAA
, MemRecursorCache::None
, &ret
, ComboAddress());
252 BOOST_CHECK(cached
> 0);
253 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
254 BOOST_CHECK(getRR
<AAAARecordContent
>(ret
[0])->getCA() == ComboAddress(newAAAA
));
257 static void test_edns_formerr_fallback_f(bool sample
)
259 std::unique_ptr
<SyncRes
> sr
;
262 sr
->setQNameMinimization();
264 ComboAddress noEDNSServer
;
265 size_t queriesWithEDNS
= 0;
266 size_t queriesWithoutEDNS
= 0;
268 sr
->setAsyncCallback([&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 */) {
269 if (EDNS0Level
!= 0) {
273 setLWResult(res
, RCode::FormErr
);
274 return LWResult::Result::Success
;
277 queriesWithoutEDNS
++;
279 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& !doTCP
) {
280 setLWResult(res
, 0, true, false, false);
281 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
282 return LWResult::Result::Success
;
285 return sample
? basicRecordsForQnameMinimization(res
, domain
, type
) : LWResult::Result::Timeout
;
290 /* fake that the root NS doesn't handle EDNS, check that we fallback */
291 vector
<DNSRecord
> ret
;
292 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
293 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
294 BOOST_CHECK_EQUAL(ret
.size(), 1U);
295 BOOST_CHECK_EQUAL(queriesWithEDNS
, sample
? 3U : 1U);
296 BOOST_CHECK_EQUAL(queriesWithoutEDNS
, sample
? 4U : 1U);
297 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), sample
? 3U : 1U);
298 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(noEDNSServer
), SyncRes::EDNSStatus::NOEDNS
);
301 BOOST_AUTO_TEST_CASE(test_edns_formerr_fallback
)
303 test_edns_formerr_fallback_f(false);
306 BOOST_AUTO_TEST_CASE(test_edns_formerr_fallback_qmin
)
308 // DISABLED UNTIL QNAME MINIMIZATION IS THERE
310 test_edns_formerr_fallback_f(true);
313 BOOST_AUTO_TEST_CASE(test_edns_formerr_but_edns_enabled
)
315 std::unique_ptr
<SyncRes
> sr
;
318 /* in this test, the auth answers with FormErr to an EDNS-enabled
319 query, but the response does contain EDNS so we should not mark
320 it as EDNS ignorant or intolerant.
322 size_t queriesWithEDNS
= 0;
323 size_t queriesWithoutEDNS
= 0;
324 std::set
<ComboAddress
> usedServers
;
326 sr
->setAsyncCallback([&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 */) {
327 if (EDNS0Level
> 0) {
331 queriesWithoutEDNS
++;
333 usedServers
.insert(ip
);
335 if (type
== QType::DNAME
) {
336 setLWResult(res
, RCode::FormErr
);
337 if (EDNS0Level
> 0) {
338 res
->d_haveEDNS
= true;
340 return LWResult::Result::Success
;
343 return LWResult::Result::Timeout
;
348 vector
<DNSRecord
> ret
;
349 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::DNAME
), QClass::IN
, ret
);
350 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
351 BOOST_CHECK_EQUAL(ret
.size(), 0U);
352 BOOST_CHECK_EQUAL(queriesWithEDNS
, 26U);
353 BOOST_CHECK_EQUAL(queriesWithoutEDNS
, 0U);
354 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), 0U);
355 BOOST_CHECK_EQUAL(usedServers
.size(), 26U);
356 for (const auto& server
: usedServers
) {
357 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
361 BOOST_AUTO_TEST_CASE(test_meta_types
)
363 std::unique_ptr
<SyncRes
> sr
;
366 static const std::set
<uint16_t> invalidTypes
= {128, QType::AXFR
, QType::IXFR
, QType::RRSIG
, QType::NSEC3
, QType::OPT
, QType::TSIG
, QType::TKEY
, QType::MAILA
, QType::MAILB
, 65535};
368 for (const auto qtype
: invalidTypes
) {
369 size_t queriesCount
= 0;
371 sr
->setAsyncCallback([&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 */) {
373 return LWResult::Result::Timeout
;
378 vector
<DNSRecord
> ret
;
379 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(qtype
), QClass::IN
, ret
);
380 BOOST_CHECK_EQUAL(res
, -1);
381 BOOST_CHECK_EQUAL(ret
.size(), 0U);
382 BOOST_CHECK_EQUAL(queriesCount
, 0U);
386 BOOST_AUTO_TEST_CASE(test_tc_fallback_to_tcp
)
388 std::unique_ptr
<SyncRes
> sr
;
391 sr
->setAsyncCallback([](const ComboAddress
& /* ip */, const DNSName
& domain
, int type
, bool doTCP
, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval
* /* now */, boost::optional
<Netmask
>& /* srcmask */, boost::optional
<const ResolveContext
&> /* context */, LWResult
* res
, bool* /* chained */) {
393 setLWResult(res
, 0, false, true, false);
394 return LWResult::Result::Success
;
396 if (domain
== DNSName("powerdns.com") && type
== QType::A
&& doTCP
) {
397 setLWResult(res
, 0, true, false, false);
398 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
399 return LWResult::Result::Success
;
402 return LWResult::Result::Timeout
;
407 /* fake that the NS truncates every request over UDP, we should fallback to TCP */
408 vector
<DNSRecord
> ret
;
409 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
410 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
413 BOOST_AUTO_TEST_CASE(test_tc_over_tcp
)
415 std::unique_ptr
<SyncRes
> sr
;
418 size_t tcpQueriesCount
= 0;
420 sr
->setAsyncCallback([&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 */) {
422 setLWResult(res
, 0, true, true, false);
423 return LWResult::Result::Success
;
426 /* first TCP query is answered with a TC response */
428 if (tcpQueriesCount
== 1) {
429 setLWResult(res
, 0, true, true, false);
432 setLWResult(res
, 0, true, false, false);
435 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
436 return LWResult::Result::Success
;
441 vector
<DNSRecord
> ret
;
442 int res
= sr
->beginResolve(DNSName("powerdns.com."), QType(QType::A
), QClass::IN
, ret
);
443 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
444 BOOST_CHECK_EQUAL(tcpQueriesCount
, 2U);
447 BOOST_AUTO_TEST_CASE(test_all_nss_down
)
449 std::unique_ptr
<SyncRes
> sr
;
451 std::set
<ComboAddress
> downServers
;
455 sr
->setAsyncCallback([&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 */) {
456 if (isRootServer(ip
)) {
457 setLWResult(res
, 0, false, false, true);
458 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
459 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
460 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
461 return LWResult::Result::Success
;
463 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
464 setLWResult(res
, 0, false, false, true);
465 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
466 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
467 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
468 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
469 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
470 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
471 return LWResult::Result::Success
;
474 downServers
.insert(ip
);
475 return LWResult::Result::Timeout
;
479 DNSName
target("powerdns.com.");
481 vector
<DNSRecord
> ret
;
482 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
483 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
484 BOOST_CHECK_EQUAL(ret
.size(), 0U);
485 BOOST_CHECK_EQUAL(downServers
.size(), 4U);
487 time_t now
= sr
->getNow().tv_sec
;
488 for (const auto& server
: downServers
) {
489 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1U);
490 BOOST_CHECK(SyncRes::isThrottled(now
, server
, target
, QType::A
));
494 BOOST_AUTO_TEST_CASE(test_all_nss_network_error
)
496 std::unique_ptr
<SyncRes
> sr
;
498 std::set
<ComboAddress
> downServers
;
502 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 */) {
503 if (isRootServer(ip
)) {
504 setLWResult(res
, 0, false, false, true);
505 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
506 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
507 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
508 return LWResult::Result::Success
;
510 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
511 setLWResult(res
, 0, false, false, true);
512 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
513 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
514 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
515 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
516 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
517 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
518 return LWResult::Result::Success
;
521 downServers
.insert(ip
);
522 return LWResult::Result::Timeout
;
526 /* exact same test than the previous one, except instead of a time out we fake a network error */
527 DNSName
target("powerdns.com.");
529 vector
<DNSRecord
> ret
;
530 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
531 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
532 BOOST_CHECK_EQUAL(ret
.size(), 0U);
533 BOOST_CHECK_EQUAL(downServers
.size(), 4U);
535 time_t now
= sr
->getNow().tv_sec
;
536 for (const auto& server
: downServers
) {
537 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 1U);
538 BOOST_CHECK(SyncRes::isThrottled(now
, server
, target
, QType::A
));
542 BOOST_AUTO_TEST_CASE(test_all_nss_send_tc_then_garbage_over_tcp
)
544 std::unique_ptr
<SyncRes
> sr
;
549 std::set
<ComboAddress
> downServers
;
551 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 */) {
552 if (isRootServer(ip
)) {
553 setLWResult(res
, 0, false, false, true);
554 addRecordToLW(res
, "lock-up.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
555 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
556 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
557 return LWResult::Result::Success
;
561 setLWResult(res
, 0, false, true, false);
562 return LWResult::Result::Success
;
565 downServers
.insert(ip
);
567 setLWResult(res
, RCode::FormErr
, false, false, false);
568 res
->d_validpacket
= false;
569 return LWResult::Result::Success
;
573 DNSName
target("www.lock-up.");
575 vector
<DNSRecord
> ret
;
576 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
577 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
578 BOOST_CHECK_EQUAL(ret
.size(), 0U);
579 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
581 for (const auto& server
: downServers
) {
582 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
583 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 1000000U);
587 BOOST_AUTO_TEST_CASE(test_all_nss_send_garbage_over_udp
)
589 std::unique_ptr
<SyncRes
> sr
;
594 std::set
<ComboAddress
> downServers
;
595 size_t queriesCount
= 0;
597 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 */) {
598 if (isRootServer(ip
)) {
599 setLWResult(res
, 0, false, false, true);
600 addRecordToLW(res
, "lock-up.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
601 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
602 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
603 return LWResult::Result::Success
;
607 downServers
.insert(ip
);
609 setLWResult(res
, RCode::FormErr
, false, false, false);
610 res
->d_validpacket
= false;
611 return LWResult::Result::Success
;
614 DNSName
target("www.lock-up.");
616 vector
<DNSRecord
> ret
;
617 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
618 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
619 BOOST_CHECK_EQUAL(ret
.size(), 0U);
620 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
621 /* two queries with EDNS, that's it */
622 BOOST_CHECK_EQUAL(queriesCount
, 2U);
624 for (const auto& server
: downServers
) {
625 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
626 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 1000000U);
627 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSIGNORANT
);
631 BOOST_AUTO_TEST_CASE(test_regular_ns_send_refused
)
633 std::unique_ptr
<SyncRes
> sr
;
638 std::set
<ComboAddress
> downServers
;
639 size_t queriesCount
= 0;
641 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 */) {
642 if (isRootServer(ip
)) {
643 setLWResult(res
, 0, false, false, true);
644 addRecordToLW(res
, "refused.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
645 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
646 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
647 return LWResult::Result::Success
;
651 downServers
.insert(ip
);
653 setLWResult(res
, RCode::Refused
, false, false, true);
655 return LWResult::Result::Success
;
658 DNSName
target("www.refused.");
660 vector
<DNSRecord
> ret
;
661 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
662 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
663 BOOST_CHECK_EQUAL(ret
.size(), 0U);
664 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
665 BOOST_CHECK_EQUAL(queriesCount
, 2U);
667 for (const auto& server
: downServers
) {
668 /* same as any other server */
669 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
670 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 0U);
671 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
675 BOOST_AUTO_TEST_CASE(test_forward_ns_send_refused
)
677 std::unique_ptr
<SyncRes
> sr
;
682 std::set
<ComboAddress
> downServers
;
683 size_t queriesCount
= 0;
685 const DNSName
target("www.refused.");
687 SyncRes::AuthDomain ad
;
688 const std::vector
<ComboAddress
> forwardedNSs
{ComboAddress("192.0.2.42:53"), ComboAddress("192.0.2.43:53")};
689 ad
.d_rdForward
= false;
690 ad
.d_servers
= forwardedNSs
;
691 (*SyncRes::t_sstorage
.domainmap
)[target
] = ad
;
693 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 */) {
694 if (isRootServer(ip
)) {
695 setLWResult(res
, 0, false, false, true);
696 addRecordToLW(res
, "refused.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
697 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
698 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
699 return LWResult::Result::Success
;
703 downServers
.insert(ip
);
705 setLWResult(res
, RCode::Refused
, false, false, true);
707 return LWResult::Result::Success
;
710 vector
<DNSRecord
> ret
;
711 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
712 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
713 BOOST_CHECK_EQUAL(ret
.size(), 0U);
714 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
715 BOOST_CHECK_EQUAL(queriesCount
, 2U);
717 for (const auto& server
: forwardedNSs
) {
718 BOOST_CHECK_EQUAL(downServers
.count(server
), 1U);
719 /* same as any other server */
720 BOOST_CHECK(SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
721 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName("a.gtld-servers.net."), server
), 0U);
722 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
726 BOOST_AUTO_TEST_CASE(test_forward_ns_send_servfail
)
728 std::unique_ptr
<SyncRes
> sr
;
733 std::set
<ComboAddress
> downServers
;
734 size_t queriesCount
= 0;
736 const DNSName
target("www.refused.");
738 SyncRes::AuthDomain ad
;
739 const std::vector
<ComboAddress
> forwardedNSs
{ComboAddress("192.0.2.42:53"), ComboAddress("192.0.2.43:53")};
740 ad
.d_rdForward
= false;
741 ad
.d_servers
= forwardedNSs
;
742 (*SyncRes::t_sstorage
.domainmap
)[DNSName("refused.")] = ad
;
744 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 */) {
745 if (isRootServer(ip
)) {
746 setLWResult(res
, 0, false, false, true);
747 addRecordToLW(res
, "refused.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
748 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
749 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
750 return LWResult::Result::Success
;
754 downServers
.insert(ip
);
756 setLWResult(res
, RCode::ServFail
, false, false, true);
758 return LWResult::Result::Success
;
761 vector
<DNSRecord
> ret
;
762 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
763 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
764 BOOST_CHECK_EQUAL(ret
.size(), 0U);
765 BOOST_CHECK_EQUAL(downServers
.size(), 2U);
766 BOOST_CHECK_EQUAL(queriesCount
, 2U);
768 for (const auto& server
: forwardedNSs
) {
769 BOOST_CHECK_EQUAL(downServers
.count(server
), 1U);
770 /* on servfail from a server we forward to we only increase the NS speed so
771 that a different server might be tried instead, but we don't throttle */
772 BOOST_CHECK(!SyncRes::isThrottled(time(nullptr), server
, target
, QType::A
));
773 BOOST_CHECK_EQUAL(SyncRes::getNSSpeed(DNSName(server
.toStringWithPort()), server
), 1000000U);
774 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatus(server
), SyncRes::EDNSStatus::EDNSOK
);
778 BOOST_AUTO_TEST_CASE(test_only_one_ns_up_resolving_itself_with_glue
)
780 std::unique_ptr
<SyncRes
> sr
;
785 DNSName
target("www.powerdns.com.");
787 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 */) {
788 if (isRootServer(ip
)) {
789 setLWResult(res
, 0, false, false, true);
790 if (domain
== target
) {
791 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
792 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.net.", DNSResourceRecord::AUTHORITY
, 172800);
793 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
794 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
796 else if (domain
== DNSName("pdns-public-ns2.powerdns.net.")) {
797 addRecordToLW(res
, "powerdns.net.", QType::NS
, "pdns-public-ns2.powerdns.net.", DNSResourceRecord::AUTHORITY
, 172800);
798 addRecordToLW(res
, "powerdns.net.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
799 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
800 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
802 return LWResult::Result::Success
;
804 else if (ip
== ComboAddress("192.0.2.3:53")) {
805 setLWResult(res
, 0, true, false, true);
806 if (domain
== DNSName("pdns-public-ns2.powerdns.net.")) {
807 if (type
== QType::A
) {
808 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::A
, "192.0.2.3");
810 else if (type
== QType::AAAA
) {
811 addRecordToLW(res
, "pdns-public-ns2.powerdns.net.", QType::AAAA
, "2001:DB8::3");
814 else if (domain
== target
) {
815 if (type
== QType::A
) {
816 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1");
818 else if (type
== QType::AAAA
) {
819 addRecordToLW(res
, domain
, QType::AAAA
, "2001:DB8::1");
822 return LWResult::Result::Success
;
824 return LWResult::Result::Timeout
;
827 vector
<DNSRecord
> ret
;
828 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
829 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
830 BOOST_CHECK_EQUAL(ret
.size(), 1U);
833 BOOST_AUTO_TEST_CASE(test_os_limit_errors
)
835 std::unique_ptr
<SyncRes
> sr
;
837 std::set
<ComboAddress
> downServers
;
841 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 */) {
842 if (isRootServer(ip
)) {
843 setLWResult(res
, 0, false, false, true);
844 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
845 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
846 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
847 return LWResult::Result::Success
;
849 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
850 setLWResult(res
, 0, false, false, true);
851 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
852 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
853 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
854 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
855 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
856 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
857 return LWResult::Result::Success
;
860 if (downServers
.size() < 3) {
861 /* only the last one will answer */
862 downServers
.insert(ip
);
863 return LWResult::Result::OSLimitError
;
866 setLWResult(res
, 0, true, false, true);
867 addRecordToLW(res
, "powerdns.com.", QType::A
, "192.0.2.42");
868 return LWResult::Result::Success
;
873 DNSName
target("powerdns.com.");
875 vector
<DNSRecord
> ret
;
876 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
877 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
878 BOOST_CHECK_EQUAL(ret
.size(), 1U);
879 BOOST_CHECK_EQUAL(downServers
.size(), 3U);
881 /* Error is reported as "OS limit error" (-2) so the servers should _NOT_ be marked down */
882 time_t now
= sr
->getNow().tv_sec
;
883 for (const auto& server
: downServers
) {
884 BOOST_CHECK_EQUAL(SyncRes::getServerFailsCount(server
), 0U);
885 BOOST_CHECK(!SyncRes::isThrottled(now
, server
, target
, QType::A
));
889 BOOST_AUTO_TEST_CASE(test_glued_referral
)
891 std::unique_ptr
<SyncRes
> sr
;
896 const DNSName
target("powerdns.com.");
898 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 */) {
899 /* this will cause issue with qname minimization if we ever implement it */
900 if (domain
!= target
) {
901 return LWResult::Result::Timeout
;
904 if (isRootServer(ip
)) {
905 setLWResult(res
, 0, false, false, true);
906 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
907 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
908 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
909 return LWResult::Result::Success
;
911 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
912 setLWResult(res
, 0, false, false, true);
913 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
914 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
915 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
916 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
917 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
918 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
919 return LWResult::Result::Success
;
921 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")) {
922 setLWResult(res
, 0, true, false, true);
923 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
924 return LWResult::Result::Success
;
927 return LWResult::Result::Timeout
;
931 vector
<DNSRecord
> ret
;
932 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
933 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
934 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
935 BOOST_CHECK(ret
[0].d_type
== QType::A
);
936 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
939 BOOST_AUTO_TEST_CASE(test_glueless_referral
)
941 std::unique_ptr
<SyncRes
> sr
;
946 const DNSName
target("powerdns.com.");
948 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 */) {
949 if (isRootServer(ip
)) {
950 setLWResult(res
, 0, false, false, true);
952 if (domain
.isPartOf(DNSName("com."))) {
953 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
955 else if (domain
.isPartOf(DNSName("org."))) {
956 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
959 setLWResult(res
, RCode::NXDomain
, false, false, true);
960 return LWResult::Result::Success
;
963 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
964 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
965 return LWResult::Result::Success
;
967 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
968 if (domain
== target
) {
969 setLWResult(res
, 0, false, false, true);
970 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
971 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
972 return LWResult::Result::Success
;
974 else if (domain
== DNSName("pdns-public-ns1.powerdns.org.")) {
975 setLWResult(res
, 0, true, false, true);
976 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2");
977 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::AAAA
, "2001:DB8::2");
978 return LWResult::Result::Success
;
980 else if (domain
== DNSName("pdns-public-ns2.powerdns.org.")) {
981 setLWResult(res
, 0, true, false, true);
982 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::A
, "192.0.2.3");
983 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::AAAA
, "2001:DB8::3");
984 return LWResult::Result::Success
;
987 setLWResult(res
, RCode::NXDomain
, false, false, true);
988 return LWResult::Result::Success
;
990 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")) {
991 setLWResult(res
, 0, true, false, true);
992 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
993 return LWResult::Result::Success
;
996 return LWResult::Result::Timeout
;
1000 vector
<DNSRecord
> ret
;
1001 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1002 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1003 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1004 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1005 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1008 BOOST_AUTO_TEST_CASE(test_endless_glueless_referral
)
1010 std::unique_ptr
<SyncRes
> sr
;
1015 const DNSName
target("powerdns.com.");
1018 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 */) {
1019 if (isRootServer(ip
)) {
1020 setLWResult(res
, 0, false, false, true);
1022 if (domain
.isPartOf(DNSName("com."))) {
1023 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1025 else if (domain
.isPartOf(DNSName("org."))) {
1026 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1029 setLWResult(res
, RCode::NXDomain
, false, false, true);
1030 return LWResult::Result::Success
;
1033 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1034 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1035 return LWResult::Result::Success
;
1037 if (domain
== target
) {
1038 setLWResult(res
, 0, false, false, true);
1039 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1040 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1041 return LWResult::Result::Success
;
1043 setLWResult(res
, 0, false, false, true);
1044 addRecordToLW(res
, domain
, QType::NS
, std::to_string(count
) + ".ns1.powerdns.org", DNSResourceRecord::AUTHORITY
, 172800);
1045 addRecordToLW(res
, domain
, QType::NS
, std::to_string(count
) + ".ns2.powerdns.org", DNSResourceRecord::AUTHORITY
, 172800);
1047 return LWResult::Result::Success
;
1050 vector
<DNSRecord
> ret
;
1051 BOOST_CHECK_EXCEPTION(sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
),
1052 ImmediateServFailException
,
1053 [](const ImmediateServFailException
& isfe
) {
1054 return isfe
.reason
.substr(0, 9) == "More than";
1058 BOOST_AUTO_TEST_CASE(test_glueless_referral_aaaa_task
)
1060 std::unique_ptr
<SyncRes
> sr
;
1065 const DNSName
target("powerdns.com.");
1067 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 */) {
1068 if (isRootServer(ip
)) {
1069 setLWResult(res
, 0, false, false, true);
1071 if (domain
.isPartOf(DNSName("com."))) {
1072 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1074 else if (domain
.isPartOf(DNSName("org."))) {
1075 addRecordToLW(res
, "org.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1078 setLWResult(res
, RCode::NXDomain
, false, false, true);
1079 return LWResult::Result::Success
;
1082 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1083 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1084 return LWResult::Result::Success
;
1086 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
1087 if (domain
== target
) {
1088 setLWResult(res
, 0, false, false, true);
1089 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1090 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
1091 return LWResult::Result::Success
;
1093 else if (domain
== DNSName("pdns-public-ns1.powerdns.org.")) {
1094 setLWResult(res
, 0, true, false, true);
1095 if (type
== QType::A
) {
1096 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::A
, "192.0.2.2");
1099 addRecordToLW(res
, "pdns-public-ns1.powerdns.org.", QType::AAAA
, "2001:DB8::2");
1101 return LWResult::Result::Success
;
1103 else if (domain
== DNSName("pdns-public-ns2.powerdns.org.")) {
1104 setLWResult(res
, 0, true, false, true);
1105 if (type
== QType::A
) {
1106 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::A
, "192.0.2.3");
1109 addRecordToLW(res
, "pdns-public-ns2.powerdns.org.", QType::AAAA
, "2001:DB8::3");
1111 return LWResult::Result::Success
;
1114 setLWResult(res
, RCode::NXDomain
, false, false, true);
1115 return LWResult::Result::Success
;
1117 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")) {
1118 setLWResult(res
, 0, true, false, true);
1119 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
1120 return LWResult::Result::Success
;
1123 return LWResult::Result::Timeout
;
1127 vector
<DNSRecord
> ret
;
1128 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1129 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1130 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1131 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1132 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1134 // One task should be submitted
1135 BOOST_REQUIRE_EQUAL(getTaskSize(), 1U);
1136 auto task
= taskQueuePop();
1137 BOOST_CHECK(task
.d_qname
== DNSName("pdns-public-ns1.powerdns.org") || task
.d_qname
== DNSName("pdns-public-ns2.powerdns.org"));
1138 BOOST_CHECK_EQUAL(task
.d_qtype
, QType::AAAA
);
1141 BOOST_AUTO_TEST_CASE(test_edns_subnet_by_domain
)
1143 std::unique_ptr
<SyncRes
> sr
;
1148 const DNSName
target("powerdns.com.");
1149 SyncRes::addEDNSDomain(target
);
1151 EDNSSubnetOpts incomingECS
;
1152 incomingECS
.source
= Netmask("192.0.2.128/32");
1153 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1155 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 */) {
1156 BOOST_REQUIRE(srcmask
);
1157 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1159 if (isRootServer(ip
)) {
1160 setLWResult(res
, 0, false, false, true);
1161 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1162 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1164 /* this one did not use the ECS info */
1165 srcmask
= boost::none
;
1167 return LWResult::Result::Success
;
1169 else if (ip
== ComboAddress("192.0.2.1:53")) {
1171 setLWResult(res
, 0, true, false, false);
1172 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1174 /* this one did, but only up to a precision of /16, not the full /24 */
1175 srcmask
= Netmask("192.0.0.0/16");
1177 return LWResult::Result::Success
;
1180 return LWResult::Result::Timeout
;
1183 SyncRes::s_ecsqueries
= 0;
1184 SyncRes::s_ecsresponses
= 0;
1185 vector
<DNSRecord
> ret
;
1186 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1187 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1188 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1189 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1190 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1191 BOOST_CHECK_EQUAL(SyncRes::s_ecsqueries
, 2U);
1192 BOOST_CHECK_EQUAL(SyncRes::s_ecsresponses
, 1U);
1193 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize4
) {
1194 BOOST_CHECK_EQUAL(entry
.second
, entry
.first
== 15 ? 1U : 0U);
1196 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize6
) {
1197 BOOST_CHECK_EQUAL(entry
.second
, 0U);
1201 BOOST_AUTO_TEST_CASE(test_edns_subnet_by_addr
)
1203 std::unique_ptr
<SyncRes
> sr
;
1208 const DNSName
target("powerdns.com.");
1209 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1211 EDNSSubnetOpts incomingECS
;
1212 incomingECS
.source
= Netmask("2001:DB8::FF/128");
1213 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1215 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 */) {
1216 if (isRootServer(ip
)) {
1217 BOOST_REQUIRE(!srcmask
);
1219 setLWResult(res
, 0, false, false, true);
1220 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1221 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1222 return LWResult::Result::Success
;
1224 else if (ip
== ComboAddress("192.0.2.1:53")) {
1226 BOOST_REQUIRE(srcmask
);
1227 BOOST_CHECK_EQUAL(srcmask
->toString(), "2001:db8::/56");
1229 setLWResult(res
, 0, true, false, false);
1230 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1231 return LWResult::Result::Success
;
1234 return LWResult::Result::Timeout
;
1237 SyncRes::s_ecsqueries
= 0;
1238 SyncRes::s_ecsresponses
= 0;
1239 vector
<DNSRecord
> ret
;
1240 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1241 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1242 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1243 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1244 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1245 BOOST_CHECK_EQUAL(SyncRes::s_ecsqueries
, 1U);
1246 BOOST_CHECK_EQUAL(SyncRes::s_ecsresponses
, 1U);
1247 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize4
) {
1248 BOOST_CHECK_EQUAL(entry
.second
, 0u);
1250 for (const auto& entry
: SyncRes::s_ecsResponsesBySubnetSize6
) {
1251 BOOST_CHECK_EQUAL(entry
.second
, entry
.first
== 55 ? 1U : 0U);
1255 BOOST_AUTO_TEST_CASE(test_ecs_use_requestor
)
1257 std::unique_ptr
<SyncRes
> sr
;
1262 const DNSName
target("powerdns.com.");
1263 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1264 // No incoming ECS data
1265 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::none
);
1267 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 */) {
1268 if (isRootServer(ip
)) {
1269 BOOST_REQUIRE(!srcmask
);
1271 setLWResult(res
, 0, false, false, true);
1272 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1273 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1274 return LWResult::Result::Success
;
1276 else if (ip
== ComboAddress("192.0.2.1:53")) {
1278 BOOST_REQUIRE(srcmask
);
1279 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1281 setLWResult(res
, 0, true, false, false);
1282 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1283 return LWResult::Result::Success
;
1286 return LWResult::Result::Timeout
;
1289 vector
<DNSRecord
> ret
;
1290 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1291 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1292 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1293 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1294 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1297 BOOST_AUTO_TEST_CASE(test_ecs_use_scope_zero
)
1299 std::unique_ptr
<SyncRes
> sr
;
1304 const DNSName
target("powerdns.com.");
1305 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1306 SyncRes::clearEDNSLocalSubnets();
1307 SyncRes::addEDNSLocalSubnet("192.0.2.254/32");
1308 // No incoming ECS data, Requestor IP not in ecs-add-for
1309 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::none
);
1311 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 */) {
1312 if (isRootServer(ip
)) {
1313 BOOST_REQUIRE(!srcmask
);
1315 setLWResult(res
, 0, false, false, true);
1316 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1317 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1318 return LWResult::Result::Success
;
1320 else if (ip
== ComboAddress("192.0.2.1:53")) {
1322 BOOST_REQUIRE(srcmask
);
1323 BOOST_CHECK_EQUAL(srcmask
->toString(), "127.0.0.1/32");
1325 setLWResult(res
, 0, true, false, false);
1326 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1327 return LWResult::Result::Success
;
1330 return LWResult::Result::Timeout
;
1333 vector
<DNSRecord
> ret
;
1334 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1335 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1336 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1337 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1338 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1341 BOOST_AUTO_TEST_CASE(test_ecs_honor_incoming_mask
)
1343 std::unique_ptr
<SyncRes
> sr
;
1348 const DNSName
target("powerdns.com.");
1349 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1350 SyncRes::clearEDNSLocalSubnets();
1351 SyncRes::addEDNSLocalSubnet("192.0.2.254/32");
1352 EDNSSubnetOpts incomingECS
;
1353 incomingECS
.source
= Netmask("192.0.0.0/16");
1354 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1356 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 */) {
1357 if (isRootServer(ip
)) {
1358 BOOST_REQUIRE(!srcmask
);
1360 setLWResult(res
, 0, false, false, true);
1361 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1362 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1363 return LWResult::Result::Success
;
1365 else if (ip
== ComboAddress("192.0.2.1:53")) {
1367 BOOST_REQUIRE(srcmask
);
1368 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.0.0/16");
1370 setLWResult(res
, 0, true, false, false);
1371 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1372 return LWResult::Result::Success
;
1375 return LWResult::Result::Timeout
;
1378 vector
<DNSRecord
> ret
;
1379 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1380 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1381 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1382 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1383 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1386 BOOST_AUTO_TEST_CASE(test_ecs_honor_incoming_mask_zero
)
1388 std::unique_ptr
<SyncRes
> sr
;
1393 const DNSName
target("powerdns.com.");
1394 SyncRes::addEDNSRemoteSubnet("192.0.2.1/32");
1395 SyncRes::clearEDNSLocalSubnets();
1396 SyncRes::addEDNSLocalSubnet("192.0.2.254/32");
1397 EDNSSubnetOpts incomingECS
;
1398 incomingECS
.source
= Netmask("0.0.0.0/0");
1399 sr
->setQuerySource(ComboAddress("192.0.2.127"), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1401 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 */) {
1402 if (isRootServer(ip
)) {
1403 BOOST_REQUIRE(!srcmask
);
1405 setLWResult(res
, 0, false, false, true);
1406 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1407 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1408 return LWResult::Result::Success
;
1410 else if (ip
== ComboAddress("192.0.2.1:53")) {
1412 BOOST_REQUIRE(srcmask
);
1413 BOOST_CHECK_EQUAL(srcmask
->toString(), "127.0.0.1/32");
1415 setLWResult(res
, 0, true, false, false);
1416 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1417 return LWResult::Result::Success
;
1420 return LWResult::Result::Timeout
;
1423 vector
<DNSRecord
> ret
;
1424 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1425 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1426 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1427 BOOST_CHECK(ret
[0].d_type
== QType::A
);
1428 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1431 BOOST_AUTO_TEST_CASE(test_following_cname
)
1433 std::unique_ptr
<SyncRes
> sr
;
1438 const DNSName
target("cname.powerdns.com.");
1439 const DNSName
cnameTarget("cname-target.powerdns.com");
1441 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 */) {
1442 if (isRootServer(ip
)) {
1443 setLWResult(res
, 0, false, false, true);
1444 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1445 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1446 return LWResult::Result::Success
;
1448 else if (ip
== ComboAddress("192.0.2.1:53")) {
1450 if (domain
== target
) {
1451 setLWResult(res
, 0, true, false, false);
1452 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1453 return LWResult::Result::Success
;
1455 else if (domain
== cnameTarget
) {
1456 setLWResult(res
, 0, true, false, false);
1457 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1460 return LWResult::Result::Success
;
1463 return LWResult::Result::Timeout
;
1466 vector
<DNSRecord
> ret
;
1467 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1468 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1469 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1470 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1471 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1472 BOOST_CHECK(ret
[1].d_type
== QType::A
);
1473 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1476 BOOST_AUTO_TEST_CASE(test_cname_nxdomain
)
1478 std::unique_ptr
<SyncRes
> sr
;
1483 const DNSName
target("cname.powerdns.com.");
1484 const DNSName
cnameTarget("cname-target.powerdns.com");
1486 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 */) {
1487 if (isRootServer(ip
)) {
1488 setLWResult(res
, 0, false, false, true);
1489 addRecordToLW(res
, "powerdns.com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1490 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1491 return LWResult::Result::Success
;
1493 else if (ip
== ComboAddress("192.0.2.1:53")) {
1495 if (domain
== target
) {
1496 setLWResult(res
, RCode::NXDomain
, true, false, false);
1497 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1498 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1500 else if (domain
== cnameTarget
) {
1501 setLWResult(res
, RCode::NXDomain
, true, false, false);
1502 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "a.powerdns.com. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1503 return LWResult::Result::Success
;
1506 return LWResult::Result::Success
;
1509 return LWResult::Result::Timeout
;
1512 vector
<DNSRecord
> ret
;
1513 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1514 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1515 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1516 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1517 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1518 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1520 /* a second time, to check the cache */
1522 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1523 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
1524 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1525 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1526 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1527 BOOST_CHECK(ret
[1].d_type
== QType::SOA
);
1530 BOOST_AUTO_TEST_CASE(test_included_poisonous_cname
)
1532 std::unique_ptr
<SyncRes
> sr
;
1537 /* In this test we directly get the NS server for cname.powerdns.com.,
1538 and we don't know whether it's also authoritative for
1539 cname-target.powerdns.com or powerdns.com, so we shouldn't accept
1540 the additional A record for cname-target.powerdns.com. */
1541 const DNSName
target("cname.powerdns.com.");
1542 const DNSName
cnameTarget("cname-target.powerdns.com");
1544 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 */) {
1545 if (isRootServer(ip
)) {
1547 setLWResult(res
, 0, false, false, true);
1549 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1550 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1551 return LWResult::Result::Success
;
1553 else if (ip
== ComboAddress("192.0.2.1:53")) {
1555 if (domain
== target
) {
1556 setLWResult(res
, 0, true, false, false);
1557 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1558 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
);
1559 return LWResult::Result::Success
;
1561 else if (domain
== cnameTarget
) {
1562 setLWResult(res
, 0, true, false, false);
1563 addRecordToLW(res
, cnameTarget
, QType::A
, "192.0.2.3");
1564 return LWResult::Result::Success
;
1567 return LWResult::Result::Success
;
1570 return LWResult::Result::Timeout
;
1573 vector
<DNSRecord
> ret
;
1574 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1575 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1576 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
1577 BOOST_REQUIRE(ret
[0].d_type
== QType::CNAME
);
1578 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1579 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[0])->getTarget(), cnameTarget
);
1580 BOOST_REQUIRE(ret
[1].d_type
== QType::A
);
1581 BOOST_CHECK_EQUAL(ret
[1].d_name
, cnameTarget
);
1582 BOOST_CHECK(getRR
<ARecordContent
>(ret
[1])->getCA() == ComboAddress("192.0.2.3"));
1585 BOOST_AUTO_TEST_CASE(test_cname_loop
)
1587 std::unique_ptr
<SyncRes
> sr
;
1593 const DNSName
target("cname.powerdns.com.");
1595 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 */) {
1598 if (isRootServer(ip
)) {
1600 setLWResult(res
, 0, false, false, true);
1601 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1602 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1603 return LWResult::Result::Success
;
1605 else if (ip
== ComboAddress("192.0.2.1:53")) {
1607 if (domain
== target
) {
1608 setLWResult(res
, 0, true, false, false);
1609 addRecordToLW(res
, domain
, QType::CNAME
, domain
.toString());
1610 return LWResult::Result::Success
;
1613 return LWResult::Result::Success
;
1616 return LWResult::Result::Timeout
;
1619 vector
<DNSRecord
> ret
;
1620 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1621 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1622 BOOST_CHECK_EQUAL(ret
.size(), 0U);
1623 BOOST_CHECK_EQUAL(count
, 2U);
1625 // Again to check cache
1627 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1630 catch (const ImmediateServFailException
& ex
) {
1635 BOOST_AUTO_TEST_CASE(test_cname_long_loop
)
1637 std::unique_ptr
<SyncRes
> sr
;
1643 const DNSName
target1("cname1.powerdns.com.");
1644 const DNSName
target2("cname2.powerdns.com.");
1645 const DNSName
target3("cname3.powerdns.com.");
1646 const DNSName
target4("cname4.powerdns.com.");
1648 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 */) {
1651 if (isRootServer(ip
)) {
1653 setLWResult(res
, 0, false, false, true);
1654 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1655 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1656 return LWResult::Result::Success
;
1658 else if (ip
== ComboAddress("192.0.2.1:53")) {
1660 if (domain
== target1
) {
1661 setLWResult(res
, 0, true, false, false);
1662 addRecordToLW(res
, domain
, QType::CNAME
, target2
.toString());
1663 return LWResult::Result::Success
;
1665 else if (domain
== target2
) {
1666 setLWResult(res
, 0, true, false, false);
1667 addRecordToLW(res
, domain
, QType::CNAME
, target3
.toString());
1668 return LWResult::Result::Success
;
1670 else if (domain
== target3
) {
1671 setLWResult(res
, 0, true, false, false);
1672 addRecordToLW(res
, domain
, QType::CNAME
, target4
.toString());
1673 return LWResult::Result::Success
;
1675 else if (domain
== target4
) {
1676 setLWResult(res
, 0, true, false, false);
1677 addRecordToLW(res
, domain
, QType::CNAME
, target1
.toString());
1678 return LWResult::Result::Success
;
1681 return LWResult::Result::Success
;
1684 return LWResult::Result::Timeout
;
1687 vector
<DNSRecord
> ret
;
1688 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1689 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1690 BOOST_CHECK_EQUAL(ret
.size(), 0U);
1691 BOOST_CHECK_EQUAL(count
, 8U);
1693 // And again to check cache
1695 sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
1698 catch (const ImmediateServFailException
& ex
) {
1703 BOOST_AUTO_TEST_CASE(test_cname_length
)
1705 std::unique_ptr
<SyncRes
> sr
;
1711 const DNSName
target("cname.powerdns.com.");
1713 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 */) {
1714 if (isRootServer(ip
)) {
1716 setLWResult(res
, 0, false, false, true);
1717 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1718 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1719 return LWResult::Result::Success
;
1721 else if (ip
== ComboAddress("192.0.2.1:53")) {
1723 setLWResult(res
, 0, true, false, false);
1724 addRecordToLW(res
, domain
, QType::CNAME
, std::to_string(length
) + "-cname.powerdns.com");
1726 return LWResult::Result::Success
;
1729 return LWResult::Result::Timeout
;
1732 vector
<DNSRecord
> ret
;
1733 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1734 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1735 BOOST_CHECK_EQUAL(ret
.size(), length
);
1736 BOOST_CHECK_EQUAL(length
, SyncRes::s_max_CNAMES_followed
+ 1);
1739 BOOST_AUTO_TEST_CASE(test_cname_target_servfail
)
1741 std::unique_ptr
<SyncRes
> resolver
;
1746 const DNSName
target("cname.powerdns.com.");
1747 const DNSName
cnameTarget("cname-target.powerdns.com");
1749 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 */) {
1750 if (isRootServer(ipAddress
)) {
1751 setLWResult(res
, 0, false, false, true);
1752 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1753 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1754 return LWResult::Result::Success
;
1756 if (ipAddress
== ComboAddress("192.0.2.1:53")) {
1758 if (domain
== target
) {
1759 setLWResult(res
, 0, true, false, false);
1760 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1761 return LWResult::Result::Success
;
1763 if (domain
== cnameTarget
) {
1764 return LWResult::Result::PermanentError
;
1767 return LWResult::Result::Success
;
1770 return LWResult::Result::Timeout
;
1773 vector
<DNSRecord
> ret
;
1774 int res
= resolver
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1775 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1776 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1777 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1778 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1781 BOOST_AUTO_TEST_CASE(test_cname_target_servfail_servestale
)
1783 std::unique_ptr
<SyncRes
> resolver
;
1785 MemRecursorCache::s_maxServedStaleExtensions
= 1440;
1789 const DNSName
target("cname.powerdns.com.");
1790 const DNSName
cnameTarget("cname-target.powerdns.com");
1792 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 */) {
1793 if (isRootServer(ipAddress
)) {
1794 setLWResult(res
, 0, false, false, true);
1795 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1796 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1797 return LWResult::Result::Success
;
1799 if (ipAddress
== ComboAddress("192.0.2.1:53")) {
1801 if (domain
== target
) {
1802 setLWResult(res
, 0, true, false, false);
1803 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1804 return LWResult::Result::Success
;
1806 if (domain
== cnameTarget
) {
1807 return LWResult::Result::PermanentError
;
1810 return LWResult::Result::Success
;
1813 return LWResult::Result::Timeout
;
1816 vector
<DNSRecord
> ret
;
1817 int res
= resolver
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1818 // different compared no non-servestale case (returns ServFail), handled by pdns_recursor
1819 BOOST_CHECK_EQUAL(res
, -1);
1820 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1821 BOOST_CHECK(ret
[0].d_type
== QType::CNAME
);
1822 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
1825 BOOST_AUTO_TEST_CASE(test_time_limit
)
1827 std::unique_ptr
<SyncRes
> sr
;
1833 const DNSName
target("cname.powerdns.com.");
1835 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 */) {
1838 if (isRootServer(ip
)) {
1839 setLWResult(res
, 0, false, false, true);
1840 /* Pretend that this query took 2000 ms */
1843 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1844 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1845 return LWResult::Result::Success
;
1847 else if (ip
== ComboAddress("192.0.2.1:53")) {
1849 setLWResult(res
, 0, true, false, false);
1850 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1851 return LWResult::Result::Success
;
1854 return LWResult::Result::Timeout
;
1857 /* Set the maximum time to 1 ms */
1858 SyncRes::s_maxtotusec
= 1000;
1861 vector
<DNSRecord
> ret
;
1862 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1865 catch (const ImmediateServFailException
& e
) {
1867 BOOST_CHECK_EQUAL(queries
, 1U);
1870 BOOST_AUTO_TEST_CASE(test_dname_processing
)
1872 std::unique_ptr
<SyncRes
> sr
;
1877 const DNSName
dnameOwner("powerdns.com");
1878 const DNSName
dnameTarget("powerdns.net");
1880 const DNSName
target("dname.powerdns.com.");
1881 const DNSName
cnameTarget("dname.powerdns.net");
1883 const DNSName
uncachedTarget("dname-uncached.powerdns.com.");
1884 const DNSName
uncachedCNAMETarget("dname-uncached.powerdns.net.");
1886 const DNSName
synthCNAME("cname-uncached.powerdns.com.");
1887 const DNSName
synthCNAMETarget("cname-uncached.powerdns.net.");
1891 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 */) {
1894 if (isRootServer(ip
)) {
1895 if (domain
.isPartOf(dnameOwner
)) {
1896 setLWResult(res
, 0, false, false, true);
1897 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1898 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1899 return LWResult::Result::Success
;
1901 if (domain
.isPartOf(dnameTarget
)) {
1902 setLWResult(res
, 0, false, false, true);
1903 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1904 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1905 return LWResult::Result::Success
;
1908 else if (ip
== ComboAddress("192.0.2.1:53")) {
1909 if (domain
== target
) {
1910 setLWResult(res
, 0, true, false, false);
1911 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
1912 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
1913 return LWResult::Result::Success
;
1916 else if (ip
== ComboAddress("192.0.2.2:53")) {
1917 if (domain
== cnameTarget
) {
1918 setLWResult(res
, 0, true, false, false);
1919 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1921 if (domain
== uncachedCNAMETarget
) {
1922 setLWResult(res
, 0, true, false, false);
1923 addRecordToLW(res
, domain
, QType::A
, "192.0.2.3");
1925 return LWResult::Result::Success
;
1927 return LWResult::Result::Timeout
;
1930 vector
<DNSRecord
> ret
;
1931 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1933 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1934 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
1936 BOOST_CHECK_EQUAL(queries
, 4u);
1938 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1939 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1940 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1942 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
1943 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
1945 BOOST_CHECK(ret
[2].d_type
== QType::A
);
1946 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
1948 // Now check the cache
1950 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1952 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1953 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
1955 BOOST_CHECK_EQUAL(queries
, 4U);
1957 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1958 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1959 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1961 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
1962 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
1964 BOOST_CHECK(ret
[2].d_type
== QType::A
);
1965 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
1967 // Check if we correctly return a synthesized CNAME, should send out just 1 more query
1969 res
= sr
->beginResolve(uncachedTarget
, QType(QType::A
), QClass::IN
, ret
);
1971 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1972 BOOST_CHECK_EQUAL(queries
, 5U);
1974 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1975 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1976 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1978 BOOST_REQUIRE(ret
[1].d_type
== QType::CNAME
);
1979 BOOST_CHECK_EQUAL(ret
[1].d_name
, uncachedTarget
);
1980 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[1])->getTarget(), uncachedCNAMETarget
);
1982 BOOST_CHECK(ret
[2].d_type
== QType::A
);
1983 BOOST_CHECK_EQUAL(ret
[2].d_name
, uncachedCNAMETarget
);
1985 // Check if we correctly return the DNAME from cache when asked
1987 res
= sr
->beginResolve(dnameOwner
, QType(QType::DNAME
), QClass::IN
, ret
);
1988 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1989 BOOST_CHECK_EQUAL(queries
, 5U);
1991 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
1992 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
1993 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
1995 // Check if we correctly return the synthesized CNAME from cache when asked
1997 res
= sr
->beginResolve(synthCNAME
, QType(QType::CNAME
), QClass::IN
, ret
);
1998 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1999 BOOST_CHECK_EQUAL(queries
, 5U);
2001 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2002 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2003 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2005 BOOST_REQUIRE(ret
[1].d_type
== QType::CNAME
);
2006 BOOST_CHECK(ret
[1].d_name
== synthCNAME
);
2007 BOOST_CHECK_EQUAL(getRR
<CNAMERecordContent
>(ret
[1])->getTarget(), synthCNAMETarget
);
2010 BOOST_AUTO_TEST_CASE(test_dname_dnssec_secure
)
2012 std::unique_ptr
<SyncRes
> sr
;
2014 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
2018 const DNSName
dnameOwner("powerdns");
2019 const DNSName
dnameTarget("example");
2021 const DNSName
target("dname.powerdns");
2022 const DNSName
cnameTarget("dname.example");
2026 auto luaconfsCopy
= g_luaconfs
.getCopy();
2027 luaconfsCopy
.dsAnchors
.clear();
2028 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2029 generateKeyMaterial(dnameOwner
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2030 generateKeyMaterial(dnameTarget
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2031 g_luaconfs
.setState(luaconfsCopy
);
2035 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 */) {
2037 /* 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
2038 * As such, we need to do some more work to make the answers correct.
2041 if (isRootServer(ip
)) {
2042 if (domain
.countLabels() == 0 && type
== QType::DNSKEY
) { // .|DNSKEY
2043 setLWResult(res
, 0, true, false, true);
2044 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2045 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2046 return LWResult::Result::Success
;
2048 if (domain
.countLabels() == 1 && type
== QType::DS
) { // powerdns|DS or example|DS
2049 setLWResult(res
, 0, true, false, true);
2050 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
2051 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2052 return LWResult::Result::Success
;
2054 // For the rest, delegate!
2055 if (domain
.isPartOf(dnameOwner
)) {
2056 setLWResult(res
, 0, false, false, true);
2057 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2058 addDS(dnameOwner
, 300, res
->d_records
, keys
);
2059 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2060 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2061 return LWResult::Result::Success
;
2063 if (domain
.isPartOf(dnameTarget
)) {
2064 setLWResult(res
, 0, false, false, true);
2065 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2066 addDS(dnameTarget
, 300, res
->d_records
, keys
);
2067 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2068 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2069 return LWResult::Result::Success
;
2072 else if (ip
== ComboAddress("192.0.2.1:53")) {
2073 if (domain
.countLabels() == 1 && type
== QType::DNSKEY
) { // powerdns|DNSKEY
2074 setLWResult(res
, 0, true, false, true);
2075 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2076 addRRSIG(keys
, res
->d_records
, domain
, 300);
2077 return LWResult::Result::Success
;
2079 if (domain
== target
&& type
== QType::DS
) { // dname.powerdns|DS
2080 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
2082 if (domain
== target
) {
2083 setLWResult(res
, 0, true, false, false);
2084 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2085 addRRSIG(keys
, res
->d_records
, dnameOwner
, 300);
2086 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString()); // CNAME from a DNAME is not signed
2087 return LWResult::Result::Success
;
2090 else if (ip
== ComboAddress("192.0.2.2:53")) {
2091 if (domain
.countLabels() == 1 && type
== QType::DNSKEY
) { // example|DNSKEY
2092 setLWResult(res
, 0, true, false, true);
2093 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2094 addRRSIG(keys
, res
->d_records
, domain
, 300);
2095 return LWResult::Result::Success
;
2097 if (domain
== cnameTarget
&& type
== QType::DS
) { // dname.example|DS
2098 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
2100 if (domain
== cnameTarget
) {
2101 setLWResult(res
, 0, true, false, false);
2102 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2103 addRRSIG(keys
, res
->d_records
, dnameTarget
, 300);
2105 return LWResult::Result::Success
;
2107 return LWResult::Result::Timeout
;
2110 vector
<DNSRecord
> ret
;
2111 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2113 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2114 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2115 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2117 BOOST_CHECK_EQUAL(queries
, 7U);
2119 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2120 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2121 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2123 BOOST_REQUIRE(ret
[1].d_type
== QType::RRSIG
);
2124 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2126 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2127 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2129 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2130 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2132 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2133 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2137 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2139 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2140 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2141 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2143 BOOST_CHECK_EQUAL(queries
, 7U);
2145 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2146 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2147 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2149 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2150 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2152 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2153 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2155 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2156 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2158 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2159 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2162 BOOST_AUTO_TEST_CASE(test_dname_plus_ns_dnssec_secure
)
2164 std::unique_ptr
<SyncRes
> sr
;
2166 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
2170 const DNSName
dnameOwner("powerdns");
2171 const DNSName
dnameTarget("example");
2173 const DNSName
target("dname.powerdns");
2174 const DNSName
cnameTarget("dname.example");
2178 auto luaconfsCopy
= g_luaconfs
.getCopy();
2179 luaconfsCopy
.dsAnchors
.clear();
2180 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2181 generateKeyMaterial(dnameTarget
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2182 g_luaconfs
.setState(luaconfsCopy
);
2186 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 */) {
2189 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
2190 return genericDSAndDNSKEYHandler(res
, domain
, domain
, type
, keys
, false);
2193 if (domain
.isPartOf(dnameOwner
)) {
2194 setLWResult(res
, 0, true, false, true);
2195 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2196 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2197 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString()); // CNAME from a DNAME is not signed
2199 addRecordToLW(res
, dnameTarget
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2200 addDS(dnameTarget
, 300, res
->d_records
, keys
);
2201 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2202 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2203 return LWResult::Result::Success
;
2205 else if (domain
== cnameTarget
) {
2206 setLWResult(res
, 0, true, false, true);
2207 addRecordToLW(res
, domain
, QType::A
, "192.0.2.42");
2208 addRRSIG(keys
, res
->d_records
, dnameTarget
, 300);
2209 return LWResult::Result::Success
;
2211 return LWResult::Result::Timeout
;
2214 vector
<DNSRecord
> ret
;
2215 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2217 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2218 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2219 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2221 BOOST_CHECK_EQUAL(queries
, 4U);
2223 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2224 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2225 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2227 BOOST_REQUIRE(ret
[1].d_type
== QType::RRSIG
);
2228 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2230 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2231 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2233 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2234 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2236 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2237 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2241 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2243 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2244 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Secure
);
2245 BOOST_REQUIRE_EQUAL(ret
.size(), 5U); /* DNAME + RRSIG(DNAME) + CNAME + A + RRSIG(A) */
2247 BOOST_CHECK_EQUAL(queries
, 4U);
2249 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2250 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2251 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2253 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2254 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2256 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2257 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2259 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2260 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2262 BOOST_CHECK(ret
[4].d_type
== QType::RRSIG
);
2263 BOOST_CHECK_EQUAL(ret
[4].d_name
, cnameTarget
);
2266 BOOST_AUTO_TEST_CASE(test_dname_dnssec_insecure
)
2269 * The DNAME itself is signed, but the final A record is not
2271 std::unique_ptr
<SyncRes
> sr
;
2273 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
2277 const DNSName
dnameOwner("powerdns");
2278 const DNSName
dnameTarget("example");
2280 const DNSName
target("dname.powerdns");
2281 const DNSName
cnameTarget("dname.example");
2285 auto luaconfsCopy
= g_luaconfs
.getCopy();
2286 luaconfsCopy
.dsAnchors
.clear();
2287 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
2288 generateKeyMaterial(dnameOwner
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
2289 g_luaconfs
.setState(luaconfsCopy
);
2293 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 */) {
2296 if (isRootServer(ip
)) {
2297 if (domain
.countLabels() == 0 && type
== QType::DNSKEY
) { // .|DNSKEY
2298 setLWResult(res
, 0, true, false, true);
2299 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2300 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2301 return LWResult::Result::Success
;
2303 if (domain
== dnameOwner
&& type
== QType::DS
) { // powerdns|DS
2304 setLWResult(res
, 0, true, false, true);
2305 addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
);
2306 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2307 return LWResult::Result::Success
;
2309 if (domain
== dnameTarget
&& type
== QType::DS
) { // example|DS
2310 return genericDSAndDNSKEYHandler(res
, domain
, DNSName("."), type
, keys
);
2312 // For the rest, delegate!
2313 if (domain
.isPartOf(dnameOwner
)) {
2314 setLWResult(res
, 0, false, false, true);
2315 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2316 addDS(dnameOwner
, 300, res
->d_records
, keys
);
2317 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2318 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2319 return LWResult::Result::Success
;
2321 if (domain
.isPartOf(dnameTarget
)) {
2322 setLWResult(res
, 0, false, false, true);
2323 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2324 addDS(dnameTarget
, 300, res
->d_records
, keys
);
2325 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
2326 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2327 return LWResult::Result::Success
;
2330 else if (ip
== ComboAddress("192.0.2.1:53")) {
2331 if (domain
.countLabels() == 1 && type
== QType::DNSKEY
) { // powerdns|DNSKEY
2332 setLWResult(res
, 0, true, false, true);
2333 addDNSKEY(keys
, domain
, 300, res
->d_records
);
2334 addRRSIG(keys
, res
->d_records
, domain
, 300);
2335 return LWResult::Result::Success
;
2337 if (domain
== target
&& type
== QType::DS
) { // dname.powerdns|DS
2338 return genericDSAndDNSKEYHandler(res
, domain
, dnameOwner
, type
, keys
, false);
2340 if (domain
== target
) {
2341 setLWResult(res
, 0, true, false, false);
2342 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2343 addRRSIG(keys
, res
->d_records
, dnameOwner
, 300);
2344 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString()); // CNAME from a DNAME is not signed
2345 return LWResult::Result::Success
;
2348 else if (ip
== ComboAddress("192.0.2.2:53")) {
2349 if (domain
== target
&& type
== QType::DS
) { // dname.example|DS
2350 return genericDSAndDNSKEYHandler(res
, domain
, dnameTarget
, type
, keys
, false);
2352 if (domain
== cnameTarget
) {
2353 setLWResult(res
, 0, true, false, false);
2354 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2356 return LWResult::Result::Success
;
2358 return LWResult::Result::Timeout
;
2361 vector
<DNSRecord
> ret
;
2362 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2364 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2365 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
2366 BOOST_REQUIRE_EQUAL(ret
.size(), 4U); /* DNAME + RRSIG(DNAME) + CNAME + A */
2368 BOOST_CHECK_EQUAL(queries
, 7U);
2370 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2371 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2372 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2374 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2375 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2377 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2378 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2380 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2381 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2385 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2387 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2388 BOOST_CHECK_EQUAL(sr
->getValidationState(), vState::Insecure
);
2389 BOOST_REQUIRE_EQUAL(ret
.size(), 4U); /* DNAME + RRSIG(DNAME) + CNAME + A */
2391 BOOST_CHECK_EQUAL(queries
, 7U);
2393 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2394 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2395 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2397 BOOST_CHECK(ret
[1].d_type
== QType::RRSIG
);
2398 BOOST_CHECK_EQUAL(ret
[1].d_name
, dnameOwner
);
2400 BOOST_CHECK(ret
[2].d_type
== QType::CNAME
);
2401 BOOST_CHECK_EQUAL(ret
[2].d_name
, target
);
2403 BOOST_CHECK(ret
[3].d_type
== QType::A
);
2404 BOOST_CHECK_EQUAL(ret
[3].d_name
, cnameTarget
);
2407 BOOST_AUTO_TEST_CASE(test_dname_processing_no_CNAME
)
2409 std::unique_ptr
<SyncRes
> sr
;
2414 const DNSName
dnameOwner("powerdns.com");
2415 const DNSName
dnameTarget("powerdns.net");
2417 const DNSName
target("dname.powerdns.com.");
2418 const DNSName
cnameTarget("dname.powerdns.net");
2422 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 */) {
2425 if (isRootServer(ip
)) {
2426 if (domain
.isPartOf(dnameOwner
)) {
2427 setLWResult(res
, 0, false, false, true);
2428 addRecordToLW(res
, dnameOwner
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2429 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2430 return LWResult::Result::Success
;
2432 if (domain
.isPartOf(dnameTarget
)) {
2433 setLWResult(res
, 0, false, false, true);
2434 addRecordToLW(res
, dnameTarget
, QType::NS
, "b.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2435 addRecordToLW(res
, "b.gtld-servers.net.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
2436 return LWResult::Result::Success
;
2439 else if (ip
== ComboAddress("192.0.2.1:53")) {
2440 if (domain
== target
) {
2441 setLWResult(res
, 0, true, false, false);
2442 addRecordToLW(res
, dnameOwner
, QType::DNAME
, dnameTarget
.toString());
2443 // No CNAME, recursor should synth
2444 return LWResult::Result::Success
;
2447 else if (ip
== ComboAddress("192.0.2.2:53")) {
2448 if (domain
== cnameTarget
) {
2449 setLWResult(res
, 0, true, false, false);
2450 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
2452 return LWResult::Result::Success
;
2454 return LWResult::Result::Timeout
;
2457 vector
<DNSRecord
> ret
;
2458 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2460 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2461 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
2463 BOOST_CHECK_EQUAL(queries
, 4U);
2465 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2466 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2467 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2469 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
2470 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
2472 BOOST_CHECK(ret
[2].d_type
== QType::A
);
2473 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
2475 // Now check the cache
2477 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2479 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2480 BOOST_REQUIRE_EQUAL(ret
.size(), 3U);
2482 BOOST_CHECK_EQUAL(queries
, 4U);
2484 BOOST_REQUIRE(ret
[0].d_type
== QType::DNAME
);
2485 BOOST_CHECK(ret
[0].d_name
== dnameOwner
);
2486 BOOST_CHECK_EQUAL(getRR
<DNAMERecordContent
>(ret
[0])->getTarget(), dnameTarget
);
2488 BOOST_CHECK(ret
[1].d_type
== QType::CNAME
);
2489 BOOST_CHECK_EQUAL(ret
[1].d_name
, target
);
2491 BOOST_CHECK(ret
[2].d_type
== QType::A
);
2492 BOOST_CHECK_EQUAL(ret
[2].d_name
, cnameTarget
);
2496 // cerr<<"asyncresolve called to ask "<<ip.toStringWithPort()<<" about "<<domain.toString()<<" / "<<QType(type).getName()<<" over "<<(doTCP ? "TCP" : "UDP")<<" (rd: "<<sendRDQuery<<", EDNS0 level: "<<EDNS0Level<<")"<<endl;
2498 - check out of band support
2504 BOOST_AUTO_TEST_CASE(test_glued_referral_child_ns_set_wrong
)
2506 std::unique_ptr
<SyncRes
> sr
;
2511 const DNSName
target("powerdns.com.");
2513 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 */) {
2514 /* this will cause issue with qname minimization if we ever implement it */
2515 if (domain
!= target
) {
2516 return LWResult::Result::Timeout
;
2519 if (isRootServer(ip
)) {
2520 setLWResult(res
, 0, false, false, true);
2521 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
2522 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
2523 addRecordToLW(res
, "a.gtld-servers.net.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
2524 return LWResult::Result::Success
;
2526 else if (ip
== ComboAddress("192.0.2.1:53") || ip
== ComboAddress("[2001:DB8::1]:53")) {
2527 setLWResult(res
, 0, false, false, true);
2528 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
2529 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
2530 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 172800);
2531 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 172800);
2532 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 172800);
2533 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 172800);
2534 return LWResult::Result::Success
;
2536 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")) {
2538 if (type
== QType::A
) {
2539 setLWResult(res
, 0, true, false, true);
2540 addRecordToLW(res
, target
, QType::A
, "192.0.2.4");
2541 return LWResult::Result::Success
;
2543 else if (type
== QType::NS
) {
2544 setLWResult(res
, 0, true, false, true);
2545 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-nsX1.powerdns.com.", DNSResourceRecord::ANSWER
, 172800);
2546 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-nsX2.powerdns.com.", DNSResourceRecord::ANSWER
, 172800);
2547 addRecordToLW(res
, "pdns-public-nsX1.powerdns.com.", QType::A
, "192.0.2.11", DNSResourceRecord::ADDITIONAL
, 172800);
2548 addRecordToLW(res
, "pdns-public-nsX1.powerdns.com.", QType::AAAA
, "2001:DB8::11", DNSResourceRecord::ADDITIONAL
, 172800);
2549 addRecordToLW(res
, "pdns-public-nsX2.powerdns.com.", QType::A
, "192.0.2.12", DNSResourceRecord::ADDITIONAL
, 172800);
2550 addRecordToLW(res
, "pdns-public-nsX2.powerdns.com.", QType::AAAA
, "2001:DB8::12", DNSResourceRecord::ADDITIONAL
, 172800);
2551 return LWResult::Result::Success
;
2554 return LWResult::Result::Timeout
;
2558 return LWResult::Result::Timeout
;
2562 vector
<DNSRecord
> ret
;
2563 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2564 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2565 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
2566 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2567 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
2569 // Now resolve NS to get auth NS set in cache and save the parent NS set
2571 res
= sr
->beginResolve(target
, QType(QType::NS
), QClass::IN
, ret
);
2572 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2573 BOOST_REQUIRE_EQUAL(ret
.size(), 2U);
2574 BOOST_CHECK(ret
[0].d_type
== QType::NS
);
2575 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
2576 BOOST_CHECK_EQUAL(SyncRes::getSaveParentsNSSetsSize(), 1U);
2578 g_recCache
->doWipeCache(target
, false, QType::A
);
2579 SyncRes::s_save_parent_ns_set
= false;
2581 // Try to resolve now via the broken child NS set... should not work
2583 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2584 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
2585 BOOST_REQUIRE_EQUAL(ret
.size(), 0U);
2587 SyncRes::s_save_parent_ns_set
= true;
2589 // Try to resolve now via the broken child... should work now via fallback to parent NS set
2591 res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
2592 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
2593 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
2594 BOOST_CHECK(ret
[0].d_type
== QType::A
);
2595 BOOST_CHECK_EQUAL(ret
[0].d_name
, target
);
2598 BOOST_AUTO_TEST_SUITE_END()