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
)
10 std::unique_ptr
<SyncRes
> sr
;
16 const DNSName
target("www.powerdns.com.");
18 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);
46 else if (ip
== ComboAddress("192.0.2.1:53")) {
48 setLWResult(res
, 0, true, false, false);
49 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
56 /* Set the maximum depth low */
57 SyncRes::s_maxdepth
= 10;
60 vector
<DNSRecord
> ret
;
61 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
64 catch (const ImmediateServFailException
& e
) {
68 BOOST_AUTO_TEST_CASE(test_cname_qperq
)
70 std::unique_ptr
<SyncRes
> sr
;
76 const DNSName
target("cname.powerdns.com.");
78 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
) {
81 if (isRootServer(ip
)) {
83 setLWResult(res
, 0, false, false, true);
84 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
85 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
88 else if (ip
== ComboAddress("192.0.2.1:53")) {
90 setLWResult(res
, 0, true, false, false);
91 addRecordToLW(res
, domain
, QType::CNAME
, std::to_string(queries
) + "-cname.powerdns.com");
98 /* Set the maximum number of questions very low */
99 SyncRes::s_maxqperq
= 5;
102 vector
<DNSRecord
> ret
;
103 sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
106 catch (const ImmediateServFailException
& e
) {
107 BOOST_CHECK_EQUAL(queries
, SyncRes::s_maxqperq
);
111 BOOST_AUTO_TEST_CASE(test_throttled_server
)
113 std::unique_ptr
<SyncRes
> sr
;
118 const DNSName
target("throttled.powerdns.com.");
119 const ComboAddress
ns("192.0.2.1:53");
120 size_t queriesToNS
= 0;
122 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
) {
123 if (isRootServer(ip
)) {
125 setLWResult(res
, 0, false, false, true);
126 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
127 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
134 setLWResult(res
, 0, true, false, false);
135 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
143 /* mark ns as down */
144 time_t now
= sr
->getNow().tv_sec
;
145 SyncRes::doThrottle(now
, ns
, SyncRes::s_serverdownthrottletime
, 10000);
147 vector
<DNSRecord
> ret
;
148 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
149 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
150 BOOST_CHECK_EQUAL(ret
.size(), 0U);
151 /* we should not have sent any queries to ns */
152 BOOST_CHECK_EQUAL(queriesToNS
, 0U);
155 BOOST_AUTO_TEST_CASE(test_throttled_server_count
)
157 std::unique_ptr
<SyncRes
> sr
;
162 const ComboAddress
ns("192.0.2.1:53");
164 const size_t blocks
= 10;
165 /* mark ns as down for 'blocks' queries */
166 time_t now
= sr
->getNow().tv_sec
;
167 SyncRes::doThrottle(now
, ns
, SyncRes::s_serverdownthrottletime
, blocks
);
169 for (size_t idx
= 0; idx
< blocks
; idx
++) {
170 BOOST_CHECK(SyncRes::isThrottled(now
, ns
));
173 /* we have been throttled 'blocks' times, we should not be throttled anymore */
174 BOOST_CHECK(!SyncRes::isThrottled(now
, ns
));
177 BOOST_AUTO_TEST_CASE(test_throttled_server_time
)
179 std::unique_ptr
<SyncRes
> sr
;
184 const ComboAddress
ns("192.0.2.1:53");
186 const size_t seconds
= 1;
187 /* mark ns as down for 'seconds' seconds */
188 time_t now
= sr
->getNow().tv_sec
;
189 SyncRes::doThrottle(now
, ns
, seconds
, 10000);
191 BOOST_CHECK(SyncRes::isThrottled(now
, ns
));
193 /* we should not be throttled anymore */
194 BOOST_CHECK(!SyncRes::isThrottled(now
+ 2, ns
));
197 BOOST_AUTO_TEST_CASE(test_dont_query_server
)
199 std::unique_ptr
<SyncRes
> sr
;
204 const DNSName
target("throttled.powerdns.com.");
205 const ComboAddress
ns("192.0.2.1:53");
206 size_t queriesToNS
= 0;
208 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
) {
209 if (isRootServer(ip
)) {
211 setLWResult(res
, 0, false, false, true);
212 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
213 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
220 setLWResult(res
, 0, true, false, false);
221 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
229 /* prevent querying this NS */
230 SyncRes::addDontQuery(Netmask(ns
));
232 vector
<DNSRecord
> ret
;
233 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
234 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
235 BOOST_CHECK_EQUAL(ret
.size(), 0U);
236 /* we should not have sent any queries to ns */
237 BOOST_CHECK_EQUAL(queriesToNS
, 0U);
240 BOOST_AUTO_TEST_CASE(test_root_nx_trust
)
242 std::unique_ptr
<SyncRes
> sr
;
247 const DNSName
target1("powerdns.com.");
248 const DNSName
target2("notpowerdns.com.");
249 const ComboAddress
ns("192.0.2.1:53");
250 size_t queriesCount
= 0;
252 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
) {
255 if (isRootServer(ip
)) {
257 if (domain
== target1
) {
258 setLWResult(res
, RCode::NXDomain
, true, false, true);
259 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
262 setLWResult(res
, 0, true, false, true);
263 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
264 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
271 setLWResult(res
, 0, true, false, false);
272 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
280 SyncRes::s_maxnegttl
= 3600;
282 vector
<DNSRecord
> ret
;
283 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
284 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
285 BOOST_CHECK_EQUAL(ret
.size(), 1U);
286 /* one for target1 and one for the entire TLD */
287 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2U);
290 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
291 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
292 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
293 BOOST_CHECK_LE(ret
[0].d_ttl
, SyncRes::s_maxnegttl
);
294 /* one for target1 and one for the entire TLD */
295 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2U);
297 /* we should have sent only one query */
298 BOOST_CHECK_EQUAL(queriesCount
, 1U);
301 BOOST_AUTO_TEST_CASE(test_root_nx_trust_specific
)
303 std::unique_ptr
<SyncRes
> sr
;
305 initSR(sr
, true, false);
309 const DNSName
target1("powerdns.com.");
310 const DNSName
target2("notpowerdns.com.");
311 const ComboAddress
ns("192.0.2.1:53");
312 size_t queriesCount
= 0;
314 /* This time the root denies target1 with a "com." SOA instead of a "." one.
315 We should add target1 to the negcache, but not "com.". */
317 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
) {
320 if (isRootServer(ip
)) {
322 if (domain
== target1
) {
323 setLWResult(res
, RCode::NXDomain
, true, false, true);
324 addRecordToLW(res
, "com.", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
327 setLWResult(res
, 0, true, false, true);
328 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
329 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
336 setLWResult(res
, 0, true, false, false);
337 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
345 vector
<DNSRecord
> ret
;
346 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
347 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
348 BOOST_CHECK_EQUAL(ret
.size(), 1U);
350 /* even with root-nx-trust on and a NX answer from the root,
351 we should not have cached the entire TLD this time. */
352 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1U);
355 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
356 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
357 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
358 BOOST_CHECK_EQUAL(ret
[0].d_name
, target2
);
359 BOOST_REQUIRE(ret
[0].d_type
== QType::A
);
360 BOOST_CHECK(getRR
<ARecordContent
>(ret
[0])->getCA() == ComboAddress("192.0.2.2"));
362 BOOST_CHECK_EQUAL(SyncRes::t_sstorage
.negcache
.size(), 1U);
364 BOOST_CHECK_EQUAL(queriesCount
, 3U);
367 BOOST_AUTO_TEST_CASE(test_root_nx_dont_trust
)
369 std::unique_ptr
<SyncRes
> sr
;
374 const DNSName
target1("powerdns.com.");
375 const DNSName
target2("notpowerdns.com.");
376 const ComboAddress
ns("192.0.2.1:53");
377 size_t queriesCount
= 0;
379 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
) {
382 if (isRootServer(ip
)) {
384 if (domain
== target1
) {
385 setLWResult(res
, RCode::NXDomain
, true, false, true);
386 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
389 setLWResult(res
, 0, true, false, true);
390 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
391 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
398 setLWResult(res
, 0, true, false, false);
399 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
407 SyncRes::s_rootNXTrust
= false;
409 vector
<DNSRecord
> ret
;
410 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
411 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
412 BOOST_CHECK_EQUAL(ret
.size(), 1U);
413 /* one for target1 */
414 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
417 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
418 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
419 BOOST_CHECK_EQUAL(ret
.size(), 1U);
420 /* one for target1 */
421 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
423 /* we should have sent three queries */
424 BOOST_CHECK_EQUAL(queriesCount
, 3U);
427 BOOST_AUTO_TEST_CASE(test_rfc8020_nothing_underneath
)
429 std::unique_ptr
<SyncRes
> sr
;
431 SyncRes::s_hardenNXD
= SyncRes::HardenNXD::Yes
;
435 const DNSName
target1("www.powerdns.com."); // will be denied
436 const DNSName
target2("foo.www.powerdns.com.");
437 const DNSName
target3("bar.www.powerdns.com.");
438 const DNSName
target4("quux.bar.www.powerdns.com.");
439 const ComboAddress
ns("192.0.2.1:53");
440 size_t queriesCount
= 0;
442 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
) {
445 if (isRootServer(ip
)) {
446 setLWResult(res
, 0, false, false, true);
447 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
448 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
452 setLWResult(res
, RCode::NXDomain
, true, false, false);
453 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "ns1.powerdns.com. hostmaster.powerdns.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
459 vector
<DNSRecord
> ret
;
460 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
461 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
462 BOOST_CHECK_EQUAL(ret
.size(), 1U);
463 BOOST_CHECK_EQUAL(queriesCount
, 2U);
464 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
467 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
468 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
469 BOOST_CHECK_EQUAL(ret
.size(), 1U);
470 BOOST_CHECK_EQUAL(queriesCount
, 2U);
471 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
474 res
= sr
->beginResolve(target3
, QType(QType::A
), QClass::IN
, ret
);
475 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
476 BOOST_CHECK_EQUAL(ret
.size(), 1U);
477 BOOST_CHECK_EQUAL(queriesCount
, 2U);
478 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
481 res
= sr
->beginResolve(target4
, QType(QType::A
), QClass::IN
, ret
);
482 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
483 BOOST_CHECK_EQUAL(ret
.size(), 1U);
484 BOOST_CHECK_EQUAL(queriesCount
, 2U);
485 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
487 // Now test without RFC 8020 to see the cache and query count grow
488 SyncRes::s_hardenNXD
= SyncRes::HardenNXD::No
;
492 res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
493 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
494 BOOST_CHECK_EQUAL(ret
.size(), 1U);
495 BOOST_CHECK_EQUAL(queriesCount
, 2U);
496 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
500 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
501 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
502 BOOST_CHECK_EQUAL(ret
.size(), 1U);
503 BOOST_CHECK_EQUAL(queriesCount
, 3U);
504 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2U);
507 res
= sr
->beginResolve(target3
, QType(QType::A
), QClass::IN
, ret
);
508 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
509 BOOST_CHECK_EQUAL(ret
.size(), 1U);
510 BOOST_CHECK_EQUAL(queriesCount
, 4U);
511 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 3U);
514 res
= sr
->beginResolve(target4
, QType(QType::A
), QClass::IN
, ret
);
515 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
516 BOOST_CHECK_EQUAL(ret
.size(), 1U);
517 BOOST_CHECK_EQUAL(queriesCount
, 5U);
518 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 4U);
521 SyncRes::s_hardenNXD
= SyncRes::HardenNXD::DNSSEC
;
524 BOOST_AUTO_TEST_CASE(test_rfc8020_nothing_underneath_dnssec
)
526 std::unique_ptr
<SyncRes
> sr
;
528 setDNSSECValidation(sr
, DNSSECMode::ValidateAll
);
532 const DNSName
parent1("com.");
533 const DNSName
parent2("powerdns.com.");
534 const DNSName
target1("www.powerdns.com."); // will be denied
535 const DNSName
target2("foo.www.powerdns.com.");
536 const DNSName
target3("bar.www.powerdns.com.");
537 const DNSName
target4("quux.bar.www.powerdns.com.");
538 const ComboAddress
ns("192.0.2.1:53");
542 auto luaconfsCopy
= g_luaconfs
.getCopy();
543 luaconfsCopy
.dsAnchors
.clear();
544 generateKeyMaterial(g_rootdnsname
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
, luaconfsCopy
.dsAnchors
);
545 generateKeyMaterial(parent1
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
546 generateKeyMaterial(parent2
, DNSSECKeeper::ECDSA256
, DNSSECKeeper::DIGEST_SHA256
, keys
);
547 g_luaconfs
.setState(luaconfsCopy
);
549 size_t queriesCount
= 0;
551 sr
->setAsyncCallback([target1
, target2
, target3
, target4
, &queriesCount
, keys
](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
) {
554 DNSName auth
= domain
;
555 if (domain
== target1
|| domain
== target2
|| domain
== target3
|| domain
== target4
) {
556 auth
= DNSName("powerdns.com.");
558 if (type
== QType::DS
|| type
== QType::DNSKEY
) {
559 if (type
== QType::DS
&& (domain
== target1
|| domain
== target2
|| domain
== target3
|| domain
== target4
)) {
560 setLWResult(res
, RCode::NXDomain
, true, false, true);
561 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
562 addRRSIG(keys
, res
->d_records
, auth
, 300);
563 addNSECRecordToLW(DNSName("wwa.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
564 addRRSIG(keys
, res
->d_records
, auth
, 300);
568 return genericDSAndDNSKEYHandler(res
, domain
, auth
, type
, keys
);
572 if (isRootServer(ip
)) {
573 setLWResult(res
, 0, false, false, true);
574 addRecordToLW(res
, "com.", QType::NS
, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY
, 3600);
575 addDS(DNSName("com."), 300, res
->d_records
, keys
);
576 addRRSIG(keys
, res
->d_records
, DNSName("."), 300);
577 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
580 else if (ip
== ComboAddress("192.0.2.1:53")) {
581 if (domain
== DNSName("com.")) {
582 setLWResult(res
, 0, true, false, true);
583 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.com.");
584 addRRSIG(keys
, res
->d_records
, domain
, 300);
585 addRecordToLW(res
, "a.gtld-servers.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
586 addRRSIG(keys
, res
->d_records
, domain
, 300);
589 setLWResult(res
, 0, false, false, true);
590 addRecordToLW(res
, auth
, QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 3600);
591 addDS(auth
, 300, res
->d_records
, keys
);
592 addRRSIG(keys
, res
->d_records
, DNSName("com."), 300);
593 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
597 else if (ip
== ComboAddress("192.0.2.2:53")) {
598 if (type
== QType::NS
) {
599 setLWResult(res
, 0, true, false, true);
600 if (domain
== DNSName("powerdns.com.")) {
601 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com.");
602 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
603 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
604 addRRSIG(keys
, res
->d_records
, DNSName("powerdns.com"), 300);
608 setLWResult(res
, RCode::NXDomain
, true, false, true);
609 addRecordToLW(res
, DNSName("powerdns.com."), QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
610 addRRSIG(keys
, res
->d_records
, auth
, 300);
611 addNSECRecordToLW(DNSName("wwa.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
612 addRRSIG(keys
, res
->d_records
, auth
, 300);
613 /* add wildcard denial */
614 addNSECRecordToLW(DNSName("powerdns.com."), DNSName("a.powerdns.com."), {QType::RRSIG
, QType::NSEC
}, 600, res
->d_records
);
615 addRRSIG(keys
, res
->d_records
, auth
, 300);
624 vector
<DNSRecord
> ret
;
625 int res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
626 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
627 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
628 BOOST_CHECK_EQUAL(ret
.size(), 6U);
629 BOOST_CHECK_EQUAL(queriesCount
, 9U);
630 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
633 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
634 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
635 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
636 BOOST_CHECK_EQUAL(ret
.size(), 6U);
637 BOOST_CHECK_EQUAL(queriesCount
, 9U);
638 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
641 res
= sr
->beginResolve(target3
, QType(QType::A
), QClass::IN
, ret
);
642 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
643 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
644 BOOST_CHECK_EQUAL(ret
.size(), 6U);
645 BOOST_CHECK_EQUAL(queriesCount
, 9U);
646 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
649 res
= sr
->beginResolve(target4
, QType(QType::A
), QClass::IN
, ret
);
650 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
651 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
652 BOOST_CHECK_EQUAL(ret
.size(), 6U);
653 BOOST_CHECK_EQUAL(queriesCount
, 9U);
654 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
656 // Now test without RFC 8020 to see the cache and query count grow
657 SyncRes::s_hardenNXD
= SyncRes::HardenNXD::No
;
661 res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
662 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
663 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
664 BOOST_CHECK_EQUAL(ret
.size(), 6U);
665 BOOST_CHECK_EQUAL(queriesCount
, 9U);
666 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
670 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
671 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
672 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
673 BOOST_CHECK_EQUAL(ret
.size(), 6U);
674 BOOST_CHECK_EQUAL(queriesCount
, 11U);
675 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2U);
678 res
= sr
->beginResolve(target3
, QType(QType::A
), QClass::IN
, ret
);
679 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
680 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
681 BOOST_CHECK_EQUAL(ret
.size(), 6U);
682 BOOST_CHECK_EQUAL(queriesCount
, 13U);
683 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 3U);
686 res
= sr
->beginResolve(target4
, QType(QType::A
), QClass::IN
, ret
);
687 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
688 BOOST_CHECK_EQUAL(sr
->getValidationState(), Secure
);
689 BOOST_CHECK_EQUAL(ret
.size(), 6U);
690 BOOST_CHECK_EQUAL(queriesCount
, 15U);
691 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 4U);
694 SyncRes::s_hardenNXD
= SyncRes::HardenNXD::DNSSEC
;
697 BOOST_AUTO_TEST_CASE(test_rfc8020_nodata
)
699 std::unique_ptr
<SyncRes
> sr
;
701 SyncRes::s_hardenNXD
= SyncRes::HardenNXD::Yes
;
705 const DNSName
target1("www.powerdns.com."); // TXT record will be denied
706 const DNSName
target2("bar.www.powerdns.com."); // will be NXD, but the www. NODATA should not interfere with 8020 processing
707 const DNSName
target3("quux.bar.www.powerdns.com."); // will be NXD, but will not yield a query
708 const ComboAddress
ns("192.0.2.1:53");
709 size_t queriesCount
= 0;
711 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
) {
714 if (isRootServer(ip
)) {
715 setLWResult(res
, 0, false, false, true);
716 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
717 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
721 if (domain
== target1
) { // NODATA for TXT, NOERROR for A
722 if (type
== QType::TXT
) {
723 setLWResult(res
, RCode::NoError
, true);
724 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "ns1.powerdns.com. hostmaster.powerdns.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
727 if (type
== QType::A
) {
728 setLWResult(res
, RCode::NoError
, true);
729 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1", DNSResourceRecord::ANSWER
, 86400);
733 if (domain
== target2
|| domain
== target3
) {
734 setLWResult(res
, RCode::NXDomain
, true);
735 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "ns1.powerdns.com. hostmaster.powerdns.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
742 vector
<DNSRecord
> ret
;
743 int res
= sr
->beginResolve(target1
, QType(QType::TXT
), QClass::IN
, ret
);
744 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
745 BOOST_CHECK_EQUAL(ret
.size(), 1U);
746 BOOST_CHECK_EQUAL(queriesCount
, 2U);
747 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
750 res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
751 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
752 BOOST_CHECK_EQUAL(ret
.size(), 1U);
753 BOOST_CHECK_EQUAL(queriesCount
, 3U);
754 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
757 res
= sr
->beginResolve(target2
, QType(QType::A
), QClass::IN
, ret
);
758 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
759 BOOST_CHECK_EQUAL(ret
.size(), 1U);
760 BOOST_CHECK_EQUAL(queriesCount
, 4U);
761 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2U);
764 res
= sr
->beginResolve(target3
, QType(QType::A
), QClass::IN
, ret
);
765 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
766 BOOST_CHECK_EQUAL(ret
.size(), 1U);
767 BOOST_CHECK_EQUAL(queriesCount
, 4U);
768 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2U);
771 BOOST_AUTO_TEST_CASE(test_rfc8020_nodata_bis
)
773 std::unique_ptr
<SyncRes
> sr
;
775 SyncRes::s_hardenNXD
= SyncRes::HardenNXD::Yes
;
779 const DNSName
target1("www.powerdns.com."); // TXT record will be denied
780 const DNSName
target2("bar.www.powerdns.com."); // will be NXD, but the www. NODATA should not interfere with 8020 processing
781 const DNSName
target3("quux.bar.www.powerdns.com."); // will be NXD, but will not yield a query
782 const ComboAddress
ns("192.0.2.1:53");
783 size_t queriesCount
= 0;
785 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
) {
788 if (isRootServer(ip
)) {
789 setLWResult(res
, 0, false, false, true);
790 addRecordToLW(res
, "powerdns.com.", QType::NS
, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
791 addRecordToLW(res
, "ns1.powerdns.com.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 3600);
795 if (domain
== target1
) { // NODATA for TXT, NOERROR for A
796 if (type
== QType::TXT
) {
797 setLWResult(res
, RCode::NoError
, true);
798 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "ns1.powerdns.com. hostmaster.powerdns.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
801 if (type
== QType::A
) {
802 setLWResult(res
, RCode::NoError
, true);
803 addRecordToLW(res
, domain
, QType::A
, "192.0.2.1", DNSResourceRecord::ANSWER
, 86400);
807 if (domain
== target2
|| domain
== target3
) {
808 setLWResult(res
, RCode::NXDomain
, true);
809 addRecordToLW(res
, "powerdns.com.", QType::SOA
, "ns1.powerdns.com. hostmaster.powerdns.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
816 vector
<DNSRecord
> ret
;
817 int res
= sr
->beginResolve(target1
, QType(QType::TXT
), QClass::IN
, ret
);
818 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
819 BOOST_CHECK_EQUAL(ret
.size(), 1U);
820 BOOST_CHECK_EQUAL(queriesCount
, 2U);
821 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
824 res
= sr
->beginResolve(target1
, QType(QType::A
), QClass::IN
, ret
);
825 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
826 BOOST_CHECK_EQUAL(ret
.size(), 1U);
827 BOOST_CHECK_EQUAL(queriesCount
, 3U);
828 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
831 res
= sr
->beginResolve(target2
, QType(QType::TXT
), QClass::IN
, ret
);
832 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
833 BOOST_CHECK_EQUAL(ret
.size(), 1U);
834 BOOST_CHECK_EQUAL(queriesCount
, 4U);
835 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2U);
838 res
= sr
->beginResolve(target3
, QType(QType::TXT
), QClass::IN
, ret
);
839 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
840 BOOST_CHECK_EQUAL(ret
.size(), 1U);
841 BOOST_CHECK_EQUAL(queriesCount
, 4U);
842 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2U);
845 BOOST_AUTO_TEST_CASE(test_skip_negcache_for_variable_response
)
847 std::unique_ptr
<SyncRes
> sr
;
852 const DNSName
target("www.powerdns.com.");
853 const DNSName
cnameTarget("cname.powerdns.com.");
855 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
857 EDNSSubnetOpts incomingECS
;
858 incomingECS
.source
= Netmask("192.0.2.128/32");
859 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
861 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
) {
862 BOOST_REQUIRE(srcmask
);
863 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
865 if (isRootServer(ip
)) {
866 setLWResult(res
, 0, false, false, true);
867 addRecordToLW(res
, "powerdns.com.", QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
868 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
870 srcmask
= boost::none
;
874 else if (ip
== ComboAddress("192.0.2.1:53")) {
875 if (domain
== target
) {
876 /* Type 2 NXDOMAIN (rfc2308 section-2.1) */
877 setLWResult(res
, RCode::NXDomain
, true, false, true);
878 addRecordToLW(res
, domain
, QType::CNAME
, cnameTarget
.toString());
879 addRecordToLW(res
, "powerdns.com", QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
881 else if (domain
== cnameTarget
) {
882 /* we shouldn't get there since the Type NXDOMAIN should have been enough,
883 but we might if we still chase the CNAME. */
884 setLWResult(res
, RCode::NXDomain
, true, false, true);
885 addRecordToLW(res
, "powerdns.com", QType::SOA
, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY
, 3600);
894 vector
<DNSRecord
> ret
;
895 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
896 BOOST_CHECK_EQUAL(res
, RCode::NXDomain
);
897 BOOST_CHECK_EQUAL(ret
.size(), 2U);
898 /* no negative cache entry because the response was variable */
899 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 0U);
902 BOOST_AUTO_TEST_CASE(test_ecs_cache_limit_allowed
)
904 std::unique_ptr
<SyncRes
> sr
;
909 const DNSName
target("www.powerdns.com.");
911 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
913 EDNSSubnetOpts incomingECS
;
914 incomingECS
.source
= Netmask("192.0.2.128/32");
915 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
916 SyncRes::s_ecsipv4cachelimit
= 24;
918 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
) {
919 BOOST_REQUIRE(srcmask
);
920 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
922 setLWResult(res
, 0, true, false, true);
923 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
928 const time_t now
= sr
->getNow().tv_sec
;
929 vector
<DNSRecord
> ret
;
930 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
931 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
932 BOOST_CHECK_EQUAL(ret
.size(), 1U);
934 /* should have been cached */
935 const ComboAddress
who("192.0.2.128");
936 vector
<DNSRecord
> cached
;
937 BOOST_REQUIRE_GT(s_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
938 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
941 BOOST_AUTO_TEST_CASE(test_ecs_cache_limit_no_ttl_limit_allowed
)
943 std::unique_ptr
<SyncRes
> sr
;
948 const DNSName
target("www.powerdns.com.");
950 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
952 EDNSSubnetOpts incomingECS
;
953 incomingECS
.source
= Netmask("192.0.2.128/32");
954 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
955 SyncRes::s_ecsipv4cachelimit
= 16;
957 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
) {
958 BOOST_REQUIRE(srcmask
);
959 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
961 setLWResult(res
, 0, true, false, true);
962 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
967 const time_t now
= sr
->getNow().tv_sec
;
968 vector
<DNSRecord
> ret
;
969 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
970 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
971 BOOST_CHECK_EQUAL(ret
.size(), 1U);
973 /* should have been cached because /24 is more specific than /16 but TTL limit is nof effective */
974 const ComboAddress
who("192.0.2.128");
975 vector
<DNSRecord
> cached
;
976 BOOST_REQUIRE_GT(s_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
977 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
980 BOOST_AUTO_TEST_CASE(test_ecs_cache_ttllimit_allowed
)
982 std::unique_ptr
<SyncRes
> sr
;
987 const DNSName
target("www.powerdns.com.");
989 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
991 EDNSSubnetOpts incomingECS
;
992 incomingECS
.source
= Netmask("192.0.2.128/32");
993 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
994 SyncRes::s_ecscachelimitttl
= 30;
996 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
) {
997 BOOST_REQUIRE(srcmask
);
998 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1000 setLWResult(res
, 0, true, false, true);
1001 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
1006 const time_t now
= sr
->getNow().tv_sec
;
1007 vector
<DNSRecord
> ret
;
1008 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1009 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1010 BOOST_CHECK_EQUAL(ret
.size(), 1U);
1012 /* should have been cached */
1013 const ComboAddress
who("192.0.2.128");
1014 vector
<DNSRecord
> cached
;
1015 BOOST_REQUIRE_GT(s_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
1016 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
1019 BOOST_AUTO_TEST_CASE(test_ecs_cache_ttllimit_and_scope_allowed
)
1021 std::unique_ptr
<SyncRes
> sr
;
1026 const DNSName
target("www.powerdns.com.");
1028 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
1030 EDNSSubnetOpts incomingECS
;
1031 incomingECS
.source
= Netmask("192.0.2.128/32");
1032 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1033 SyncRes::s_ecscachelimitttl
= 100;
1034 SyncRes::s_ecsipv4cachelimit
= 24;
1036 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
) {
1037 BOOST_REQUIRE(srcmask
);
1038 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1040 setLWResult(res
, 0, true, false, true);
1041 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
1046 const time_t now
= sr
->getNow().tv_sec
;
1047 vector
<DNSRecord
> ret
;
1048 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1049 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1050 BOOST_CHECK_EQUAL(ret
.size(), 1U);
1052 /* should have been cached */
1053 const ComboAddress
who("192.0.2.128");
1054 vector
<DNSRecord
> cached
;
1055 BOOST_REQUIRE_GT(s_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
1056 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
1059 BOOST_AUTO_TEST_CASE(test_ecs_cache_ttllimit_notallowed
)
1061 std::unique_ptr
<SyncRes
> sr
;
1066 const DNSName
target("www.powerdns.com.");
1068 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
1070 EDNSSubnetOpts incomingECS
;
1071 incomingECS
.source
= Netmask("192.0.2.128/32");
1072 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1073 SyncRes::s_ecscachelimitttl
= 100;
1074 SyncRes::s_ecsipv4cachelimit
= 16;
1076 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
) {
1077 BOOST_REQUIRE(srcmask
);
1078 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1080 setLWResult(res
, 0, true, false, true);
1081 addRecordToLW(res
, target
, QType::A
, "192.0.2.1");
1086 const time_t now
= sr
->getNow().tv_sec
;
1087 vector
<DNSRecord
> ret
;
1088 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1089 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1090 BOOST_CHECK_EQUAL(ret
.size(), 1U);
1092 /* should have NOT been cached because TTL of 60 is too small and /24 is more specific than /16 */
1093 const ComboAddress
who("192.0.2.128");
1094 vector
<DNSRecord
> cached
;
1095 BOOST_REQUIRE_LT(s_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
1096 BOOST_REQUIRE_EQUAL(cached
.size(), 0U);
1099 BOOST_AUTO_TEST_CASE(test_ns_speed
)
1101 std::unique_ptr
<SyncRes
> sr
;
1106 const DNSName
target("powerdns.com.");
1108 std::map
<ComboAddress
, uint64_t> nsCounts
;
1110 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
) {
1111 if (isRootServer(ip
)) {
1112 setLWResult(res
, 0, false, false, true);
1113 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1114 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1115 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1117 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1118 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::AAAA
, "2001:DB8::1", DNSResourceRecord::ADDITIONAL
, 3600);
1119 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::A
, "192.0.2.2", DNSResourceRecord::ADDITIONAL
, 3600);
1120 addRecordToLW(res
, "pdns-public-ns2.powerdns.com.", QType::AAAA
, "2001:DB8::2", DNSResourceRecord::ADDITIONAL
, 3600);
1121 addRecordToLW(res
, "pdns-public-ns3.powerdns.com.", QType::A
, "192.0.2.3", DNSResourceRecord::ADDITIONAL
, 3600);
1122 addRecordToLW(res
, "pdns-public-ns3.powerdns.com.", QType::AAAA
, "2001:DB8::3", DNSResourceRecord::ADDITIONAL
, 3600);
1129 if (ip
== ComboAddress("[2001:DB8::2]:53") || ip
== ComboAddress("192.0.2.2:53")) {
1130 BOOST_CHECK_LT(nsCounts
.size(), 3U);
1132 /* let's time out on pdns-public-ns2.powerdns.com. */
1135 else if (ip
== ComboAddress("192.0.2.1:53")) {
1136 BOOST_CHECK_EQUAL(nsCounts
.size(), 3U);
1138 setLWResult(res
, 0, true, false, true);
1139 addRecordToLW(res
, domain
, QType::A
, "192.0.2.254");
1149 struct timeval now
= sr
->getNow();
1151 /* make pdns-public-ns2.powerdns.com. the fastest NS, with its IPv6 address faster than the IPV4 one,
1152 then pdns-public-ns1.powerdns.com. on IPv4 */
1153 SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("192.0.2.1:53"), 100, now
);
1154 SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("[2001:DB8::1]:53"), 10000, now
);
1155 SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("192.0.2.2:53"), 10, now
);
1156 SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("[2001:DB8::2]:53"), 1, now
);
1157 SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("192.0.2.3:53"), 10000, now
);
1158 SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("[2001:DB8::3]:53"), 10000, now
);
1160 vector
<DNSRecord
> ret
;
1161 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1162 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1163 BOOST_CHECK_EQUAL(ret
.size(), 1U);
1164 BOOST_CHECK_EQUAL(nsCounts
.size(), 3U);
1165 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("192.0.2.1:53")], 1U);
1166 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("192.0.2.2:53")], 1U);
1167 BOOST_CHECK_EQUAL(nsCounts
[ComboAddress("[2001:DB8::2]:53")], 1U);
1170 BOOST_AUTO_TEST_CASE(test_flawed_nsset
)
1172 std::unique_ptr
<SyncRes
> sr
;
1177 const DNSName
target("powerdns.com.");
1179 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
) {
1180 if (isRootServer(ip
)) {
1181 setLWResult(res
, 0, false, false, true);
1182 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1184 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1188 else if (ip
== ComboAddress("192.0.2.1:53")) {
1189 setLWResult(res
, 0, true, false, true);
1190 addRecordToLW(res
, domain
, QType::A
, "192.0.2.254");
1197 /* we populate the cache with a flawed NSset, i.e. there is a NS entry but no corresponding glue */
1198 time_t now
= sr
->getNow().tv_sec
;
1199 std::vector
<DNSRecord
> records
;
1200 std::vector
<shared_ptr
<RRSIGRecordContent
>> sigs
;
1201 addRecordToList(records
, target
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, now
+ 3600);
1203 s_RC
->replace(now
, target
, QType(QType::NS
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
1205 vector
<DNSRecord
> ret
;
1206 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1207 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1208 BOOST_CHECK_EQUAL(ret
.size(), 1U);
1211 BOOST_AUTO_TEST_CASE(test_completely_flawed_nsset
)
1213 std::unique_ptr
<SyncRes
> sr
;
1218 const DNSName
target("powerdns.com.");
1219 size_t queriesCount
= 0;
1221 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
) {
1224 if (isRootServer(ip
) && domain
== target
) {
1225 setLWResult(res
, 0, false, false, true);
1226 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1227 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1230 else if (domain
== DNSName("pdns-public-ns2.powerdns.com.") || domain
== DNSName("pdns-public-ns3.powerdns.com.")) {
1231 setLWResult(res
, 0, true, false, true);
1232 addRecordToLW(res
, ".", QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
1239 vector
<DNSRecord
> ret
;
1240 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1241 BOOST_CHECK_EQUAL(res
, RCode::ServFail
);
1242 BOOST_CHECK_EQUAL(ret
.size(), 0U);
1243 /* one query to get NSs, then A and AAAA for each NS */
1244 BOOST_CHECK_EQUAL(queriesCount
, 5U);
1247 BOOST_AUTO_TEST_CASE(test_cache_hit
)
1249 std::unique_ptr
<SyncRes
> sr
;
1254 const DNSName
target("powerdns.com.");
1256 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
) {
1260 /* we populate the cache with eveything we need */
1261 time_t now
= sr
->getNow().tv_sec
;
1262 std::vector
<DNSRecord
> records
;
1263 std::vector
<shared_ptr
<RRSIGRecordContent
>> sigs
;
1265 addRecordToList(records
, target
, QType::A
, "192.0.2.1", DNSResourceRecord::ANSWER
, now
+ 3600);
1266 s_RC
->replace(now
, target
, QType(QType::A
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
1268 vector
<DNSRecord
> ret
;
1269 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1270 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1271 BOOST_CHECK_EQUAL(ret
.size(), 1U);
1274 BOOST_AUTO_TEST_CASE(test_no_rd
)
1276 std::unique_ptr
<SyncRes
> sr
;
1281 const DNSName
target("powerdns.com.");
1282 size_t queriesCount
= 0;
1286 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
) {
1291 vector
<DNSRecord
> ret
;
1292 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1293 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1294 BOOST_CHECK_EQUAL(ret
.size(), 0U);
1295 BOOST_CHECK_EQUAL(queriesCount
, 0U);
1298 BOOST_AUTO_TEST_CASE(test_cache_min_max_ttl
)
1300 std::unique_ptr
<SyncRes
> sr
;
1305 const DNSName
target("cachettl.powerdns.com.");
1306 const ComboAddress
ns("192.0.2.1:53");
1308 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
) {
1309 if (isRootServer(ip
)) {
1311 setLWResult(res
, 0, false, false, true);
1312 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1313 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 7200);
1316 else if (ip
== ns
) {
1318 setLWResult(res
, 0, true, false, false);
1319 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2", DNSResourceRecord::ANSWER
, 10);
1327 const time_t now
= sr
->getNow().tv_sec
;
1328 SyncRes::s_minimumTTL
= 60;
1329 SyncRes::s_maxcachettl
= 3600;
1331 vector
<DNSRecord
> ret
;
1332 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1333 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1334 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1335 BOOST_CHECK_EQUAL(ret
[0].d_ttl
, SyncRes::s_minimumTTL
);
1337 const ComboAddress who
;
1338 vector
<DNSRecord
> cached
;
1339 BOOST_REQUIRE_GT(s_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
1340 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
1341 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
1342 BOOST_CHECK_EQUAL((cached
[0].d_ttl
- now
), SyncRes::s_minimumTTL
);
1345 BOOST_REQUIRE_GT(s_RC
->get(now
, target
, QType(QType::NS
), false, &cached
, who
), 0);
1346 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
1347 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
1348 BOOST_CHECK_LE((cached
[0].d_ttl
- now
), SyncRes::s_maxcachettl
);
1351 BOOST_AUTO_TEST_CASE(test_cache_min_max_ecs_ttl
)
1353 std::unique_ptr
<SyncRes
> sr
;
1358 const DNSName
target("cacheecsttl.powerdns.com.");
1359 const ComboAddress
ns("192.0.2.1:53");
1361 EDNSSubnetOpts incomingECS
;
1362 incomingECS
.source
= Netmask("192.0.2.128/32");
1363 sr
->setQuerySource(ComboAddress(), boost::optional
<const EDNSSubnetOpts
&>(incomingECS
));
1364 SyncRes::addEDNSDomain(target
);
1366 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
) {
1367 BOOST_REQUIRE(srcmask
);
1368 BOOST_CHECK_EQUAL(srcmask
->toString(), "192.0.2.0/24");
1370 if (isRootServer(ip
)) {
1372 setLWResult(res
, 0, false, false, true);
1373 addRecordToLW(res
, domain
, QType::NS
, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY
, 172800);
1374 addRecordToLW(res
, "a.gtld-servers.net.", QType::A
, ns
.toString(), DNSResourceRecord::ADDITIONAL
, 20);
1375 srcmask
= boost::none
;
1379 else if (ip
== ns
) {
1381 setLWResult(res
, 0, true, false, false);
1382 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2", DNSResourceRecord::ANSWER
, 10);
1390 const time_t now
= sr
->getNow().tv_sec
;
1391 SyncRes::s_minimumTTL
= 60;
1392 SyncRes::s_minimumECSTTL
= 120;
1393 SyncRes::s_maxcachettl
= 3600;
1395 vector
<DNSRecord
> ret
;
1396 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1397 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1398 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1399 BOOST_CHECK_EQUAL(ret
[0].d_ttl
, SyncRes::s_minimumECSTTL
);
1401 const ComboAddress
who("192.0.2.128");
1402 vector
<DNSRecord
> cached
;
1403 BOOST_REQUIRE_GT(s_RC
->get(now
, target
, QType(QType::A
), true, &cached
, who
), 0);
1404 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
1405 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
1406 BOOST_CHECK_EQUAL((cached
[0].d_ttl
- now
), SyncRes::s_minimumECSTTL
);
1409 BOOST_REQUIRE_GT(s_RC
->get(now
, target
, QType(QType::NS
), false, &cached
, who
), 0);
1410 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
1411 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
1412 BOOST_CHECK_LE((cached
[0].d_ttl
- now
), SyncRes::s_maxcachettl
);
1415 BOOST_REQUIRE_GT(s_RC
->get(now
, DNSName("a.gtld-servers.net."), QType(QType::A
), false, &cached
, who
), 0);
1416 BOOST_REQUIRE_EQUAL(cached
.size(), 1U);
1417 BOOST_REQUIRE_GT(cached
[0].d_ttl
, now
);
1418 BOOST_CHECK_LE((cached
[0].d_ttl
- now
), SyncRes::s_minimumTTL
);
1421 BOOST_AUTO_TEST_CASE(test_cache_expired_ttl
)
1423 std::unique_ptr
<SyncRes
> sr
;
1428 const DNSName
target("powerdns.com.");
1430 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
) {
1431 if (isRootServer(ip
)) {
1432 setLWResult(res
, 0, false, false, true);
1433 addRecordToLW(res
, domain
, QType::NS
, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY
, 172800);
1435 addRecordToLW(res
, "pdns-public-ns1.powerdns.com.", QType::A
, "192.0.2.1", DNSResourceRecord::ADDITIONAL
, 3600);
1439 else if (ip
== ComboAddress("192.0.2.1:53")) {
1440 setLWResult(res
, 0, true, false, true);
1441 addRecordToLW(res
, domain
, QType::A
, "192.0.2.2");
1448 /* we populate the cache with entries that expired 60s ago*/
1449 const time_t now
= sr
->getNow().tv_sec
;
1451 std::vector
<DNSRecord
> records
;
1452 std::vector
<shared_ptr
<RRSIGRecordContent
>> sigs
;
1453 addRecordToList(records
, target
, QType::A
, "192.0.2.42", DNSResourceRecord::ANSWER
, now
- 60);
1455 s_RC
->replace(now
- 3600, target
, QType(QType::A
), records
, sigs
, vector
<std::shared_ptr
<DNSRecord
>>(), true, boost::optional
<Netmask
>());
1457 vector
<DNSRecord
> ret
;
1458 int res
= sr
->beginResolve(target
, QType(QType::A
), QClass::IN
, ret
);
1459 BOOST_CHECK_EQUAL(res
, RCode::NoError
);
1460 BOOST_REQUIRE_EQUAL(ret
.size(), 1U);
1461 BOOST_REQUIRE(ret
[0].d_type
== QType::A
);
1462 BOOST_CHECK_EQUAL(getRR
<ARecordContent
>(ret
[0])->getCA().toStringWithPort(), ComboAddress("192.0.2.2").toStringWithPort());
1465 BOOST_AUTO_TEST_SUITE_END()