]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/recursordist/test-syncres_cc2.cc
Fix warnings about dup/missing prototypes
[thirdparty/pdns.git] / pdns / recursordist / test-syncres_cc2.cc
CommitLineData
86675669
OM
1#define BOOST_TEST_DYN_LINK
2#include <boost/test/unit_test.hpp>
3
4#include "test-syncres_cc.hh"
5
6BOOST_AUTO_TEST_SUITE(syncres_cc2)
7
050e6877 8static void do_test_referral_depth(bool limited)
42dcf516 9{
86675669
OM
10 std::unique_ptr<SyncRes> sr;
11 initSR(sr);
12
13 primeHints();
14
15 size_t queries = 0;
16 const DNSName target("www.powerdns.com.");
17
42dcf516
OM
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) {
19 queries++;
86675669 20
42dcf516
OM
21 if (isRootServer(ip)) {
22 setLWResult(res, 0, false, false, true);
86675669 23
42dcf516
OM
24 if (domain == DNSName("www.powerdns.com.")) {
25 addRecordToLW(res, domain, QType::NS, "ns.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
26 }
27 else if (domain == DNSName("ns.powerdns.com.")) {
28 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.org.", DNSResourceRecord::AUTHORITY, 172800);
29 }
30 else if (domain == DNSName("ns1.powerdns.org.")) {
31 addRecordToLW(res, domain, QType::NS, "ns2.powerdns.org.", DNSResourceRecord::AUTHORITY, 172800);
32 }
33 else if (domain == DNSName("ns2.powerdns.org.")) {
34 addRecordToLW(res, domain, QType::NS, "ns3.powerdns.org.", DNSResourceRecord::AUTHORITY, 172800);
35 }
36 else if (domain == DNSName("ns3.powerdns.org.")) {
37 addRecordToLW(res, domain, QType::NS, "ns4.powerdns.org.", DNSResourceRecord::AUTHORITY, 172800);
ca34b34f 38 addRecordToLW(res, "ns4.powerdns.org.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
42dcf516 39 }
86675669 40
42dcf516
OM
41 return 1;
42 }
43 else if (ip == ComboAddress("192.0.2.1:53")) {
42dcf516 44 setLWResult(res, 0, true, false, false);
ca34b34f
OM
45 if (domain == DNSName("www.powerdns.com.")) {
46 addRecordToLW(res, domain, QType::A, "192.0.2.2");
47 }
48 else {
49 addRecordToLW(res, domain, QType::A, "192.0.2.1");
50 }
42dcf516
OM
51 return 1;
52 }
86675669 53
42dcf516
OM
54 return 0;
55 });
86675669 56
46817cd2
OM
57 if (limited) {
58 /* Set the maximum depth low */
59 SyncRes::s_maxdepth = 10;
60 try {
61 vector<DNSRecord> ret;
62 sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
63 BOOST_CHECK(false);
64 }
65 catch (const ImmediateServFailException& e) {
66 BOOST_CHECK(e.reason.find("max-recursion-depth") != string::npos);
67 }
86675669 68 }
46817cd2
OM
69 else {
70 // Check if the setup with high limit is OK.
71 SyncRes::s_maxdepth = 50;
72 try {
73 vector<DNSRecord> ret;
74 int rcode = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
75 BOOST_CHECK_EQUAL(rcode, RCode::NoError);
76 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
77 BOOST_CHECK_EQUAL(ret[0].d_name, target);
78 BOOST_REQUIRE(ret[0].d_type == QType::A);
79 BOOST_CHECK(getRR<ARecordContent>(ret[0])->getCA() == ComboAddress("192.0.2.2"));
80 }
81 catch (const ImmediateServFailException& e) {
82 BOOST_CHECK(false);
83 }
ca34b34f 84 }
46817cd2 85}
ca34b34f 86
46817cd2
OM
87BOOST_AUTO_TEST_CASE(test_referral_depth)
88{
89 // Test with limit
90 do_test_referral_depth(true);
91}
92
93BOOST_AUTO_TEST_CASE(test_referral_depth_ok)
94{
95 // Test with default limit
96 do_test_referral_depth(false);
86675669
OM
97}
98
42dcf516
OM
99BOOST_AUTO_TEST_CASE(test_cname_qperq)
100{
86675669
OM
101 std::unique_ptr<SyncRes> sr;
102 initSR(sr);
103
104 primeHints();
105
106 size_t queries = 0;
107 const DNSName target("cname.powerdns.com.");
108
42dcf516
OM
109 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) {
110 queries++;
86675669 111
42dcf516 112 if (isRootServer(ip)) {
86675669 113
42dcf516
OM
114 setLWResult(res, 0, false, false, true);
115 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
116 addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
117 return 1;
118 }
119 else if (ip == ComboAddress("192.0.2.1:53")) {
86675669 120
42dcf516
OM
121 setLWResult(res, 0, true, false, false);
122 addRecordToLW(res, domain, QType::CNAME, std::to_string(queries) + "-cname.powerdns.com");
123 return 1;
124 }
86675669 125
42dcf516
OM
126 return 0;
127 });
86675669
OM
128
129 /* Set the maximum number of questions very low */
130 SyncRes::s_maxqperq = 5;
131
132 try {
133 vector<DNSRecord> ret;
134 sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
135 BOOST_CHECK(false);
136 }
42dcf516 137 catch (const ImmediateServFailException& e) {
86675669
OM
138 BOOST_CHECK_EQUAL(queries, SyncRes::s_maxqperq);
139 }
140}
141
42dcf516
OM
142BOOST_AUTO_TEST_CASE(test_throttled_server)
143{
86675669
OM
144 std::unique_ptr<SyncRes> sr;
145 initSR(sr);
146
147 primeHints();
148
149 const DNSName target("throttled.powerdns.com.");
150 const ComboAddress ns("192.0.2.1:53");
151 size_t queriesToNS = 0;
152
42dcf516
OM
153 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) {
154 if (isRootServer(ip)) {
86675669 155
42dcf516
OM
156 setLWResult(res, 0, false, false, true);
157 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
158 addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
159 return 1;
160 }
161 else if (ip == ns) {
86675669 162
42dcf516 163 queriesToNS++;
86675669 164
42dcf516
OM
165 setLWResult(res, 0, true, false, false);
166 addRecordToLW(res, domain, QType::A, "192.0.2.2");
86675669 167
42dcf516
OM
168 return 1;
169 }
86675669 170
42dcf516
OM
171 return 0;
172 });
86675669
OM
173
174 /* mark ns as down */
175 time_t now = sr->getNow().tv_sec;
176 SyncRes::doThrottle(now, ns, SyncRes::s_serverdownthrottletime, 10000);
177
178 vector<DNSRecord> ret;
179 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
180 BOOST_CHECK_EQUAL(res, RCode::ServFail);
690b86b7 181 BOOST_CHECK_EQUAL(ret.size(), 0U);
86675669 182 /* we should not have sent any queries to ns */
690b86b7 183 BOOST_CHECK_EQUAL(queriesToNS, 0U);
86675669
OM
184}
185
42dcf516
OM
186BOOST_AUTO_TEST_CASE(test_throttled_server_count)
187{
86675669
OM
188 std::unique_ptr<SyncRes> sr;
189 initSR(sr);
190
191 primeHints();
192
193 const ComboAddress ns("192.0.2.1:53");
194
195 const size_t blocks = 10;
196 /* mark ns as down for 'blocks' queries */
197 time_t now = sr->getNow().tv_sec;
198 SyncRes::doThrottle(now, ns, SyncRes::s_serverdownthrottletime, blocks);
199
200 for (size_t idx = 0; idx < blocks; idx++) {
201 BOOST_CHECK(SyncRes::isThrottled(now, ns));
202 }
203
204 /* we have been throttled 'blocks' times, we should not be throttled anymore */
205 BOOST_CHECK(!SyncRes::isThrottled(now, ns));
206}
207
42dcf516
OM
208BOOST_AUTO_TEST_CASE(test_throttled_server_time)
209{
86675669
OM
210 std::unique_ptr<SyncRes> sr;
211 initSR(sr);
212
213 primeHints();
214
215 const ComboAddress ns("192.0.2.1:53");
216
217 const size_t seconds = 1;
218 /* mark ns as down for 'seconds' seconds */
219 time_t now = sr->getNow().tv_sec;
220 SyncRes::doThrottle(now, ns, seconds, 10000);
221
222 BOOST_CHECK(SyncRes::isThrottled(now, ns));
223
224 /* we should not be throttled anymore */
225 BOOST_CHECK(!SyncRes::isThrottled(now + 2, ns));
226}
227
42dcf516
OM
228BOOST_AUTO_TEST_CASE(test_dont_query_server)
229{
86675669
OM
230 std::unique_ptr<SyncRes> sr;
231 initSR(sr);
232
233 primeHints();
234
235 const DNSName target("throttled.powerdns.com.");
236 const ComboAddress ns("192.0.2.1:53");
237 size_t queriesToNS = 0;
238
42dcf516
OM
239 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) {
240 if (isRootServer(ip)) {
86675669 241
42dcf516
OM
242 setLWResult(res, 0, false, false, true);
243 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
244 addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
245 return 1;
246 }
247 else if (ip == ns) {
86675669 248
42dcf516 249 queriesToNS++;
86675669 250
42dcf516
OM
251 setLWResult(res, 0, true, false, false);
252 addRecordToLW(res, domain, QType::A, "192.0.2.2");
86675669 253
42dcf516
OM
254 return 1;
255 }
86675669 256
42dcf516
OM
257 return 0;
258 });
86675669
OM
259
260 /* prevent querying this NS */
261 SyncRes::addDontQuery(Netmask(ns));
262
263 vector<DNSRecord> ret;
264 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
265 BOOST_CHECK_EQUAL(res, RCode::ServFail);
690b86b7 266 BOOST_CHECK_EQUAL(ret.size(), 0U);
86675669 267 /* we should not have sent any queries to ns */
690b86b7 268 BOOST_CHECK_EQUAL(queriesToNS, 0U);
86675669
OM
269}
270
42dcf516
OM
271BOOST_AUTO_TEST_CASE(test_root_nx_trust)
272{
86675669
OM
273 std::unique_ptr<SyncRes> sr;
274 initSR(sr);
275
276 primeHints();
277
278 const DNSName target1("powerdns.com.");
279 const DNSName target2("notpowerdns.com.");
280 const ComboAddress ns("192.0.2.1:53");
281 size_t queriesCount = 0;
282
283 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) {
42dcf516 284 queriesCount++;
86675669 285
42dcf516 286 if (isRootServer(ip)) {
86675669 287
42dcf516
OM
288 if (domain == target1) {
289 setLWResult(res, RCode::NXDomain, true, false, true);
290 addRecordToLW(res, ".", QType::SOA, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400);
291 }
292 else {
293 setLWResult(res, 0, true, false, true);
294 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
295 addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
296 }
86675669 297
42dcf516
OM
298 return 1;
299 }
300 else if (ip == ns) {
86675669 301
42dcf516
OM
302 setLWResult(res, 0, true, false, false);
303 addRecordToLW(res, domain, QType::A, "192.0.2.2");
86675669 304
42dcf516
OM
305 return 1;
306 }
86675669 307
42dcf516
OM
308 return 0;
309 });
86675669
OM
310
311 SyncRes::s_maxnegttl = 3600;
312
313 vector<DNSRecord> ret;
314 int res = sr->beginResolve(target1, QType(QType::A), QClass::IN, ret);
315 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
690b86b7 316 BOOST_CHECK_EQUAL(ret.size(), 1U);
86675669 317 /* one for target1 and one for the entire TLD */
690b86b7 318 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2U);
86675669
OM
319
320 ret.clear();
321 res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret);
322 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
690b86b7 323 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
86675669
OM
324 BOOST_CHECK_LE(ret[0].d_ttl, SyncRes::s_maxnegttl);
325 /* one for target1 and one for the entire TLD */
690b86b7 326 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2U);
86675669
OM
327
328 /* we should have sent only one query */
690b86b7 329 BOOST_CHECK_EQUAL(queriesCount, 1U);
86675669
OM
330}
331
42dcf516
OM
332BOOST_AUTO_TEST_CASE(test_root_nx_trust_specific)
333{
86675669
OM
334 std::unique_ptr<SyncRes> sr;
335 initSR();
336 initSR(sr, true, false);
337
338 primeHints();
339
340 const DNSName target1("powerdns.com.");
341 const DNSName target2("notpowerdns.com.");
342 const ComboAddress ns("192.0.2.1:53");
343 size_t queriesCount = 0;
344
345 /* This time the root denies target1 with a "com." SOA instead of a "." one.
346 We should add target1 to the negcache, but not "com.". */
347
348 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) {
42dcf516 349 queriesCount++;
86675669 350
42dcf516 351 if (isRootServer(ip)) {
86675669 352
42dcf516
OM
353 if (domain == target1) {
354 setLWResult(res, RCode::NXDomain, true, false, true);
355 addRecordToLW(res, "com.", QType::SOA, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400);
356 }
357 else {
358 setLWResult(res, 0, true, false, true);
359 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
360 addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
361 }
86675669 362
42dcf516
OM
363 return 1;
364 }
365 else if (ip == ns) {
86675669 366
42dcf516
OM
367 setLWResult(res, 0, true, false, false);
368 addRecordToLW(res, domain, QType::A, "192.0.2.2");
86675669 369
42dcf516
OM
370 return 1;
371 }
86675669 372
42dcf516
OM
373 return 0;
374 });
86675669
OM
375
376 vector<DNSRecord> ret;
377 int res = sr->beginResolve(target1, QType(QType::A), QClass::IN, ret);
378 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
690b86b7 379 BOOST_CHECK_EQUAL(ret.size(), 1U);
86675669
OM
380
381 /* even with root-nx-trust on and a NX answer from the root,
382 we should not have cached the entire TLD this time. */
690b86b7 383 BOOST_CHECK_EQUAL(SyncRes::t_sstorage.negcache.size(), 1U);
86675669
OM
384
385 ret.clear();
386 res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret);
387 BOOST_CHECK_EQUAL(res, RCode::NoError);
690b86b7 388 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
86675669
OM
389 BOOST_CHECK_EQUAL(ret[0].d_name, target2);
390 BOOST_REQUIRE(ret[0].d_type == QType::A);
391 BOOST_CHECK(getRR<ARecordContent>(ret[0])->getCA() == ComboAddress("192.0.2.2"));
392
690b86b7 393 BOOST_CHECK_EQUAL(SyncRes::t_sstorage.negcache.size(), 1U);
86675669 394
690b86b7 395 BOOST_CHECK_EQUAL(queriesCount, 3U);
86675669
OM
396}
397
42dcf516
OM
398BOOST_AUTO_TEST_CASE(test_root_nx_dont_trust)
399{
86675669
OM
400 std::unique_ptr<SyncRes> sr;
401 initSR(sr);
402
403 primeHints();
404
405 const DNSName target1("powerdns.com.");
406 const DNSName target2("notpowerdns.com.");
407 const ComboAddress ns("192.0.2.1:53");
408 size_t queriesCount = 0;
409
410 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) {
42dcf516 411 queriesCount++;
86675669 412
42dcf516 413 if (isRootServer(ip)) {
86675669 414
42dcf516
OM
415 if (domain == target1) {
416 setLWResult(res, RCode::NXDomain, true, false, true);
417 addRecordToLW(res, ".", QType::SOA, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400);
418 }
419 else {
420 setLWResult(res, 0, true, false, true);
421 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
422 addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
423 }
86675669 424
42dcf516
OM
425 return 1;
426 }
427 else if (ip == ns) {
86675669 428
42dcf516
OM
429 setLWResult(res, 0, true, false, false);
430 addRecordToLW(res, domain, QType::A, "192.0.2.2");
86675669 431
42dcf516
OM
432 return 1;
433 }
86675669 434
42dcf516
OM
435 return 0;
436 });
86675669
OM
437
438 SyncRes::s_rootNXTrust = false;
439
440 vector<DNSRecord> ret;
441 int res = sr->beginResolve(target1, QType(QType::A), QClass::IN, ret);
442 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
690b86b7 443 BOOST_CHECK_EQUAL(ret.size(), 1U);
86675669 444 /* one for target1 */
690b86b7 445 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
86675669
OM
446
447 ret.clear();
448 res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret);
449 BOOST_CHECK_EQUAL(res, RCode::NoError);
690b86b7 450 BOOST_CHECK_EQUAL(ret.size(), 1U);
86675669 451 /* one for target1 */
690b86b7 452 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
86675669
OM
453
454 /* we should have sent three queries */
690b86b7 455 BOOST_CHECK_EQUAL(queriesCount, 3U);
86675669
OM
456}
457
42dcf516
OM
458BOOST_AUTO_TEST_CASE(test_rfc8020_nothing_underneath)
459{
157647ec
PL
460 std::unique_ptr<SyncRes> sr;
461 initSR(sr);
d40a915b 462 SyncRes::s_hardenNXD = SyncRes::HardenNXD::Yes;
157647ec
PL
463
464 primeHints();
465
466 const DNSName target1("www.powerdns.com."); // will be denied
467 const DNSName target2("foo.www.powerdns.com.");
468 const DNSName target3("bar.www.powerdns.com.");
469 const DNSName target4("quux.bar.www.powerdns.com.");
470 const ComboAddress ns("192.0.2.1:53");
471 size_t queriesCount = 0;
472
473 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) {
42dcf516 474 queriesCount++;
157647ec 475
42dcf516
OM
476 if (isRootServer(ip)) {
477 setLWResult(res, 0, false, false, true);
478 addRecordToLW(res, "powerdns.com.", QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
479 addRecordToLW(res, "ns1.powerdns.com.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
480 return 1;
481 }
482 else if (ip == ns) {
483 setLWResult(res, RCode::NXDomain, true, false, false);
484 addRecordToLW(res, "powerdns.com.", QType::SOA, "ns1.powerdns.com. hostmaster.powerdns.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400);
485 return 1;
486 }
487 return 0;
488 });
157647ec
PL
489
490 vector<DNSRecord> ret;
491 int res = sr->beginResolve(target1, QType(QType::A), QClass::IN, ret);
492 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
d40a915b
OM
493 BOOST_CHECK_EQUAL(ret.size(), 1U);
494 BOOST_CHECK_EQUAL(queriesCount, 2U);
495 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
157647ec
PL
496
497 ret.clear();
498 res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret);
499 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
d40a915b
OM
500 BOOST_CHECK_EQUAL(ret.size(), 1U);
501 BOOST_CHECK_EQUAL(queriesCount, 2U);
502 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
157647ec
PL
503
504 ret.clear();
505 res = sr->beginResolve(target3, QType(QType::A), QClass::IN, ret);
506 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
d40a915b
OM
507 BOOST_CHECK_EQUAL(ret.size(), 1U);
508 BOOST_CHECK_EQUAL(queriesCount, 2U);
509 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
157647ec
PL
510
511 ret.clear();
512 res = sr->beginResolve(target4, QType(QType::A), QClass::IN, ret);
513 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
d40a915b
OM
514 BOOST_CHECK_EQUAL(ret.size(), 1U);
515 BOOST_CHECK_EQUAL(queriesCount, 2U);
516 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
157647ec
PL
517
518 // Now test without RFC 8020 to see the cache and query count grow
d40a915b 519 SyncRes::s_hardenNXD = SyncRes::HardenNXD::No;
157647ec
PL
520
521 // Already cached
522 ret.clear();
523 res = sr->beginResolve(target1, QType(QType::A), QClass::IN, ret);
524 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
d40a915b
OM
525 BOOST_CHECK_EQUAL(ret.size(), 1U);
526 BOOST_CHECK_EQUAL(queriesCount, 2U);
527 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
157647ec
PL
528
529 // New query
530 ret.clear();
531 res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret);
532 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
d40a915b
OM
533 BOOST_CHECK_EQUAL(ret.size(), 1U);
534 BOOST_CHECK_EQUAL(queriesCount, 3U);
535 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2U);
157647ec
PL
536
537 ret.clear();
538 res = sr->beginResolve(target3, QType(QType::A), QClass::IN, ret);
539 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
d40a915b
OM
540 BOOST_CHECK_EQUAL(ret.size(), 1U);
541 BOOST_CHECK_EQUAL(queriesCount, 4U);
542 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 3U);
157647ec
PL
543
544 ret.clear();
545 res = sr->beginResolve(target4, QType(QType::A), QClass::IN, ret);
546 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
d40a915b
OM
547 BOOST_CHECK_EQUAL(ret.size(), 1U);
548 BOOST_CHECK_EQUAL(queriesCount, 5U);
549 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 4U);
157647ec
PL
550
551 // reset
d40a915b 552 SyncRes::s_hardenNXD = SyncRes::HardenNXD::DNSSEC;
157647ec 553}
42dcf516
OM
554
555BOOST_AUTO_TEST_CASE(test_rfc8020_nothing_underneath_dnssec)
556{
be4f1994
OM
557 std::unique_ptr<SyncRes> sr;
558 initSR(sr, true);
559 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
560
561 primeHints();
562
563 const DNSName parent1("com.");
564 const DNSName parent2("powerdns.com.");
565 const DNSName target1("www.powerdns.com."); // will be denied
566 const DNSName target2("foo.www.powerdns.com.");
567 const DNSName target3("bar.www.powerdns.com.");
568 const DNSName target4("quux.bar.www.powerdns.com.");
569 const ComboAddress ns("192.0.2.1:53");
570
571 testkeysset_t keys;
572
573 auto luaconfsCopy = g_luaconfs.getCopy();
574 luaconfsCopy.dsAnchors.clear();
575 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
576 generateKeyMaterial(parent1, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
577 generateKeyMaterial(parent2, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
578 g_luaconfs.setState(luaconfsCopy);
579
580 size_t queriesCount = 0;
581
42dcf516 582 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) {
be4f1994
OM
583 queriesCount++;
584
585 DNSName auth = domain;
586 if (domain == target1 || domain == target2 || domain == target3 || domain == target4) {
587 auth = DNSName("powerdns.com.");
588 }
589 if (type == QType::DS || type == QType::DNSKEY) {
590 if (type == QType::DS && (domain == target1 || domain == target2 || domain == target3 || domain == target4)) {
591 setLWResult(res, RCode::NXDomain, true, false, true);
592 addRecordToLW(res, DNSName("powerdns.com."), QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
593 addRRSIG(keys, res->d_records, auth, 300);
42dcf516 594 addNSECRecordToLW(DNSName("wwa.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::RRSIG, QType::NSEC}, 600, res->d_records);
be4f1994
OM
595 addRRSIG(keys, res->d_records, auth, 300);
596 return 1;
597 }
598 else {
599 return genericDSAndDNSKEYHandler(res, domain, auth, type, keys);
600 }
601 }
602 else {
603 if (isRootServer(ip)) {
604 setLWResult(res, 0, false, false, true);
605 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.com.", DNSResourceRecord::AUTHORITY, 3600);
606 addDS(DNSName("com."), 300, res->d_records, keys);
607 addRRSIG(keys, res->d_records, DNSName("."), 300);
608 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
609 return 1;
610 }
611 else if (ip == ComboAddress("192.0.2.1:53")) {
612 if (domain == DNSName("com.")) {
613 setLWResult(res, 0, true, false, true);
614 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.com.");
615 addRRSIG(keys, res->d_records, domain, 300);
616 addRecordToLW(res, "a.gtld-servers.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
617 addRRSIG(keys, res->d_records, domain, 300);
618 }
619 else {
620 setLWResult(res, 0, false, false, true);
621 addRecordToLW(res, auth, QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 3600);
622 addDS(auth, 300, res->d_records, keys);
623 addRRSIG(keys, res->d_records, DNSName("com."), 300);
624 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
625 }
626 return 1;
627 }
628 else if (ip == ComboAddress("192.0.2.2:53")) {
629 if (type == QType::NS) {
630 setLWResult(res, 0, true, false, true);
631 if (domain == DNSName("powerdns.com.")) {
632 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com.");
633 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
634 addRecordToLW(res, "ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
635 addRRSIG(keys, res->d_records, DNSName("powerdns.com"), 300);
636 }
be4f1994
OM
637 }
638 else {
639 setLWResult(res, RCode::NXDomain, true, false, true);
640 addRecordToLW(res, DNSName("powerdns.com."), QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
641 addRRSIG(keys, res->d_records, auth, 300);
42dcf516 642 addNSECRecordToLW(DNSName("wwa.powerdns.com."), DNSName("wwz.powerdns.com."), {QType::RRSIG, QType::NSEC}, 600, res->d_records);
be4f1994
OM
643 addRRSIG(keys, res->d_records, auth, 300);
644 /* add wildcard denial */
42dcf516 645 addNSECRecordToLW(DNSName("powerdns.com."), DNSName("a.powerdns.com."), {QType::RRSIG, QType::NSEC}, 600, res->d_records);
be4f1994
OM
646 addRRSIG(keys, res->d_records, auth, 300);
647 }
648 return 1;
649 }
650 }
651
652 return 0;
653 });
654
655 vector<DNSRecord> ret;
656 int res = sr->beginResolve(target1, QType(QType::A), QClass::IN, ret);
657 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
658 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
659 BOOST_CHECK_EQUAL(ret.size(), 6U);
660 BOOST_CHECK_EQUAL(queriesCount, 9U);
661 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
662
663 ret.clear();
664 res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret);
665 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
666 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
667 BOOST_CHECK_EQUAL(ret.size(), 6U);
668 BOOST_CHECK_EQUAL(queriesCount, 9U);
669 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
670
671 ret.clear();
672 res = sr->beginResolve(target3, QType(QType::A), QClass::IN, ret);
673 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
674 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
675 BOOST_CHECK_EQUAL(ret.size(), 6U);
676 BOOST_CHECK_EQUAL(queriesCount, 9U);
677 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
678
679 ret.clear();
680 res = sr->beginResolve(target4, QType(QType::A), QClass::IN, ret);
681 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
682 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
683 BOOST_CHECK_EQUAL(ret.size(), 6U);
684 BOOST_CHECK_EQUAL(queriesCount, 9U);
685 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
686
687 // Now test without RFC 8020 to see the cache and query count grow
688 SyncRes::s_hardenNXD = SyncRes::HardenNXD::No;
689
690 // Already cached
691 ret.clear();
692 res = sr->beginResolve(target1, QType(QType::A), QClass::IN, ret);
693 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
694 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
695 BOOST_CHECK_EQUAL(ret.size(), 6U);
696 BOOST_CHECK_EQUAL(queriesCount, 9U);
697 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
698
699 // New query
700 ret.clear();
701 res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret);
702 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
703 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
704 BOOST_CHECK_EQUAL(ret.size(), 6U);
705 BOOST_CHECK_EQUAL(queriesCount, 11U);
706 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2U);
707
708 ret.clear();
709 res = sr->beginResolve(target3, QType(QType::A), QClass::IN, ret);
710 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
711 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
712 BOOST_CHECK_EQUAL(ret.size(), 6U);
713 BOOST_CHECK_EQUAL(queriesCount, 13U);
714 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 3U);
715
716 ret.clear();
717 res = sr->beginResolve(target4, QType(QType::A), QClass::IN, ret);
718 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
719 BOOST_CHECK_EQUAL(sr->getValidationState(), Secure);
720 BOOST_CHECK_EQUAL(ret.size(), 6U);
721 BOOST_CHECK_EQUAL(queriesCount, 15U);
722 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 4U);
723
724 // reset
725 SyncRes::s_hardenNXD = SyncRes::HardenNXD::DNSSEC;
726}
157647ec 727
42dcf516
OM
728BOOST_AUTO_TEST_CASE(test_rfc8020_nodata)
729{
157647ec
PL
730 std::unique_ptr<SyncRes> sr;
731 initSR(sr);
d40a915b 732 SyncRes::s_hardenNXD = SyncRes::HardenNXD::Yes;
157647ec
PL
733
734 primeHints();
735
736 const DNSName target1("www.powerdns.com."); // TXT record will be denied
737 const DNSName target2("bar.www.powerdns.com."); // will be NXD, but the www. NODATA should not interfere with 8020 processing
738 const DNSName target3("quux.bar.www.powerdns.com."); // will be NXD, but will not yield a query
739 const ComboAddress ns("192.0.2.1:53");
740 size_t queriesCount = 0;
741
742 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) {
42dcf516 743 queriesCount++;
157647ec 744
42dcf516
OM
745 if (isRootServer(ip)) {
746 setLWResult(res, 0, false, false, true);
747 addRecordToLW(res, "powerdns.com.", QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
748 addRecordToLW(res, "ns1.powerdns.com.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
749 return 1;
750 }
751 else if (ip == ns) {
752 if (domain == target1) { // NODATA for TXT, NOERROR for A
753 if (type == QType::TXT) {
754 setLWResult(res, RCode::NoError, true);
157647ec
PL
755 addRecordToLW(res, "powerdns.com.", QType::SOA, "ns1.powerdns.com. hostmaster.powerdns.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400);
756 return 1;
757 }
42dcf516
OM
758 if (type == QType::A) {
759 setLWResult(res, RCode::NoError, true);
760 addRecordToLW(res, domain, QType::A, "192.0.2.1", DNSResourceRecord::ANSWER, 86400);
761 return 1;
762 }
157647ec 763 }
42dcf516
OM
764 if (domain == target2 || domain == target3) {
765 setLWResult(res, RCode::NXDomain, true);
766 addRecordToLW(res, "powerdns.com.", QType::SOA, "ns1.powerdns.com. hostmaster.powerdns.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400);
767 return 1;
768 }
769 }
770 return 0;
771 });
157647ec
PL
772
773 vector<DNSRecord> ret;
774 int res = sr->beginResolve(target1, QType(QType::TXT), QClass::IN, ret);
775 BOOST_CHECK_EQUAL(res, RCode::NoError);
d40a915b
OM
776 BOOST_CHECK_EQUAL(ret.size(), 1U);
777 BOOST_CHECK_EQUAL(queriesCount, 2U);
778 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
157647ec
PL
779
780 ret.clear();
781 res = sr->beginResolve(target1, QType(QType::A), QClass::IN, ret);
782 BOOST_CHECK_EQUAL(res, RCode::NoError);
d40a915b
OM
783 BOOST_CHECK_EQUAL(ret.size(), 1U);
784 BOOST_CHECK_EQUAL(queriesCount, 3U);
785 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
157647ec
PL
786
787 ret.clear();
788 res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret);
789 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
d40a915b
OM
790 BOOST_CHECK_EQUAL(ret.size(), 1U);
791 BOOST_CHECK_EQUAL(queriesCount, 4U);
792 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2U);
157647ec
PL
793
794 ret.clear();
795 res = sr->beginResolve(target3, QType(QType::A), QClass::IN, ret);
796 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
d40a915b
OM
797 BOOST_CHECK_EQUAL(ret.size(), 1U);
798 BOOST_CHECK_EQUAL(queriesCount, 4U);
799 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2U);
157647ec
PL
800}
801
42dcf516
OM
802BOOST_AUTO_TEST_CASE(test_rfc8020_nodata_bis)
803{
157647ec
PL
804 std::unique_ptr<SyncRes> sr;
805 initSR(sr);
d40a915b 806 SyncRes::s_hardenNXD = SyncRes::HardenNXD::Yes;
157647ec
PL
807
808 primeHints();
809
810 const DNSName target1("www.powerdns.com."); // TXT record will be denied
811 const DNSName target2("bar.www.powerdns.com."); // will be NXD, but the www. NODATA should not interfere with 8020 processing
812 const DNSName target3("quux.bar.www.powerdns.com."); // will be NXD, but will not yield a query
813 const ComboAddress ns("192.0.2.1:53");
814 size_t queriesCount = 0;
815
816 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) {
42dcf516 817 queriesCount++;
157647ec 818
42dcf516
OM
819 if (isRootServer(ip)) {
820 setLWResult(res, 0, false, false, true);
821 addRecordToLW(res, "powerdns.com.", QType::NS, "ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
822 addRecordToLW(res, "ns1.powerdns.com.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
823 return 1;
824 }
825 else if (ip == ns) {
826 if (domain == target1) { // NODATA for TXT, NOERROR for A
827 if (type == QType::TXT) {
828 setLWResult(res, RCode::NoError, true);
157647ec
PL
829 addRecordToLW(res, "powerdns.com.", QType::SOA, "ns1.powerdns.com. hostmaster.powerdns.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400);
830 return 1;
831 }
42dcf516
OM
832 if (type == QType::A) {
833 setLWResult(res, RCode::NoError, true);
834 addRecordToLW(res, domain, QType::A, "192.0.2.1", DNSResourceRecord::ANSWER, 86400);
835 return 1;
836 }
157647ec 837 }
42dcf516
OM
838 if (domain == target2 || domain == target3) {
839 setLWResult(res, RCode::NXDomain, true);
840 addRecordToLW(res, "powerdns.com.", QType::SOA, "ns1.powerdns.com. hostmaster.powerdns.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400);
841 return 1;
842 }
843 }
844 return 0;
845 });
157647ec
PL
846
847 vector<DNSRecord> ret;
848 int res = sr->beginResolve(target1, QType(QType::TXT), QClass::IN, ret);
849 BOOST_CHECK_EQUAL(res, RCode::NoError);
d40a915b
OM
850 BOOST_CHECK_EQUAL(ret.size(), 1U);
851 BOOST_CHECK_EQUAL(queriesCount, 2U);
852 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
157647ec
PL
853
854 ret.clear();
855 res = sr->beginResolve(target1, QType(QType::A), QClass::IN, ret);
856 BOOST_CHECK_EQUAL(res, RCode::NoError);
d40a915b
OM
857 BOOST_CHECK_EQUAL(ret.size(), 1U);
858 BOOST_CHECK_EQUAL(queriesCount, 3U);
859 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 1U);
157647ec
PL
860
861 ret.clear();
862 res = sr->beginResolve(target2, QType(QType::TXT), QClass::IN, ret);
863 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
d40a915b
OM
864 BOOST_CHECK_EQUAL(ret.size(), 1U);
865 BOOST_CHECK_EQUAL(queriesCount, 4U);
866 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2U);
157647ec
PL
867
868 ret.clear();
869 res = sr->beginResolve(target3, QType(QType::TXT), QClass::IN, ret);
870 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
d40a915b
OM
871 BOOST_CHECK_EQUAL(ret.size(), 1U);
872 BOOST_CHECK_EQUAL(queriesCount, 4U);
873 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 2U);
157647ec
PL
874}
875
42dcf516
OM
876BOOST_AUTO_TEST_CASE(test_skip_negcache_for_variable_response)
877{
86675669
OM
878 std::unique_ptr<SyncRes> sr;
879 initSR(sr);
880
881 primeHints();
882
883 const DNSName target("www.powerdns.com.");
884 const DNSName cnameTarget("cname.powerdns.com.");
885
886 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
887
888 EDNSSubnetOpts incomingECS;
889 incomingECS.source = Netmask("192.0.2.128/32");
890 sr->setQuerySource(ComboAddress(), boost::optional<const EDNSSubnetOpts&>(incomingECS));
891
42dcf516
OM
892 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) {
893 BOOST_REQUIRE(srcmask);
894 BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
86675669 895
42dcf516
OM
896 if (isRootServer(ip)) {
897 setLWResult(res, 0, false, false, true);
898 addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
899 addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
86675669 900
42dcf516 901 srcmask = boost::none;
86675669 902
42dcf516
OM
903 return 1;
904 }
905 else if (ip == ComboAddress("192.0.2.1:53")) {
906 if (domain == target) {
907 /* Type 2 NXDOMAIN (rfc2308 section-2.1) */
908 setLWResult(res, RCode::NXDomain, true, false, true);
909 addRecordToLW(res, domain, QType::CNAME, cnameTarget.toString());
910 addRecordToLW(res, "powerdns.com", QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
911 }
912 else if (domain == cnameTarget) {
913 /* we shouldn't get there since the Type NXDOMAIN should have been enough,
86675669 914 but we might if we still chase the CNAME. */
42dcf516
OM
915 setLWResult(res, RCode::NXDomain, true, false, true);
916 addRecordToLW(res, "powerdns.com", QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
86675669
OM
917 }
918
42dcf516
OM
919 return 1;
920 }
921
922 return 0;
923 });
86675669
OM
924
925 vector<DNSRecord> ret;
926 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
927 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
690b86b7 928 BOOST_CHECK_EQUAL(ret.size(), 2U);
86675669 929 /* no negative cache entry because the response was variable */
690b86b7 930 BOOST_CHECK_EQUAL(SyncRes::getNegCacheSize(), 0U);
86675669
OM
931}
932
42dcf516
OM
933BOOST_AUTO_TEST_CASE(test_ecs_cache_limit_allowed)
934{
86675669
OM
935 std::unique_ptr<SyncRes> sr;
936 initSR(sr);
937
938 primeHints();
939
940 const DNSName target("www.powerdns.com.");
941
942 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
943
944 EDNSSubnetOpts incomingECS;
945 incomingECS.source = Netmask("192.0.2.128/32");
946 sr->setQuerySource(ComboAddress(), boost::optional<const EDNSSubnetOpts&>(incomingECS));
947 SyncRes::s_ecsipv4cachelimit = 24;
948
949 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) {
42dcf516
OM
950 BOOST_REQUIRE(srcmask);
951 BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
86675669 952
42dcf516
OM
953 setLWResult(res, 0, true, false, true);
954 addRecordToLW(res, target, QType::A, "192.0.2.1");
86675669 955
42dcf516
OM
956 return 1;
957 });
86675669
OM
958
959 const time_t now = sr->getNow().tv_sec;
960 vector<DNSRecord> ret;
961 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
962 BOOST_CHECK_EQUAL(res, RCode::NoError);
690b86b7 963 BOOST_CHECK_EQUAL(ret.size(), 1U);
86675669
OM
964
965 /* should have been cached */
966 const ComboAddress who("192.0.2.128");
967 vector<DNSRecord> cached;
a7956123 968 BOOST_REQUIRE_GT(s_RC->get(now, target, QType(QType::A), true, &cached, who), 0);
690b86b7 969 BOOST_REQUIRE_EQUAL(cached.size(), 1U);
86675669
OM
970}
971
42dcf516
OM
972BOOST_AUTO_TEST_CASE(test_ecs_cache_limit_no_ttl_limit_allowed)
973{
86675669
OM
974 std::unique_ptr<SyncRes> sr;
975 initSR(sr);
976
977 primeHints();
978
979 const DNSName target("www.powerdns.com.");
980
981 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
982
983 EDNSSubnetOpts incomingECS;
984 incomingECS.source = Netmask("192.0.2.128/32");
985 sr->setQuerySource(ComboAddress(), boost::optional<const EDNSSubnetOpts&>(incomingECS));
986 SyncRes::s_ecsipv4cachelimit = 16;
987
988 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) {
42dcf516
OM
989 BOOST_REQUIRE(srcmask);
990 BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
86675669 991
42dcf516
OM
992 setLWResult(res, 0, true, false, true);
993 addRecordToLW(res, target, QType::A, "192.0.2.1");
86675669 994
42dcf516
OM
995 return 1;
996 });
86675669
OM
997
998 const time_t now = sr->getNow().tv_sec;
999 vector<DNSRecord> ret;
1000 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1001 BOOST_CHECK_EQUAL(res, RCode::NoError);
690b86b7 1002 BOOST_CHECK_EQUAL(ret.size(), 1U);
86675669
OM
1003
1004 /* should have been cached because /24 is more specific than /16 but TTL limit is nof effective */
1005 const ComboAddress who("192.0.2.128");
1006 vector<DNSRecord> cached;
a7956123 1007 BOOST_REQUIRE_GT(s_RC->get(now, target, QType(QType::A), true, &cached, who), 0);
690b86b7 1008 BOOST_REQUIRE_EQUAL(cached.size(), 1U);
86675669
OM
1009}
1010
42dcf516
OM
1011BOOST_AUTO_TEST_CASE(test_ecs_cache_ttllimit_allowed)
1012{
1013 std::unique_ptr<SyncRes> sr;
1014 initSR(sr);
86675669 1015
42dcf516 1016 primeHints();
86675669 1017
42dcf516 1018 const DNSName target("www.powerdns.com.");
86675669 1019
42dcf516 1020 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
86675669 1021
42dcf516
OM
1022 EDNSSubnetOpts incomingECS;
1023 incomingECS.source = Netmask("192.0.2.128/32");
1024 sr->setQuerySource(ComboAddress(), boost::optional<const EDNSSubnetOpts&>(incomingECS));
1025 SyncRes::s_ecscachelimitttl = 30;
86675669 1026
42dcf516
OM
1027 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) {
1028 BOOST_REQUIRE(srcmask);
1029 BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
86675669 1030
42dcf516
OM
1031 setLWResult(res, 0, true, false, true);
1032 addRecordToLW(res, target, QType::A, "192.0.2.1");
86675669 1033
42dcf516
OM
1034 return 1;
1035 });
86675669 1036
42dcf516
OM
1037 const time_t now = sr->getNow().tv_sec;
1038 vector<DNSRecord> ret;
1039 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1040 BOOST_CHECK_EQUAL(res, RCode::NoError);
1041 BOOST_CHECK_EQUAL(ret.size(), 1U);
86675669 1042
42dcf516
OM
1043 /* should have been cached */
1044 const ComboAddress who("192.0.2.128");
1045 vector<DNSRecord> cached;
a7956123 1046 BOOST_REQUIRE_GT(s_RC->get(now, target, QType(QType::A), true, &cached, who), 0);
42dcf516 1047 BOOST_REQUIRE_EQUAL(cached.size(), 1U);
86675669
OM
1048}
1049
42dcf516
OM
1050BOOST_AUTO_TEST_CASE(test_ecs_cache_ttllimit_and_scope_allowed)
1051{
1052 std::unique_ptr<SyncRes> sr;
1053 initSR(sr);
86675669 1054
42dcf516 1055 primeHints();
86675669 1056
42dcf516 1057 const DNSName target("www.powerdns.com.");
86675669 1058
42dcf516 1059 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
86675669 1060
42dcf516
OM
1061 EDNSSubnetOpts incomingECS;
1062 incomingECS.source = Netmask("192.0.2.128/32");
1063 sr->setQuerySource(ComboAddress(), boost::optional<const EDNSSubnetOpts&>(incomingECS));
1064 SyncRes::s_ecscachelimitttl = 100;
1065 SyncRes::s_ecsipv4cachelimit = 24;
86675669 1066
42dcf516
OM
1067 sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
1068 BOOST_REQUIRE(srcmask);
1069 BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
86675669 1070
42dcf516
OM
1071 setLWResult(res, 0, true, false, true);
1072 addRecordToLW(res, target, QType::A, "192.0.2.1");
86675669 1073
42dcf516
OM
1074 return 1;
1075 });
86675669 1076
42dcf516
OM
1077 const time_t now = sr->getNow().tv_sec;
1078 vector<DNSRecord> ret;
1079 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1080 BOOST_CHECK_EQUAL(res, RCode::NoError);
1081 BOOST_CHECK_EQUAL(ret.size(), 1U);
86675669 1082
42dcf516
OM
1083 /* should have been cached */
1084 const ComboAddress who("192.0.2.128");
1085 vector<DNSRecord> cached;
a7956123 1086 BOOST_REQUIRE_GT(s_RC->get(now, target, QType(QType::A), true, &cached, who), 0);
42dcf516 1087 BOOST_REQUIRE_EQUAL(cached.size(), 1U);
86675669
OM
1088}
1089
42dcf516
OM
1090BOOST_AUTO_TEST_CASE(test_ecs_cache_ttllimit_notallowed)
1091{
1092 std::unique_ptr<SyncRes> sr;
1093 initSR(sr);
86675669 1094
42dcf516 1095 primeHints();
86675669 1096
42dcf516 1097 const DNSName target("www.powerdns.com.");
86675669 1098
42dcf516 1099 SyncRes::addEDNSDomain(DNSName("powerdns.com."));
86675669 1100
42dcf516
OM
1101 EDNSSubnetOpts incomingECS;
1102 incomingECS.source = Netmask("192.0.2.128/32");
1103 sr->setQuerySource(ComboAddress(), boost::optional<const EDNSSubnetOpts&>(incomingECS));
1104 SyncRes::s_ecscachelimitttl = 100;
1105 SyncRes::s_ecsipv4cachelimit = 16;
86675669 1106
42dcf516
OM
1107 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) {
1108 BOOST_REQUIRE(srcmask);
1109 BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
86675669 1110
42dcf516
OM
1111 setLWResult(res, 0, true, false, true);
1112 addRecordToLW(res, target, QType::A, "192.0.2.1");
86675669 1113
42dcf516
OM
1114 return 1;
1115 });
86675669 1116
42dcf516
OM
1117 const time_t now = sr->getNow().tv_sec;
1118 vector<DNSRecord> ret;
1119 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1120 BOOST_CHECK_EQUAL(res, RCode::NoError);
1121 BOOST_CHECK_EQUAL(ret.size(), 1U);
86675669 1122
42dcf516
OM
1123 /* should have NOT been cached because TTL of 60 is too small and /24 is more specific than /16 */
1124 const ComboAddress who("192.0.2.128");
1125 vector<DNSRecord> cached;
a7956123 1126 BOOST_REQUIRE_LT(s_RC->get(now, target, QType(QType::A), true, &cached, who), 0);
42dcf516 1127 BOOST_REQUIRE_EQUAL(cached.size(), 0U);
86675669
OM
1128}
1129
42dcf516
OM
1130BOOST_AUTO_TEST_CASE(test_ns_speed)
1131{
86675669
OM
1132 std::unique_ptr<SyncRes> sr;
1133 initSR(sr);
1134
1135 primeHints();
1136
1137 const DNSName target("powerdns.com.");
1138
1139 std::map<ComboAddress, uint64_t> nsCounts;
1140
42dcf516
OM
1141 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) {
1142 if (isRootServer(ip)) {
1143 setLWResult(res, 0, false, false, true);
1144 addRecordToLW(res, domain, QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
1145 addRecordToLW(res, domain, QType::NS, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
1146 addRecordToLW(res, domain, QType::NS, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
86675669 1147
42dcf516
OM
1148 addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
1149 addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::AAAA, "2001:DB8::1", DNSResourceRecord::ADDITIONAL, 3600);
1150 addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600);
1151 addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::AAAA, "2001:DB8::2", DNSResourceRecord::ADDITIONAL, 3600);
1152 addRecordToLW(res, "pdns-public-ns3.powerdns.com.", QType::A, "192.0.2.3", DNSResourceRecord::ADDITIONAL, 3600);
1153 addRecordToLW(res, "pdns-public-ns3.powerdns.com.", QType::AAAA, "2001:DB8::3", DNSResourceRecord::ADDITIONAL, 3600);
86675669 1154
42dcf516
OM
1155 return 1;
1156 }
1157 else {
1158 nsCounts[ip]++;
86675669 1159
42dcf516
OM
1160 if (ip == ComboAddress("[2001:DB8::2]:53") || ip == ComboAddress("192.0.2.2:53")) {
1161 BOOST_CHECK_LT(nsCounts.size(), 3U);
86675669 1162
42dcf516 1163 /* let's time out on pdns-public-ns2.powerdns.com. */
86675669
OM
1164 return 0;
1165 }
42dcf516
OM
1166 else if (ip == ComboAddress("192.0.2.1:53")) {
1167 BOOST_CHECK_EQUAL(nsCounts.size(), 3U);
1168
1169 setLWResult(res, 0, true, false, true);
1170 addRecordToLW(res, domain, QType::A, "192.0.2.254");
1171 return 1;
1172 }
86675669
OM
1173
1174 return 0;
42dcf516
OM
1175 }
1176
1177 return 0;
1178 });
86675669
OM
1179
1180 struct timeval now = sr->getNow();
1181
1182 /* make pdns-public-ns2.powerdns.com. the fastest NS, with its IPv6 address faster than the IPV4 one,
1183 then pdns-public-ns1.powerdns.com. on IPv4 */
b9715061
OM
1184 SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("192.0.2.1:53"), 100, now);
1185 SyncRes::submitNSSpeed(DNSName("pdns-public-ns1.powerdns.com."), ComboAddress("[2001:DB8::1]:53"), 10000, now);
1186 SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("192.0.2.2:53"), 10, now);
1187 SyncRes::submitNSSpeed(DNSName("pdns-public-ns2.powerdns.com."), ComboAddress("[2001:DB8::2]:53"), 1, now);
1188 SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("192.0.2.3:53"), 10000, now);
1189 SyncRes::submitNSSpeed(DNSName("pdns-public-ns3.powerdns.com."), ComboAddress("[2001:DB8::3]:53"), 10000, now);
86675669
OM
1190
1191 vector<DNSRecord> ret;
1192 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1193 BOOST_CHECK_EQUAL(res, RCode::NoError);
690b86b7
OM
1194 BOOST_CHECK_EQUAL(ret.size(), 1U);
1195 BOOST_CHECK_EQUAL(nsCounts.size(), 3U);
1196 BOOST_CHECK_EQUAL(nsCounts[ComboAddress("192.0.2.1:53")], 1U);
1197 BOOST_CHECK_EQUAL(nsCounts[ComboAddress("192.0.2.2:53")], 1U);
1198 BOOST_CHECK_EQUAL(nsCounts[ComboAddress("[2001:DB8::2]:53")], 1U);
86675669
OM
1199}
1200
42dcf516
OM
1201BOOST_AUTO_TEST_CASE(test_flawed_nsset)
1202{
86675669
OM
1203 std::unique_ptr<SyncRes> sr;
1204 initSR(sr);
1205
1206 primeHints();
1207
1208 const DNSName target("powerdns.com.");
1209
1210 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) {
42dcf516
OM
1211 if (isRootServer(ip)) {
1212 setLWResult(res, 0, false, false, true);
1213 addRecordToLW(res, domain, QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
86675669 1214
42dcf516 1215 addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
86675669 1216
42dcf516
OM
1217 return 1;
1218 }
1219 else if (ip == ComboAddress("192.0.2.1:53")) {
1220 setLWResult(res, 0, true, false, true);
1221 addRecordToLW(res, domain, QType::A, "192.0.2.254");
1222 return 1;
1223 }
86675669 1224
42dcf516
OM
1225 return 0;
1226 });
86675669
OM
1227
1228 /* we populate the cache with a flawed NSset, i.e. there is a NS entry but no corresponding glue */
1229 time_t now = sr->getNow().tv_sec;
1230 std::vector<DNSRecord> records;
42dcf516 1231 std::vector<shared_ptr<RRSIGRecordContent>> sigs;
86675669
OM
1232 addRecordToList(records, target, QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, now + 3600);
1233
a7956123 1234 s_RC->replace(now, target, QType(QType::NS), records, sigs, vector<std::shared_ptr<DNSRecord>>(), true, boost::optional<Netmask>());
86675669
OM
1235
1236 vector<DNSRecord> ret;
1237 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1238 BOOST_CHECK_EQUAL(res, RCode::NoError);
690b86b7 1239 BOOST_CHECK_EQUAL(ret.size(), 1U);
86675669
OM
1240}
1241
42dcf516
OM
1242BOOST_AUTO_TEST_CASE(test_completely_flawed_nsset)
1243{
86675669
OM
1244 std::unique_ptr<SyncRes> sr;
1245 initSR(sr);
1246
1247 primeHints();
1248
1249 const DNSName target("powerdns.com.");
1250 size_t queriesCount = 0;
1251
42dcf516
OM
1252 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) {
1253 queriesCount++;
86675669 1254
42dcf516
OM
1255 if (isRootServer(ip) && domain == target) {
1256 setLWResult(res, 0, false, false, true);
1257 addRecordToLW(res, domain, QType::NS, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
1258 addRecordToLW(res, domain, QType::NS, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
1259 return 1;
1260 }
1261 else if (domain == DNSName("pdns-public-ns2.powerdns.com.") || domain == DNSName("pdns-public-ns3.powerdns.com.")) {
1262 setLWResult(res, 0, true, false, true);
1263 addRecordToLW(res, ".", QType::SOA, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400);
1264 return 1;
1265 }
86675669 1266
42dcf516
OM
1267 return 0;
1268 });
86675669
OM
1269
1270 vector<DNSRecord> ret;
1271 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1272 BOOST_CHECK_EQUAL(res, RCode::ServFail);
690b86b7 1273 BOOST_CHECK_EQUAL(ret.size(), 0U);
86675669 1274 /* one query to get NSs, then A and AAAA for each NS */
690b86b7 1275 BOOST_CHECK_EQUAL(queriesCount, 5U);
86675669
OM
1276}
1277
42dcf516
OM
1278BOOST_AUTO_TEST_CASE(test_cache_hit)
1279{
86675669
OM
1280 std::unique_ptr<SyncRes> sr;
1281 initSR(sr);
1282
1283 primeHints();
1284
1285 const DNSName target("powerdns.com.");
1286
1287 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) {
42dcf516
OM
1288 return 0;
1289 });
86675669 1290
ef2ea4bf 1291 /* we populate the cache with everything we need */
86675669
OM
1292 time_t now = sr->getNow().tv_sec;
1293 std::vector<DNSRecord> records;
42dcf516 1294 std::vector<shared_ptr<RRSIGRecordContent>> sigs;
86675669
OM
1295
1296 addRecordToList(records, target, QType::A, "192.0.2.1", DNSResourceRecord::ANSWER, now + 3600);
a7956123 1297 s_RC->replace(now, target, QType(QType::A), records, sigs, vector<std::shared_ptr<DNSRecord>>(), true, boost::optional<Netmask>());
86675669
OM
1298
1299 vector<DNSRecord> ret;
1300 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1301 BOOST_CHECK_EQUAL(res, RCode::NoError);
690b86b7 1302 BOOST_CHECK_EQUAL(ret.size(), 1U);
86675669
OM
1303}
1304
42dcf516
OM
1305BOOST_AUTO_TEST_CASE(test_no_rd)
1306{
86675669
OM
1307 std::unique_ptr<SyncRes> sr;
1308 initSR(sr);
1309
1310 primeHints();
1311
1312 const DNSName target("powerdns.com.");
1313 size_t queriesCount = 0;
1314
1315 sr->setCacheOnly();
1316
42dcf516
OM
1317 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) {
1318 queriesCount++;
1319 return 0;
1320 });
86675669
OM
1321
1322 vector<DNSRecord> ret;
1323 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1324 BOOST_CHECK_EQUAL(res, RCode::NoError);
690b86b7
OM
1325 BOOST_CHECK_EQUAL(ret.size(), 0U);
1326 BOOST_CHECK_EQUAL(queriesCount, 0U);
86675669
OM
1327}
1328
42dcf516
OM
1329BOOST_AUTO_TEST_CASE(test_cache_min_max_ttl)
1330{
86675669
OM
1331 std::unique_ptr<SyncRes> sr;
1332 initSR(sr);
1333
1334 primeHints();
1335
1336 const DNSName target("cachettl.powerdns.com.");
1337 const ComboAddress ns("192.0.2.1:53");
1338
42dcf516
OM
1339 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) {
1340 if (isRootServer(ip)) {
86675669 1341
42dcf516
OM
1342 setLWResult(res, 0, false, false, true);
1343 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
1344 addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 7200);
1345 return 1;
1346 }
1347 else if (ip == ns) {
86675669 1348
42dcf516
OM
1349 setLWResult(res, 0, true, false, false);
1350 addRecordToLW(res, domain, QType::A, "192.0.2.2", DNSResourceRecord::ANSWER, 10);
86675669 1351
42dcf516
OM
1352 return 1;
1353 }
86675669 1354
42dcf516
OM
1355 return 0;
1356 });
86675669
OM
1357
1358 const time_t now = sr->getNow().tv_sec;
1359 SyncRes::s_minimumTTL = 60;
1360 SyncRes::s_maxcachettl = 3600;
1361
1362 vector<DNSRecord> ret;
1363 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1364 BOOST_CHECK_EQUAL(res, RCode::NoError);
690b86b7 1365 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
86675669
OM
1366 BOOST_CHECK_EQUAL(ret[0].d_ttl, SyncRes::s_minimumTTL);
1367
1368 const ComboAddress who;
1369 vector<DNSRecord> cached;
a7956123 1370 BOOST_REQUIRE_GT(s_RC->get(now, target, QType(QType::A), true, &cached, who), 0);
690b86b7 1371 BOOST_REQUIRE_EQUAL(cached.size(), 1U);
86675669
OM
1372 BOOST_REQUIRE_GT(cached[0].d_ttl, now);
1373 BOOST_CHECK_EQUAL((cached[0].d_ttl - now), SyncRes::s_minimumTTL);
1374
1375 cached.clear();
a7956123 1376 BOOST_REQUIRE_GT(s_RC->get(now, target, QType(QType::NS), false, &cached, who), 0);
690b86b7 1377 BOOST_REQUIRE_EQUAL(cached.size(), 1U);
86675669
OM
1378 BOOST_REQUIRE_GT(cached[0].d_ttl, now);
1379 BOOST_CHECK_LE((cached[0].d_ttl - now), SyncRes::s_maxcachettl);
1380}
1381
42dcf516
OM
1382BOOST_AUTO_TEST_CASE(test_cache_min_max_ecs_ttl)
1383{
86675669
OM
1384 std::unique_ptr<SyncRes> sr;
1385 initSR(sr);
1386
1387 primeHints();
1388
1389 const DNSName target("cacheecsttl.powerdns.com.");
1390 const ComboAddress ns("192.0.2.1:53");
1391
1392 EDNSSubnetOpts incomingECS;
1393 incomingECS.source = Netmask("192.0.2.128/32");
1394 sr->setQuerySource(ComboAddress(), boost::optional<const EDNSSubnetOpts&>(incomingECS));
1395 SyncRes::addEDNSDomain(target);
1396
42dcf516
OM
1397 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) {
1398 BOOST_REQUIRE(srcmask);
1399 BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
86675669 1400
42dcf516 1401 if (isRootServer(ip)) {
86675669 1402
42dcf516
OM
1403 setLWResult(res, 0, false, false, true);
1404 addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
1405 addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 20);
1406 srcmask = boost::none;
86675669 1407
42dcf516
OM
1408 return 1;
1409 }
1410 else if (ip == ns) {
86675669 1411
42dcf516
OM
1412 setLWResult(res, 0, true, false, false);
1413 addRecordToLW(res, domain, QType::A, "192.0.2.2", DNSResourceRecord::ANSWER, 10);
86675669 1414
42dcf516
OM
1415 return 1;
1416 }
86675669 1417
42dcf516
OM
1418 return 0;
1419 });
86675669
OM
1420
1421 const time_t now = sr->getNow().tv_sec;
1422 SyncRes::s_minimumTTL = 60;
1423 SyncRes::s_minimumECSTTL = 120;
1424 SyncRes::s_maxcachettl = 3600;
1425
1426 vector<DNSRecord> ret;
1427 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1428 BOOST_CHECK_EQUAL(res, RCode::NoError);
690b86b7 1429 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
86675669
OM
1430 BOOST_CHECK_EQUAL(ret[0].d_ttl, SyncRes::s_minimumECSTTL);
1431
1432 const ComboAddress who("192.0.2.128");
1433 vector<DNSRecord> cached;
a7956123 1434 BOOST_REQUIRE_GT(s_RC->get(now, target, QType(QType::A), true, &cached, who), 0);
690b86b7 1435 BOOST_REQUIRE_EQUAL(cached.size(), 1U);
86675669
OM
1436 BOOST_REQUIRE_GT(cached[0].d_ttl, now);
1437 BOOST_CHECK_EQUAL((cached[0].d_ttl - now), SyncRes::s_minimumECSTTL);
1438
1439 cached.clear();
a7956123 1440 BOOST_REQUIRE_GT(s_RC->get(now, target, QType(QType::NS), false, &cached, who), 0);
690b86b7 1441 BOOST_REQUIRE_EQUAL(cached.size(), 1U);
86675669
OM
1442 BOOST_REQUIRE_GT(cached[0].d_ttl, now);
1443 BOOST_CHECK_LE((cached[0].d_ttl - now), SyncRes::s_maxcachettl);
1444
1445 cached.clear();
a7956123 1446 BOOST_REQUIRE_GT(s_RC->get(now, DNSName("a.gtld-servers.net."), QType(QType::A), false, &cached, who), 0);
690b86b7 1447 BOOST_REQUIRE_EQUAL(cached.size(), 1U);
86675669
OM
1448 BOOST_REQUIRE_GT(cached[0].d_ttl, now);
1449 BOOST_CHECK_LE((cached[0].d_ttl - now), SyncRes::s_minimumTTL);
1450}
1451
42dcf516
OM
1452BOOST_AUTO_TEST_CASE(test_cache_expired_ttl)
1453{
86675669
OM
1454 std::unique_ptr<SyncRes> sr;
1455 initSR(sr);
1456
1457 primeHints();
1458
1459 const DNSName target("powerdns.com.");
1460
1461 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) {
42dcf516
OM
1462 if (isRootServer(ip)) {
1463 setLWResult(res, 0, false, false, true);
1464 addRecordToLW(res, domain, QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
86675669 1465
42dcf516 1466 addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
86675669 1467
42dcf516
OM
1468 return 1;
1469 }
1470 else if (ip == ComboAddress("192.0.2.1:53")) {
1471 setLWResult(res, 0, true, false, true);
1472 addRecordToLW(res, domain, QType::A, "192.0.2.2");
1473 return 1;
1474 }
86675669 1475
42dcf516
OM
1476 return 0;
1477 });
86675669
OM
1478
1479 /* we populate the cache with entries that expired 60s ago*/
1480 const time_t now = sr->getNow().tv_sec;
1481
1482 std::vector<DNSRecord> records;
42dcf516 1483 std::vector<shared_ptr<RRSIGRecordContent>> sigs;
86675669
OM
1484 addRecordToList(records, target, QType::A, "192.0.2.42", DNSResourceRecord::ANSWER, now - 60);
1485
a7956123 1486 s_RC->replace(now - 3600, target, QType(QType::A), records, sigs, vector<std::shared_ptr<DNSRecord>>(), true, boost::optional<Netmask>());
86675669
OM
1487
1488 vector<DNSRecord> ret;
1489 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1490 BOOST_CHECK_EQUAL(res, RCode::NoError);
690b86b7 1491 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
86675669
OM
1492 BOOST_REQUIRE(ret[0].d_type == QType::A);
1493 BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toStringWithPort(), ComboAddress("192.0.2.2").toStringWithPort());
1494}
1495
1496BOOST_AUTO_TEST_SUITE_END()