1 #define BOOST_TEST_DYN_LINK
2 #include <boost/test/unit_test.hpp>
4 #include "test-syncres_cc.hh"
6 BOOST_AUTO_TEST_SUITE(syncres_cc2
)
8 BOOST_AUTO_TEST_CASE(test_referral_depth
) {
9 std::unique_ptr
<SyncRes
> sr
;
15 const DNSName
target("www.powerdns.com.");
17 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
) {
21 if (isRootServer(ip
)) {
22 setLWResult(res
, 0, false, false, true);
24 if (domain
== DNSName("www.powerdns.com.")) {
25 addRecordToLW(res
, domain
, QType::NS
, "ns.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
27 else if (domain
== DNSName("ns.powerdns.com.")) {
28 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
30 else if (domain
== DNSName("ns1.powerdns.org.")) {
31 addRecordToLW(res
, domain
, QType::NS
, "ns2.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
33 else if (domain
== DNSName("ns2.powerdns.org.")) {
34 addRecordToLW(res
, domain
, QType::NS
, "ns3.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
36 else if (domain
== DNSName("ns3.powerdns.org.")) {
37 addRecordToLW(res
, domain
, QType::NS
, "ns4.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
39 else if (domain
== DNSName("ns4.powerdns.org.")) {
40 addRecordToLW(res
, domain
, QType::NS
, "ns5.powerdns.org.", DNSResourceRecord::AUTHORITY
, 172800);
41 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1", DNSResourceRecord::AUTHORITY
, 172800);
45 } else if (ip
== ComboAddress("192.0.2.1:53")) {
47 setLWResult(res
, 0, true, false, false);
48 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
55 /* Set the maximum depth low */
56 SyncRes::s_maxdepth
= 10;
59 vector
<DNSRecord
> ret
;
60 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
63 catch(const ImmediateServFailException
& e
) {
67 BOOST_AUTO_TEST_CASE(test_cname_qperq
) {
68 std::unique_ptr
<SyncRes
> sr
;
74 const DNSName
target("cname.powerdns.com.");
76 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
) {
80 if (isRootServer(ip
)) {
82 setLWResult(res
, 0, false, false, true);
83 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
84 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
86 } else if (ip
== ComboAddress("192.0.2.1:53")) {
88 setLWResult(res
, 0, true, false, false);
89 addRecordToLW(res
, domain
, QType::CNAME
, std::to_string(queries
) + "-cname.powerdns.com");
96 /* Set the maximum number of questions very low */
97 SyncRes::s_maxqperq
= 5;
100 vector
<DNSRecord
> ret
;
101 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
104 catch(const ImmediateServFailException
& e
) {
105 BOOST_CHECK_EQUAL(queries
, SyncRes::s_maxqperq
);
109 BOOST_AUTO_TEST_CASE(test_throttled_server
) {
110 std::unique_ptr
<SyncRes
> sr
;
115 const DNSName
target("throttled.powerdns.com.");
116 const ComboAddress
ns("192.0.2.1:53");
117 size_t queriesToNS
= 0;
119 sr
->setAsyncCallback([target
,ns
,&queriesToNS
](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
) {
121 if (isRootServer(ip
)) {
123 setLWResult(res
, 0, false, false, true);
124 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
125 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
127 } else if (ip
== ns
) {
131 setLWResult(res
, 0, true, false, false);
132 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
140 /* mark ns as down */
141 time_t now
= sr
->getNow().tv_sec
;
142 SyncRes::doThrottle(now
, ns
, SyncRes::s_serverdownthrottletime
, 10000);
144 vector
<DNSRecord
> ret
;
145 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
146 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
147 BOOST_CHECK_EQUAL(ret
.size(), 0U);
148 /* we should not have sent any queries to ns */
149 BOOST_CHECK_EQUAL(queriesToNS
, 0U);
152 BOOST_AUTO_TEST_CASE(test_throttled_server_count
) {
153 std::unique_ptr
<SyncRes
> sr
;
158 const ComboAddress
ns("192.0.2.1:53");
160 const size_t blocks
= 10;
161 /* mark ns as down for 'blocks' queries */
162 time_t now
= sr
->getNow().tv_sec
;
163 SyncRes::doThrottle(now
, ns
, SyncRes::s_serverdownthrottletime
, blocks
);
165 for (size_t idx
= 0; idx
< blocks
; idx
++) {
166 BOOST_CHECK(SyncRes::isThrottled(now
, ns
));
169 /* we have been throttled 'blocks' times, we should not be throttled anymore */
170 BOOST_CHECK(!SyncRes::isThrottled(now
, ns
));
173 BOOST_AUTO_TEST_CASE(test_throttled_server_time
) {
174 std::unique_ptr
<SyncRes
> sr
;
179 const ComboAddress
ns("192.0.2.1:53");
181 const size_t seconds
= 1;
182 /* mark ns as down for 'seconds' seconds */
183 time_t now
= sr
->getNow().tv_sec
;
184 SyncRes::doThrottle(now
, ns
, seconds
, 10000);
186 BOOST_CHECK(SyncRes::isThrottled(now
, ns
));
188 /* we should not be throttled anymore */
189 BOOST_CHECK(!SyncRes::isThrottled(now
+ 2, ns
));
192 BOOST_AUTO_TEST_CASE(test_dont_query_server
) {
193 std::unique_ptr
<SyncRes
> sr
;
198 const DNSName
target("throttled.powerdns.com.");
199 const ComboAddress
ns("192.0.2.1:53");
200 size_t queriesToNS
= 0;
202 sr
->setAsyncCallback([target
,ns
,&queriesToNS
](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
) {
204 if (isRootServer(ip
)) {
206 setLWResult(res
, 0, false, false, true);
207 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
208 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
210 } else if (ip
== ns
) {
214 setLWResult(res
, 0, true, false, false);
215 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
223 /* prevent querying this NS */
224 SyncRes::addDontQuery(Netmask(ns
));
226 vector
<DNSRecord
> ret
;
227 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
228 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
229 BOOST_CHECK_EQUAL(ret
.size(), 0U);
230 /* we should not have sent any queries to ns */
231 BOOST_CHECK_EQUAL(queriesToNS
, 0U);
234 BOOST_AUTO_TEST_CASE(test_root_nx_trust
) {
235 std::unique_ptr
<SyncRes
> sr
;
240 const DNSName
target1("powerdns.com.");
241 const DNSName
target2("notpowerdns.com.");
242 const ComboAddress
ns("192.0.2.1:53");
243 size_t queriesCount
= 0;
245 sr
->setAsyncCallback([target1
, target2
, ns
, &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
) {
249 if (isRootServer(ip
)) {
251 if (domain
== target1
) {
252 setLWResult(res
, RCode::NXDomain
, true, false, true);
253 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
256 setLWResult(res
, 0, true, false, true);
257 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
258 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
262 } else if (ip
== ns
) {
264 setLWResult(res
, 0, true, false, false);
265 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
273 SyncRes::s_maxnegttl
= 3600;
275 vector
<DNSRecord
> ret
;
276 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
277 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
278 BOOST_CHECK_EQUAL(ret
.size(), 1U);
279 /* one for target1 and one for the entire TLD */
280 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2U);
283 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
284 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
285 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
286 BOOST_CHECK_LE(ret
[0].d_ttl
, SyncRes::s_maxnegttl
);
287 /* one for target1 and one for the entire TLD */
288 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2U);
290 /* we should have sent only one query */
291 BOOST_CHECK_EQUAL(queriesCount
, 1U);
294 BOOST_AUTO_TEST_CASE(test_root_nx_trust_specific
) {
295 std::unique_ptr
<SyncRes
> sr
;
297 initSR(sr
, true, false);
301 const DNSName
target1("powerdns.com.");
302 const DNSName
target2("notpowerdns.com.");
303 const ComboAddress
ns("192.0.2.1:53");
304 size_t queriesCount
= 0;
306 /* This time the root denies target1 with a "com." SOA instead of a "." one.
307 We should add target1 to the negcache, but not "com.". */
309 sr
->setAsyncCallback([target1
, target2
, ns
, &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
) {
313 if (isRootServer(ip
)) {
315 if (domain
== target1
) {
316 setLWResult(res
, RCode::NXDomain
, true, false, true);
317 addRecordToLW(res
, "com.", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
320 setLWResult(res
, 0, true, false, true);
321 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
322 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
326 } else if (ip
== ns
) {
328 setLWResult(res
, 0, true, false, false);
329 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
337 vector
<DNSRecord
> ret
;
338 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
339 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
340 BOOST_CHECK_EQUAL(ret
.size(), 1U);
342 /* even with root-nx-trust on and a NX answer from the root,
343 we should not have cached the entire TLD this time. */
344 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1U);
347 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
348 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
349 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
350 BOOST_CHECK_EQUAL(ret
[0].d_name
, target2
);
351 BOOST_REQUIRE(ret
[0].d_type
== QType::A
);
352 BOOST_CHECK(getRR
<ARecordContent
>(ret
[0])->getCA() == ComboAddress("192.0.2.2"));
354 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1U);
356 BOOST_CHECK_EQUAL(queriesCount
, 3U);
359 BOOST_AUTO_TEST_CASE(test_root_nx_dont_trust
) {
360 std::unique_ptr
<SyncRes
> sr
;
365 const DNSName
target1("powerdns.com.");
366 const DNSName
target2("notpowerdns.com.");
367 const ComboAddress
ns("192.0.2.1:53");
368 size_t queriesCount
= 0;
370 sr
->setAsyncCallback([target1
, target2
, ns
, &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
) {
374 if (isRootServer(ip
)) {
376 if (domain
== target1
) {
377 setLWResult(res
, RCode::NXDomain
, true, false, true);
378 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
381 setLWResult(res
, 0, true, false, true);
382 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
383 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
387 } else if (ip
== ns
) {
389 setLWResult(res
, 0, true, false, false);
390 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
398 SyncRes::s_rootNXTrust
= false;
400 vector
<DNSRecord
> ret
;
401 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
402 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
403 BOOST_CHECK_EQUAL(ret
.size(), 1U);
404 /* one for target1 */
405 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
408 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
409 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
410 BOOST_CHECK_EQUAL(ret
.size(), 1U);
411 /* one for target1 */
412 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
414 /* we should have sent three queries */
415 BOOST_CHECK_EQUAL(queriesCount
, 3U);
418 BOOST_AUTO_TEST_CASE(test_rfc8020_nothing_underneath
) {
419 std::unique_ptr
<SyncRes
> sr
;
424 const DNSName
target1("www.powerdns.com."); // will be denied
425 const DNSName
target2("foo.www.powerdns.com.");
426 const DNSName
target3("bar.www.powerdns.com.");
427 const DNSName
target4("quux.bar.www.powerdns.com.");
428 const ComboAddress
ns("192.0.2.1:53");
429 size_t queriesCount
= 0;
431 sr
->setAsyncCallback([ns
, &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
) {
435 if (isRootServer(ip
)) {
436 setLWResult(res
, 0, false, false, true);
437 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
438 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
440 } else if (ip
== ns
) {
441 setLWResult(res
, RCode::NXDomain
, true, false, false);
442 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "ns1.powerdns.com. hostmaster.powerdns.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
448 vector
<DNSRecord
> ret
;
449 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
450 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
451 BOOST_CHECK_EQUAL(ret
.size(), 1);
452 BOOST_CHECK_EQUAL(queriesCount
, 2);
453 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
456 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
457 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
458 BOOST_CHECK_EQUAL(ret
.size(), 1);
459 BOOST_CHECK_EQUAL(queriesCount
, 2);
460 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
463 res
= sr
->beginResolve(target3
, QType(QType::A
), QClass::IN
, ret
);
464 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
465 BOOST_CHECK_EQUAL(ret
.size(), 1);
466 BOOST_CHECK_EQUAL(queriesCount
, 2);
467 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
470 res
= sr
->beginResolve(target4
, QType(QType::A
), QClass::IN
, ret
);
471 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
472 BOOST_CHECK_EQUAL(ret
.size(), 1);
473 BOOST_CHECK_EQUAL(queriesCount
, 2);
474 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
476 // Now test without RFC 8020 to see the cache and query count grow
477 SyncRes::s_hardenNXD
= false;
481 res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
482 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
483 BOOST_CHECK_EQUAL(ret
.size(), 1);
484 BOOST_CHECK_EQUAL(queriesCount
, 2);
485 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
489 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
490 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
491 BOOST_CHECK_EQUAL(ret
.size(), 1);
492 BOOST_CHECK_EQUAL(queriesCount
, 3);
493 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
496 res
= sr
->beginResolve(target3
, QType(QType::A
), QClass::IN
, ret
);
497 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
498 BOOST_CHECK_EQUAL(ret
.size(), 1);
499 BOOST_CHECK_EQUAL(queriesCount
, 4);
500 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 3);
503 res
= sr
->beginResolve(target4
, QType(QType::A
), QClass::IN
, ret
);
504 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
505 BOOST_CHECK_EQUAL(ret
.size(), 1);
506 BOOST_CHECK_EQUAL(queriesCount
, 5);
507 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 4);
510 SyncRes::s_hardenNXD
= true;
513 BOOST_AUTO_TEST_CASE(test_rfc8020_nodata
) {
514 std::unique_ptr
<SyncRes
> sr
;
519 const DNSName
target1("www.powerdns.com."); // TXT record will be denied
520 const DNSName
target2("bar.www.powerdns.com."); // will be NXD, but the www. NODATA should not interfere with 8020 processing
521 const DNSName
target3("quux.bar.www.powerdns.com."); // will be NXD, but will not yield a query
522 const ComboAddress
ns("192.0.2.1:53");
523 size_t queriesCount
= 0;
525 sr
->setAsyncCallback([ns
, target1
, target2
, target3
, &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
) {
529 if (isRootServer(ip
)) {
530 setLWResult(res
, 0, false, false, true);
531 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
532 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
534 } else if (ip
== ns
) {
535 if (domain
== target1
) { // NODATA for TXT, NOERROR for A
536 if (type
== QType::TXT
) {
537 setLWResult(res
, RCode::NoError
, true);
538 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "ns1.powerdns.com. hostmaster.powerdns.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
541 if (type
== QType::A
) {
542 setLWResult(res
, RCode::NoError
, true);
543 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1", DNSResourceRecord::ANSWER
, 86400);
547 if (domain
== target2
|| domain
== target3
) {
548 setLWResult(res
, RCode::NXDomain
, true);
549 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "ns1.powerdns.com. hostmaster.powerdns.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
556 vector
<DNSRecord
> ret
;
557 int res
= sr
->beginResolve(target1
, QType(QType::TXT
), QClass::IN
, ret
);
558 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
559 BOOST_CHECK_EQUAL(ret
.size(), 1);
560 BOOST_CHECK_EQUAL(queriesCount
, 2);
561 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
564 res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
565 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
566 BOOST_CHECK_EQUAL(ret
.size(), 1);
567 BOOST_CHECK_EQUAL(queriesCount
, 3);
568 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
571 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
572 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
573 BOOST_CHECK_EQUAL(ret
.size(), 1);
574 BOOST_CHECK_EQUAL(queriesCount
, 4);
575 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
578 res
= sr
->beginResolve(target3
, QType(QType::A
), QClass::IN
, ret
);
579 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
580 BOOST_CHECK_EQUAL(ret
.size(), 1);
581 BOOST_CHECK_EQUAL(queriesCount
, 4);
582 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
585 BOOST_AUTO_TEST_CASE(test_rfc8020_nodata_bis
) {
586 std::unique_ptr
<SyncRes
> sr
;
591 const DNSName
target1("www.powerdns.com."); // TXT record will be denied
592 const DNSName
target2("bar.www.powerdns.com."); // will be NXD, but the www. NODATA should not interfere with 8020 processing
593 const DNSName
target3("quux.bar.www.powerdns.com."); // will be NXD, but will not yield a query
594 const ComboAddress
ns("192.0.2.1:53");
595 size_t queriesCount
= 0;
597 sr
->setAsyncCallback([ns
, target1
, target2
, target3
, &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
) {
601 if (isRootServer(ip
)) {
602 setLWResult(res
, 0, false, false, true);
603 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
604 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
606 } else if (ip
== ns
) {
607 if (domain
== target1
) { // NODATA for TXT, NOERROR for A
608 if (type
== QType::TXT
) {
609 setLWResult(res
, RCode::NoError
, true);
610 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "ns1.powerdns.com. hostmaster.powerdns.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
613 if (type
== QType::A
) {
614 setLWResult(res
, RCode::NoError
, true);
615 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1", DNSResourceRecord::ANSWER
, 86400);
619 if (domain
== target2
|| domain
== target3
) {
620 setLWResult(res
, RCode::NXDomain
, true);
621 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "ns1.powerdns.com. hostmaster.powerdns.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
628 vector
<DNSRecord
> ret
;
629 int res
= sr
->beginResolve(target1
, QType(QType::TXT
), QClass::IN
, ret
);
630 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
631 BOOST_CHECK_EQUAL(ret
.size(), 1);
632 BOOST_CHECK_EQUAL(queriesCount
, 2);
633 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
636 res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
637 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
638 BOOST_CHECK_EQUAL(ret
.size(), 1);
639 BOOST_CHECK_EQUAL(queriesCount
, 3);
640 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1);
643 res
= sr
->beginResolve(target2
, QType(QType::TXT
), QClass::IN
, ret
);
644 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
645 BOOST_CHECK_EQUAL(ret
.size(), 1);
646 BOOST_CHECK_EQUAL(queriesCount
, 4);
647 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
650 res
= sr
->beginResolve(target3
, QType(QType::TXT
), QClass::IN
, ret
);
651 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
652 BOOST_CHECK_EQUAL(ret
.size(), 1);
653 BOOST_CHECK_EQUAL(queriesCount
, 4);
654 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2);
657 BOOST_AUTO_TEST_CASE(test_skip_negcache_for_variable_response
) {
658 std::unique_ptr
<SyncRes
> sr
;
663 const DNSName
target("www.powerdns.com.");
664 const DNSName
cnameTarget("cname.powerdns.com.");
666 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
668 EDNSSubnetOpts incomingECS
;
669 incomingECS
.source
= Netmask("192.0.2.128/32");
670 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
672 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
) {
674 BOOST_REQUIRE(srcmask
);
675 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
677 if (isRootServer(ip
)) {
678 setLWResult(res
, 0, false, false, true);
679 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
680 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
682 srcmask
= boost::none
;
685 } else if (ip
== ComboAddress("192.0.2.1:53")) {
686 if (domain
== target
) {
687 /* Type 2 NXDOMAIN (rfc2308 section-2.1) */
688 setLWResult(res
, RCode::NXDomain
, true, false, true);
689 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
690 addRecordToLW(res
, "powerdns.com", QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
692 else if (domain
== cnameTarget
) {
693 /* we shouldn't get there since the Type NXDOMAIN should have been enough,
694 but we might if we still chase the CNAME. */
695 setLWResult(res
, RCode::NXDomain
, true, false, true);
696 addRecordToLW(res
, "powerdns.com", QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
705 vector
<DNSRecord
> ret
;
706 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
707 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
708 BOOST_CHECK_EQUAL(ret
.size(), 2U);
709 /* no negative cache entry because the response was variable */
710 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 0U);
713 BOOST_AUTO_TEST_CASE(test_ecs_cache_limit_allowed
) {
714 std::unique_ptr
<SyncRes
> sr
;
719 const DNSName
target("www.powerdns.com.");
721 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
723 EDNSSubnetOpts incomingECS
;
724 incomingECS
.source
= Netmask("192.0.2.128/32");
725 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
726 SyncRes::s_ecsipv4cachelimit
= 24;
728 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
) {
730 BOOST_REQUIRE(srcmask
);
731 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
733 setLWResult(res
, 0, true, false, true);
734 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
739 const time_t now
= sr
->getNow().tv_sec
;
740 vector
<DNSRecord
> ret
;
741 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
742 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
743 BOOST_CHECK_EQUAL(ret
.size(), 1U);
745 /* should have been cached */
746 const ComboAddress
who("192.0.2.128");
747 vector
<DNSRecord
> cached
;
748 BOOST_REQUIRE_GT(t_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
749 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
752 BOOST_AUTO_TEST_CASE(test_ecs_cache_limit_no_ttl_limit_allowed
) {
753 std::unique_ptr
<SyncRes
> sr
;
758 const DNSName
target("www.powerdns.com.");
760 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
762 EDNSSubnetOpts incomingECS
;
763 incomingECS
.source
= Netmask("192.0.2.128/32");
764 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
765 SyncRes::s_ecsipv4cachelimit
= 16;
767 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
) {
769 BOOST_REQUIRE(srcmask
);
770 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
772 setLWResult(res
, 0, true, false, true);
773 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
778 const time_t now
= sr
->getNow().tv_sec
;
779 vector
<DNSRecord
> ret
;
780 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
781 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
782 BOOST_CHECK_EQUAL(ret
.size(), 1U);
784 /* should have been cached because /24 is more specific than /16 but TTL limit is nof effective */
785 const ComboAddress
who("192.0.2.128");
786 vector
<DNSRecord
> cached
;
787 BOOST_REQUIRE_GT(t_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
788 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
791 BOOST_AUTO_TEST_CASE(test_ecs_cache_ttllimit_allowed
) {
792 std::unique_ptr
<SyncRes
> sr
;
797 const DNSName
target("www.powerdns.com.");
799 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
801 EDNSSubnetOpts incomingECS
;
802 incomingECS
.source
= Netmask("192.0.2.128/32");
803 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
804 SyncRes::s_ecscachelimitttl
= 30;
806 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
) {
808 BOOST_REQUIRE(srcmask
);
809 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
811 setLWResult(res
, 0, true, false, true);
812 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
817 const time_t now
= sr
->getNow().tv_sec
;
818 vector
<DNSRecord
> ret
;
819 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
820 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
821 BOOST_CHECK_EQUAL(ret
.size(), 1U);
823 /* should have been cached */
824 const ComboAddress
who("192.0.2.128");
825 vector
<DNSRecord
> cached
;
826 BOOST_REQUIRE_GT(t_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
827 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
830 BOOST_AUTO_TEST_CASE(test_ecs_cache_ttllimit_and_scope_allowed
) {
831 std::unique_ptr
<SyncRes
> sr
;
836 const DNSName
target("www.powerdns.com.");
838 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
840 EDNSSubnetOpts incomingECS
;
841 incomingECS
.source
= Netmask("192.0.2.128/32");
842 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
843 SyncRes::s_ecscachelimitttl
= 100;
844 SyncRes::s_ecsipv4cachelimit
= 24;
846 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
) {
848 BOOST_REQUIRE(srcmask
);
849 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
851 setLWResult(res
, 0, true, false, true);
852 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
857 const time_t now
= sr
->getNow().tv_sec
;
858 vector
<DNSRecord
> ret
;
859 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
860 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
861 BOOST_CHECK_EQUAL(ret
.size(), 1U);
863 /* should have been cached */
864 const ComboAddress
who("192.0.2.128");
865 vector
<DNSRecord
> cached
;
866 BOOST_REQUIRE_GT(t_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
867 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
870 BOOST_AUTO_TEST_CASE(test_ecs_cache_ttllimit_notallowed
) {
871 std::unique_ptr
<SyncRes
> sr
;
876 const DNSName
target("www.powerdns.com.");
878 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
880 EDNSSubnetOpts incomingECS
;
881 incomingECS
.source
= Netmask("192.0.2.128/32");
882 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
883 SyncRes::s_ecscachelimitttl
= 100;
884 SyncRes::s_ecsipv4cachelimit
= 16;
886 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
) {
888 BOOST_REQUIRE(srcmask
);
889 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
891 setLWResult(res
, 0, true, false, true);
892 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
897 const time_t now
= sr
->getNow().tv_sec
;
898 vector
<DNSRecord
> ret
;
899 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
900 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
901 BOOST_CHECK_EQUAL(ret
.size(), 1U);
903 /* should have NOT been cached because TTL of 60 is too small and /24 is more specific than /16 */
904 const ComboAddress
who("192.0.2.128");
905 vector
<DNSRecord
> cached
;
906 BOOST_REQUIRE_LT(t_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
907 BOOST_REQUIRE_EQUAL(cached
.size(), 0U);
911 BOOST_AUTO_TEST_CASE(test_ns_speed
) {
912 std::unique_ptr
<SyncRes
> sr
;
917 const DNSName
target("powerdns.com.");
919 std::map
<ComboAddress
, uint64_t> nsCounts
;
921 sr
->setAsyncCallback([target
,&nsCounts
](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
) {
923 if (isRootServer(ip
)) {
924 setLWResult(res
, 0, false, false, true);
925 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
926 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
927 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
929 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
930 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
931 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
932 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 3600);
933 addRecordToLW(res
, "pdns-public-ns3.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 3600);
934 addRecordToLW(res
, "pdns-public-ns3.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 3600);
940 if (ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("192.0.2.2:53")) {
941 BOOST_CHECK_LT(nsCounts
.size(), 3U);
943 /* let's time out on pdns-public-ns2.powerdns.com. */
946 else if (ip
== ComboAddress("192.0.2.1:53")) {
947 BOOST_CHECK_EQUAL(nsCounts
.size(), 3U);
949 setLWResult(res
, 0, true, false, true);
950 addRecordToLW(res
, domain
, QType::A
, "192.0.2.254");
960 struct timeval now
= sr
->getNow();
962 /* make pdns-public-ns2.powerdns.com. the fastest NS, with its IPv6 address faster than the IPV4 one,
963 then pdns-public-ns1.powerdns.com. on IPv4 */
964 SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("192.0.2.1:53"), 100, &now
);
965 SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("[2001:DB8::1]:53"), 10000, &now
);
966 SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("192.0.2.2:53"), 10, &now
);
967 SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("[2001:DB8::2]:53"), 1, &now
);
968 SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("192.0.2.3:53"), 10000, &now
);
969 SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("[2001:DB8::3]:53"), 10000, &now
);
971 vector
<DNSRecord
> ret
;
972 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
973 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
974 BOOST_CHECK_EQUAL(ret
.size(), 1U);
975 BOOST_CHECK_EQUAL(nsCounts
.size(), 3U);
976 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("192.0.2.1:53")], 1U);
977 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("192.0.2.2:53")], 1U);
978 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("[2001:DB8::2]:53")], 1U);
981 BOOST_AUTO_TEST_CASE(test_flawed_nsset
) {
982 std::unique_ptr
<SyncRes
> sr
;
987 const DNSName
target("powerdns.com.");
989 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
) {
991 if (isRootServer(ip
)) {
992 setLWResult(res
, 0, false, false, true);
993 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
995 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
998 } else if (ip
== ComboAddress("192.0.2.1:53")) {
999 setLWResult(res
, 0, true, false, true);
1000 addRecordToLW(res
, domain
, QType::A
, "192.0.2.254");
1007 /* we populate the cache with a flawed NSset, i.e. there is a NS entry but no corresponding glue */
1008 time_t now
= sr
->getNow().tv_sec
;
1009 std::vector
<DNSRecord
> records
;
1010 std::vector
<shared_ptr
<RRSIGRecordContent
> > sigs
;
1011 addRecordToList(records
, target
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, now
+ 3600);
1013 t_RC
->replace(now
, target
, QType(QType::NS
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
1015 vector
<DNSRecord
> ret
;
1016 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1017 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1018 BOOST_CHECK_EQUAL(ret
.size(), 1U);
1021 BOOST_AUTO_TEST_CASE(test_completely_flawed_nsset
) {
1022 std::unique_ptr
<SyncRes
> sr
;
1027 const DNSName
target("powerdns.com.");
1028 size_t queriesCount
= 0;
1030 sr
->setAsyncCallback([&queriesCount
,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
) {
1034 if (isRootServer(ip
) && domain
== target
) {
1035 setLWResult(res
, 0, false, false, true);
1036 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1037 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1039 } else if (domain
== DNSName("pdns-public-ns2.powerdns.com.") || domain
== DNSName("pdns-public-ns3.powerdns.com.")){
1040 setLWResult(res
, 0, true, false, true);
1041 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1048 vector
<DNSRecord
> ret
;
1049 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1050 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1051 BOOST_CHECK_EQUAL(ret
.size(), 0U);
1052 /* one query to get NSs, then A and AAAA for each NS */
1053 BOOST_CHECK_EQUAL(queriesCount
, 5U);
1056 BOOST_AUTO_TEST_CASE(test_cache_hit
) {
1057 std::unique_ptr
<SyncRes
> sr
;
1062 const DNSName
target("powerdns.com.");
1064 sr
->setAsyncCallback([target
](const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost::optional
<Netmask
>& srcmask
, boost::optional
<const ResolveContext
&> context
, LWResult
* res
, bool* chained
) {
1069 /* we populate the cache with eveything we need */
1070 time_t now
= sr
->getNow().tv_sec
;
1071 std::vector
<DNSRecord
> records
;
1072 std::vector
<shared_ptr
<RRSIGRecordContent
> > sigs
;
1074 addRecordToList(records
, target
, QType::A
, "192.0.2.1", DNSResourceRecord::ANSWER
, now
+ 3600);
1075 t_RC
->replace(now
, target
, QType(QType::A
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
1077 vector
<DNSRecord
> ret
;
1078 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1079 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1080 BOOST_CHECK_EQUAL(ret
.size(), 1U);
1083 BOOST_AUTO_TEST_CASE(test_no_rd
) {
1084 std::unique_ptr
<SyncRes
> sr
;
1089 const DNSName
target("powerdns.com.");
1090 size_t queriesCount
= 0;
1094 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
) {
1100 vector
<DNSRecord
> ret
;
1101 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1102 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1103 BOOST_CHECK_EQUAL(ret
.size(), 0U);
1104 BOOST_CHECK_EQUAL(queriesCount
, 0U);
1107 BOOST_AUTO_TEST_CASE(test_cache_min_max_ttl
) {
1108 std::unique_ptr
<SyncRes
> sr
;
1113 const DNSName
target("cachettl.powerdns.com.");
1114 const ComboAddress
ns("192.0.2.1:53");
1116 sr
->setAsyncCallback([target
,ns
](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
) {
1118 if (isRootServer(ip
)) {
1120 setLWResult(res
, 0, false, false, true);
1121 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1122 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 7200);
1124 } else if (ip
== ns
) {
1126 setLWResult(res
, 0, true, false, false);
1127 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2", DNSResourceRecord::ANSWER
, 10);
1135 const time_t now
= sr
->getNow().tv_sec
;
1136 SyncRes::s_minimumTTL
= 60;
1137 SyncRes::s_maxcachettl
= 3600;
1139 vector
<DNSRecord
> ret
;
1140 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1141 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1142 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1143 BOOST_CHECK_EQUAL(ret
[0].d_ttl
, SyncRes::s_minimumTTL
);
1145 const ComboAddress who
;
1146 vector
<DNSRecord
> cached
;
1147 BOOST_REQUIRE_GT(t_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
1148 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
1149 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
1150 BOOST_CHECK_EQUAL((cached
[0].d_ttl
- now
), SyncRes::s_minimumTTL
);
1153 BOOST_REQUIRE_GT(t_RC
->get(now
, target
, QType(QType::NS
), false, &cached
, who
), 0);
1154 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
1155 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
1156 BOOST_CHECK_LE((cached
[0].d_ttl
- now
), SyncRes::s_maxcachettl
);
1159 BOOST_AUTO_TEST_CASE(test_cache_min_max_ecs_ttl
) {
1160 std::unique_ptr
<SyncRes
> sr
;
1165 const DNSName
target("cacheecsttl.powerdns.com.");
1166 const ComboAddress
ns("192.0.2.1:53");
1168 EDNSSubnetOpts incomingECS
;
1169 incomingECS
.source
= Netmask("192.0.2.128/32");
1170 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1171 SyncRes::addEDNSDomain(target
);
1173 sr
->setAsyncCallback([target
,ns
](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
) {
1175 BOOST_REQUIRE(srcmask
);
1176 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1178 if (isRootServer(ip
)) {
1180 setLWResult(res
, 0, false, false, true);
1181 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1182 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 20);
1183 srcmask
= boost::none
;
1186 } else if (ip
== ns
) {
1188 setLWResult(res
, 0, true, false, false);
1189 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2", DNSResourceRecord::ANSWER
, 10);
1197 const time_t now
= sr
->getNow().tv_sec
;
1198 SyncRes::s_minimumTTL
= 60;
1199 SyncRes::s_minimumECSTTL
= 120;
1200 SyncRes::s_maxcachettl
= 3600;
1202 vector
<DNSRecord
> ret
;
1203 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1204 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1205 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1206 BOOST_CHECK_EQUAL(ret
[0].d_ttl
, SyncRes::s_minimumECSTTL
);
1208 const ComboAddress
who("192.0.2.128");
1209 vector
<DNSRecord
> cached
;
1210 BOOST_REQUIRE_GT(t_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
1211 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
1212 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
1213 BOOST_CHECK_EQUAL((cached
[0].d_ttl
- now
), SyncRes::s_minimumECSTTL
);
1216 BOOST_REQUIRE_GT(t_RC
->get(now
, target
, QType(QType::NS
), false, &cached
, who
), 0);
1217 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
1218 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
1219 BOOST_CHECK_LE((cached
[0].d_ttl
- now
), SyncRes::s_maxcachettl
);
1222 BOOST_REQUIRE_GT(t_RC
->get(now
, DNSName("a.gtld-servers.net."), QType(QType::A
), false, &cached
, who
), 0);
1223 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
1224 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
1225 BOOST_CHECK_LE((cached
[0].d_ttl
- now
), SyncRes::s_minimumTTL
);
1228 BOOST_AUTO_TEST_CASE(test_cache_expired_ttl
) {
1229 std::unique_ptr
<SyncRes
> sr
;
1234 const DNSName
target("powerdns.com.");
1236 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
) {
1238 if (isRootServer(ip
)) {
1239 setLWResult(res
, 0, false, false, true);
1240 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1242 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1245 } else if (ip
== ComboAddress("192.0.2.1:53")) {
1246 setLWResult(res
, 0, true, false, true);
1247 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1254 /* we populate the cache with entries that expired 60s ago*/
1255 const time_t now
= sr
->getNow().tv_sec
;
1257 std::vector
<DNSRecord
> records
;
1258 std::vector
<shared_ptr
<RRSIGRecordContent
> > sigs
;
1259 addRecordToList(records
, target
, QType::A
, "192.0.2.42", DNSResourceRecord::ANSWER
, now
- 60);
1261 t_RC
->replace(now
- 3600, target
, QType(QType::A
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
1263 vector
<DNSRecord
> ret
;
1264 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1265 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1266 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1267 BOOST_REQUIRE(ret
[0].d_type
== QType::A
);
1268 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toStringWithPort(), ComboAddress("192.0.2.2").toStringWithPort());
1271 BOOST_AUTO_TEST_SUITE_END()