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