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