]>
Commit | Line | Data |
---|---|---|
30ee601a RG |
1 | #define BOOST_TEST_DYN_LINK |
2 | #define BOOST_TEST_NO_MAIN | |
3 | #include <boost/test/unit_test.hpp> | |
4 | ||
5 | #include "arguments.hh" | |
6 | #include "lua-recursor4.hh" | |
7 | #include "namespaces.hh" | |
8 | #include "rec-lua-conf.hh" | |
9 | #include "root-dnssec.hh" | |
10 | #include "syncres.hh" | |
11 | #include "validate-recursor.hh" | |
12 | ||
13 | std::unordered_set<DNSName> g_delegationOnly; | |
14 | RecursorStats g_stats; | |
15 | GlobalStateHolder<LuaConfigItems> g_luaconfs; | |
16 | NetmaskGroup* g_dontQuery{nullptr}; | |
17 | __thread MemRecursorCache* t_RC{nullptr}; | |
18 | SyncRes::domainmap_t* g_initialDomainMap{nullptr}; | |
19 | unsigned int g_numThreads = 1; | |
20 | ||
21 | /* Fake some required functions we didn't want the trouble to | |
22 | link with */ | |
23 | ArgvMap &arg() | |
24 | { | |
25 | static ArgvMap theArg; | |
26 | return theArg; | |
27 | } | |
28 | ||
29 | int getMTaskerTID() | |
30 | { | |
31 | return 0; | |
32 | } | |
33 | ||
34 | bool RecursorLua4::preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, int& ret) | |
35 | { | |
36 | return false; | |
37 | } | |
38 | ||
39 | int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) | |
40 | { | |
41 | return 0; | |
42 | } | |
43 | ||
44 | /* primeHints() is only here for now because it | |
45 | was way too much trouble to link with the real one. | |
46 | We should fix this, empty functions are one thing, but this is | |
47 | bad. | |
48 | */ | |
49 | ||
50 | #include "root-addresses.hh" | |
51 | ||
52 | void primeHints(void) | |
53 | { | |
54 | vector<DNSRecord> nsset; | |
55 | if(!t_RC) | |
56 | t_RC = new MemRecursorCache(); | |
57 | ||
58 | DNSRecord arr, aaaarr, nsrr; | |
59 | nsrr.d_name=g_rootdnsname; | |
60 | arr.d_type=QType::A; | |
61 | aaaarr.d_type=QType::AAAA; | |
62 | nsrr.d_type=QType::NS; | |
63 | arr.d_ttl=aaaarr.d_ttl=nsrr.d_ttl=time(nullptr)+3600000; | |
64 | ||
65 | for(char c='a';c<='m';++c) { | |
66 | static char templ[40]; | |
67 | strncpy(templ,"a.root-servers.net.", sizeof(templ) - 1); | |
68 | templ[sizeof(templ)-1] = '\0'; | |
69 | *templ=c; | |
70 | aaaarr.d_name=arr.d_name=DNSName(templ); | |
71 | nsrr.d_content=std::make_shared<NSRecordContent>(DNSName(templ)); | |
72 | arr.d_content=std::make_shared<ARecordContent>(ComboAddress(rootIps4[c-'a'])); | |
73 | vector<DNSRecord> aset; | |
74 | aset.push_back(arr); | |
75 | t_RC->replace(time(0), DNSName(templ), QType(QType::A), aset, vector<std::shared_ptr<RRSIGRecordContent>>(), true); // auth, nuke it all | |
76 | if (rootIps6[c-'a'] != NULL) { | |
77 | aaaarr.d_content=std::make_shared<AAAARecordContent>(ComboAddress(rootIps6[c-'a'])); | |
78 | ||
79 | vector<DNSRecord> aaaaset; | |
80 | aaaaset.push_back(aaaarr); | |
81 | t_RC->replace(time(0), DNSName(templ), QType(QType::AAAA), aaaaset, vector<std::shared_ptr<RRSIGRecordContent>>(), true); | |
82 | } | |
83 | ||
84 | nsset.push_back(nsrr); | |
85 | } | |
86 | t_RC->replace(time(0), g_rootdnsname, QType(QType::NS), nsset, vector<std::shared_ptr<RRSIGRecordContent>>(), false); // and stuff in the cache | |
87 | } | |
88 | ||
89 | LuaConfigItems::LuaConfigItems() | |
90 | { | |
91 | for (const auto &dsRecord : rootDSs) { | |
92 | auto ds=unique_ptr<DSRecordContent>(dynamic_cast<DSRecordContent*>(DSRecordContent::make(dsRecord))); | |
93 | dsAnchors[g_rootdnsname].insert(*ds); | |
94 | } | |
95 | } | |
96 | ||
97 | /* Some helpers functions */ | |
98 | ||
99 | static void init(bool debug=false) | |
100 | { | |
101 | if (debug) { | |
102 | L.setName("test"); | |
103 | L.setLoglevel((Logger::Urgency)(6)); // info and up | |
104 | L.disableSyslog(true); | |
105 | L.toConsole(Logger::Info); | |
106 | } | |
107 | ||
108 | seedRandom("/dev/urandom"); | |
d6e797b8 | 109 | reportAllTypes(); |
30ee601a RG |
110 | |
111 | if (g_dontQuery) | |
112 | delete g_dontQuery; | |
113 | g_dontQuery = new NetmaskGroup(); | |
114 | ||
115 | if (t_RC) | |
116 | delete t_RC; | |
117 | t_RC = new MemRecursorCache(); | |
118 | ||
119 | if (g_initialDomainMap) | |
120 | delete g_initialDomainMap; | |
121 | g_initialDomainMap = new SyncRes::domainmap_t(); // new threads needs this to be setup | |
122 | ||
123 | SyncRes::s_maxqperq = 50; | |
124 | SyncRes::s_maxtotusec = 1000*7000; | |
125 | SyncRes::s_maxdepth = 40; | |
126 | SyncRes::s_maxnegttl = 3600; | |
127 | SyncRes::s_maxcachettl = 86400; | |
128 | SyncRes::s_packetcachettl = 3600; | |
129 | SyncRes::s_packetcacheservfailttl = 60; | |
130 | SyncRes::s_serverdownmaxfails = 64; | |
131 | SyncRes::s_serverdownthrottletime = 60; | |
132 | SyncRes::s_doIPv6 = true; | |
e9f9b8ec RG |
133 | SyncRes::s_ecsipv4limit = 24; |
134 | SyncRes::s_ecsipv6limit = 56; | |
f58c8379 | 135 | SyncRes::s_rootNXTrust = true; |
d6e797b8 | 136 | SyncRes::s_minimumTTL = 0; |
648bcbd1 | 137 | SyncRes::s_serverID = "PowerDNS Unit Tests Server ID"; |
30ee601a | 138 | |
e9f9b8ec RG |
139 | g_ednssubnets = NetmaskGroup(); |
140 | g_ednsdomains = SuffixMatchNode(); | |
141 | g_useIncomingECS = false; | |
d6e797b8 | 142 | g_delegationOnly.clear(); |
648bcbd1 RG |
143 | |
144 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
145 | luaconfsCopy.dfe.clear(); | |
146 | g_luaconfs.setState(luaconfsCopy); | |
147 | ||
148 | ::arg().set("version-string", "string reported on version.pdns or version.bind")="PowerDNS Unit Tests"; | |
30ee601a RG |
149 | } |
150 | ||
d6e797b8 | 151 | static void initSR(std::unique_ptr<SyncRes>& sr, bool edns0, bool dnssec, SyncRes::LogMode lm=SyncRes::LogNone, time_t fakeNow=0) |
30ee601a RG |
152 | { |
153 | struct timeval now; | |
d6e797b8 RG |
154 | if (fakeNow > 0) { |
155 | now.tv_sec = fakeNow; | |
156 | now.tv_usec = 0; | |
157 | } | |
158 | else { | |
159 | Utility::gettimeofday(&now, 0); | |
160 | } | |
161 | ||
30ee601a RG |
162 | sr = std::unique_ptr<SyncRes>(new SyncRes(now)); |
163 | sr->setDoEDNS0(edns0); | |
164 | sr->setDoDNSSEC(dnssec); | |
4fff116b | 165 | sr->setLogMode(lm); |
30ee601a RG |
166 | t_sstorage->domainmap = g_initialDomainMap; |
167 | t_sstorage->negcache.clear(); | |
168 | t_sstorage->nsSpeeds.clear(); | |
169 | t_sstorage->ednsstatus.clear(); | |
170 | t_sstorage->throttle.clear(); | |
171 | t_sstorage->fails.clear(); | |
172 | t_sstorage->dnssecmap.clear(); | |
173 | } | |
174 | ||
175 | static void setLWResult(LWResult* res, int rcode, bool aa=false, bool tc=false, bool edns=false) | |
176 | { | |
177 | res->d_rcode = rcode; | |
178 | res->d_aabit = aa; | |
179 | res->d_tcbit = tc; | |
180 | res->d_haveEDNS = edns; | |
181 | } | |
182 | ||
d6e797b8 | 183 | static void addRecordToList(std::vector<DNSRecord>& records, const DNSName& name, uint16_t type, const std::string& content, DNSResourceRecord::Place place, uint32_t ttl) |
30ee601a RG |
184 | { |
185 | DNSRecord rec; | |
186 | rec.d_place = place; | |
187 | rec.d_name = name; | |
188 | rec.d_type = type; | |
189 | rec.d_ttl = ttl; | |
190 | ||
191 | if (type == QType::NS) { | |
192 | rec.d_content = std::make_shared<NSRecordContent>(DNSName(content)); | |
193 | } | |
194 | else if (type == QType::A) { | |
195 | rec.d_content = std::make_shared<ARecordContent>(ComboAddress(content)); | |
196 | } | |
778bcea6 | 197 | else if (type == QType::AAAA) { |
30ee601a RG |
198 | rec.d_content = std::make_shared<AAAARecordContent>(ComboAddress(content)); |
199 | } | |
778bcea6 RG |
200 | else if (type == QType::CNAME) { |
201 | rec.d_content = std::make_shared<CNAMERecordContent>(DNSName(content)); | |
202 | } | |
d6e797b8 RG |
203 | else if (type == QType::OPT) { |
204 | rec.d_content = std::make_shared<OPTRecordContent>(); | |
205 | } | |
30ee601a RG |
206 | else { |
207 | rec.d_content = shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(type, QClass::IN, content)); | |
208 | } | |
209 | ||
d6e797b8 RG |
210 | records.push_back(rec); |
211 | } | |
212 | ||
213 | static void addRecordToList(std::vector<DNSRecord>& records, const std::string& name, uint16_t type, const std::string& content, DNSResourceRecord::Place place, uint32_t ttl) | |
214 | { | |
215 | addRecordToList(records, name, type, content, place, ttl); | |
216 | } | |
217 | ||
218 | static void addRecordToLW(LWResult* res, const DNSName& name, uint16_t type, const std::string& content, DNSResourceRecord::Place place=DNSResourceRecord::ANSWER, uint32_t ttl=60) | |
219 | { | |
220 | addRecordToList(res->d_records, name, type, content, place, ttl); | |
30ee601a RG |
221 | } |
222 | ||
223 | static void addRecordToLW(LWResult* res, const std::string& name, uint16_t type, const std::string& content, DNSResourceRecord::Place place=DNSResourceRecord::ANSWER, uint32_t ttl=60) | |
224 | { | |
225 | addRecordToLW(res, DNSName(name), type, content, place, ttl); | |
226 | } | |
227 | ||
228 | static bool isRootServer(const ComboAddress& ip) | |
229 | { | |
230 | for (size_t idx = 0; idx < rootIps4Count; idx++) { | |
231 | if (ip.toString() == rootIps4[idx]) { | |
232 | return true; | |
233 | } | |
234 | } | |
235 | ||
236 | for (size_t idx = 0; idx < rootIps6Count; idx++) { | |
237 | if (ip.toString() == rootIps6[idx]) { | |
238 | return true; | |
239 | } | |
240 | } | |
241 | return false; | |
242 | } | |
243 | ||
244 | /* Real tests */ | |
245 | ||
246 | BOOST_AUTO_TEST_SUITE(syncres_cc) | |
247 | ||
248 | BOOST_AUTO_TEST_CASE(test_root_primed) { | |
249 | std::unique_ptr<SyncRes> sr; | |
250 | init(); | |
251 | initSR(sr, true, false); | |
252 | ||
253 | primeHints(); | |
254 | ||
255 | /* we are primed, we should be able to resolve NS . without any query */ | |
256 | vector<DNSRecord> ret; | |
257 | int res = sr->beginResolve(DNSName("."), QType(QType::NS), QClass::IN, ret); | |
258 | BOOST_CHECK_EQUAL(res, 0); | |
259 | BOOST_CHECK_EQUAL(ret.size(), 13); | |
260 | } | |
261 | ||
262 | BOOST_AUTO_TEST_CASE(test_root_not_primed) { | |
263 | std::unique_ptr<SyncRes> sr; | |
264 | init(false); | |
265 | initSR(sr, true, false); | |
266 | ||
267 | size_t queriesCount = 0; | |
268 | ||
269 | sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
270 | queriesCount++; | |
271 | ||
272 | if (domain == g_rootdnsname && type == QType::NS) { | |
273 | setLWResult(res, 0, true, false, true); | |
274 | addRecordToLW(res, g_rootdnsname, QType::NS, "a.root-servers.net.", DNSResourceRecord::ANSWER, 3600); | |
275 | addRecordToLW(res, "a.root-servers.net.", QType::A, "198.41.0.4", DNSResourceRecord::ADDITIONAL, 3600); | |
276 | addRecordToLW(res, "a.root-servers.net.", QType::AAAA, "2001:503:ba3e::2:30", DNSResourceRecord::ADDITIONAL, 3600); | |
277 | ||
278 | return 1; | |
279 | } | |
280 | ||
281 | return 0; | |
282 | }); | |
283 | ||
284 | /* we are not primed yet, so SyncRes will have to call primeHints() | |
285 | then call getRootNS(), for which at least one of the root servers needs to answer */ | |
286 | vector<DNSRecord> ret; | |
287 | int res = sr->beginResolve(DNSName("."), QType(QType::NS), QClass::IN, ret); | |
288 | BOOST_CHECK_EQUAL(res, 0); | |
289 | BOOST_CHECK_EQUAL(ret.size(), 1); | |
290 | BOOST_CHECK_EQUAL(queriesCount, 2); | |
291 | } | |
292 | ||
293 | BOOST_AUTO_TEST_CASE(test_root_not_primed_and_no_response) { | |
294 | std::unique_ptr<SyncRes> sr; | |
295 | init(); | |
296 | initSR(sr, true, false); | |
297 | std::set<ComboAddress> downServers; | |
298 | ||
299 | /* we are not primed yet, so SyncRes will have to call primeHints() | |
300 | then call getRootNS(), for which at least one of the root servers needs to answer. | |
301 | None will, so it should ServFail. | |
302 | */ | |
303 | sr->setAsyncCallback([&downServers](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
304 | ||
305 | downServers.insert(ip); | |
306 | return 0; | |
307 | }); | |
308 | ||
309 | vector<DNSRecord> ret; | |
310 | int res = sr->beginResolve(DNSName("."), QType(QType::NS), QClass::IN, ret); | |
f58c8379 | 311 | BOOST_CHECK_EQUAL(res, RCode::ServFail); |
30ee601a RG |
312 | BOOST_CHECK_EQUAL(ret.size(), 0); |
313 | BOOST_CHECK(downServers.size() > 0); | |
314 | /* we explicitly refuse to mark the root servers down */ | |
315 | for (const auto& server : downServers) { | |
316 | BOOST_CHECK_EQUAL(t_sstorage->fails.value(server), 0); | |
317 | } | |
318 | } | |
319 | ||
320 | BOOST_AUTO_TEST_CASE(test_edns_formerr_fallback) { | |
321 | std::unique_ptr<SyncRes> sr; | |
322 | init(); | |
323 | initSR(sr, true, false); | |
324 | ||
325 | ComboAddress noEDNSServer; | |
326 | size_t queriesWithEDNS = 0; | |
327 | size_t queriesWithoutEDNS = 0; | |
328 | ||
329 | sr->setAsyncCallback([&queriesWithEDNS, &queriesWithoutEDNS, &noEDNSServer](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
330 | if (EDNS0Level != 0) { | |
331 | queriesWithEDNS++; | |
332 | noEDNSServer = ip; | |
333 | ||
334 | setLWResult(res, RCode::FormErr); | |
335 | return 1; | |
336 | } | |
337 | ||
338 | queriesWithoutEDNS++; | |
339 | ||
340 | if (domain == DNSName("powerdns.com") && type == QType::A && !doTCP) { | |
341 | setLWResult(res, 0, true, false, false); | |
342 | addRecordToLW(res, domain, QType::A, "192.0.2.1"); | |
343 | return 1; | |
344 | } | |
345 | ||
346 | return 0; | |
347 | }); | |
348 | ||
349 | primeHints(); | |
350 | ||
351 | /* fake that the root NS doesn't handle EDNS, check that we fallback */ | |
352 | vector<DNSRecord> ret; | |
353 | int res = sr->beginResolve(DNSName("powerdns.com."), QType(QType::A), QClass::IN, ret); | |
354 | BOOST_CHECK_EQUAL(res, 0); | |
355 | BOOST_CHECK_EQUAL(ret.size(), 1); | |
356 | BOOST_CHECK_EQUAL(queriesWithEDNS, 1); | |
357 | BOOST_CHECK_EQUAL(queriesWithoutEDNS, 1); | |
358 | BOOST_CHECK_EQUAL(t_sstorage->ednsstatus.size(), 1); | |
359 | BOOST_CHECK_EQUAL(t_sstorage->ednsstatus[noEDNSServer].mode, SyncRes::EDNSStatus::NOEDNS); | |
360 | } | |
361 | ||
362 | BOOST_AUTO_TEST_CASE(test_edns_notimp_fallback) { | |
363 | std::unique_ptr<SyncRes> sr; | |
364 | init(); | |
365 | initSR(sr, true, false); | |
366 | ||
367 | size_t queriesWithEDNS = 0; | |
368 | size_t queriesWithoutEDNS = 0; | |
369 | ||
370 | sr->setAsyncCallback([&queriesWithEDNS, &queriesWithoutEDNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
371 | if (EDNS0Level != 0) { | |
372 | queriesWithEDNS++; | |
373 | setLWResult(res, RCode::NotImp); | |
374 | return 1; | |
375 | } | |
376 | ||
377 | queriesWithoutEDNS++; | |
378 | ||
379 | if (domain == DNSName("powerdns.com") && type == QType::A && !doTCP) { | |
380 | setLWResult(res, 0, true, false, false); | |
381 | addRecordToLW(res, domain, QType::A, "192.0.2.1"); | |
382 | return 1; | |
383 | } | |
384 | ||
385 | return 0; | |
386 | }); | |
387 | ||
388 | primeHints(); | |
389 | ||
390 | /* fake that the NS doesn't handle EDNS, check that we fallback */ | |
391 | vector<DNSRecord> ret; | |
392 | int res = sr->beginResolve(DNSName("powerdns.com."), QType(QType::A), QClass::IN, ret); | |
393 | BOOST_CHECK_EQUAL(res, 0); | |
394 | BOOST_CHECK_EQUAL(ret.size(), 1); | |
395 | BOOST_CHECK_EQUAL(queriesWithEDNS, 1); | |
396 | BOOST_CHECK_EQUAL(queriesWithoutEDNS, 1); | |
397 | } | |
398 | ||
399 | BOOST_AUTO_TEST_CASE(test_tc_fallback_to_tcp) { | |
400 | std::unique_ptr<SyncRes> sr; | |
401 | init(); | |
402 | initSR(sr, true, false); | |
403 | ||
404 | sr->setAsyncCallback([](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
405 | if (!doTCP) { | |
406 | setLWResult(res, 0, false, true, false); | |
407 | return 1; | |
408 | } | |
409 | if (domain == DNSName("powerdns.com") && type == QType::A && doTCP) { | |
410 | setLWResult(res, 0, true, false, false); | |
411 | addRecordToLW(res, domain, QType::A, "192.0.2.1"); | |
412 | return 1; | |
413 | } | |
414 | ||
415 | return 0; | |
416 | }); | |
417 | ||
418 | primeHints(); | |
419 | ||
420 | /* fake that the NS truncates every request over UDP, we should fallback to TCP */ | |
421 | vector<DNSRecord> ret; | |
422 | int res = sr->beginResolve(DNSName("powerdns.com."), QType(QType::A), QClass::IN, ret); | |
423 | BOOST_CHECK_EQUAL(res, 0); | |
424 | } | |
425 | ||
426 | BOOST_AUTO_TEST_CASE(test_all_nss_down) { | |
427 | std::unique_ptr<SyncRes> sr; | |
428 | init(); | |
429 | initSR(sr, true, false); | |
430 | std::set<ComboAddress> downServers; | |
431 | ||
432 | primeHints(); | |
433 | ||
434 | sr->setAsyncCallback([&downServers](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
435 | ||
436 | if (isRootServer(ip)) { | |
437 | setLWResult(res, 0, true, false, true); | |
438 | addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
439 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
440 | addRecordToLW(res, "a.gtld-servers.net.", QType::AAAA, "2001:DB8::1", DNSResourceRecord::ADDITIONAL, 3600); | |
441 | return 1; | |
442 | } | |
443 | else if (ip == ComboAddress("192.0.2.1:53") || ip == ComboAddress("[2001:DB8::1]:53")) { | |
444 | setLWResult(res, 0, true, false, true); | |
445 | addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800); | |
446 | addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800); | |
447 | addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 172800); | |
448 | addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::AAAA, "2001:DB8::2", DNSResourceRecord::ADDITIONAL, 172800); | |
449 | addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::A, "192.0.2.3", DNSResourceRecord::ADDITIONAL, 172800); | |
450 | addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::AAAA, "2001:DB8::3", DNSResourceRecord::ADDITIONAL, 172800); | |
451 | return 1; | |
452 | } | |
453 | else { | |
454 | downServers.insert(ip); | |
455 | return 0; | |
456 | } | |
457 | }); | |
458 | ||
ccb07d93 RG |
459 | DNSName target("powerdns.com."); |
460 | ||
30ee601a | 461 | vector<DNSRecord> ret; |
ccb07d93 | 462 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); |
f58c8379 | 463 | BOOST_CHECK_EQUAL(res, RCode::ServFail); |
30ee601a RG |
464 | BOOST_CHECK_EQUAL(ret.size(), 0); |
465 | BOOST_CHECK_EQUAL(downServers.size(), 4); | |
466 | ||
467 | for (const auto& server : downServers) { | |
468 | BOOST_CHECK_EQUAL(t_sstorage->fails.value(server), 1); | |
ccb07d93 | 469 | BOOST_CHECK(t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(server, target, QType::A))); |
30ee601a RG |
470 | } |
471 | } | |
472 | ||
648bcbd1 RG |
473 | BOOST_AUTO_TEST_CASE(test_all_nss_network_error) { |
474 | std::unique_ptr<SyncRes> sr; | |
475 | init(); | |
476 | initSR(sr, true, false); | |
477 | std::set<ComboAddress> downServers; | |
478 | ||
479 | primeHints(); | |
480 | ||
481 | sr->setAsyncCallback([&downServers](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
482 | ||
483 | if (isRootServer(ip)) { | |
484 | setLWResult(res, 0, true, false, true); | |
485 | addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
486 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
487 | addRecordToLW(res, "a.gtld-servers.net.", QType::AAAA, "2001:DB8::1", DNSResourceRecord::ADDITIONAL, 3600); | |
488 | return 1; | |
489 | } | |
490 | else if (ip == ComboAddress("192.0.2.1:53") || ip == ComboAddress("[2001:DB8::1]:53")) { | |
491 | setLWResult(res, 0, true, false, true); | |
492 | addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800); | |
493 | addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800); | |
494 | addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 172800); | |
495 | addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::AAAA, "2001:DB8::2", DNSResourceRecord::ADDITIONAL, 172800); | |
496 | addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::A, "192.0.2.3", DNSResourceRecord::ADDITIONAL, 172800); | |
497 | addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::AAAA, "2001:DB8::3", DNSResourceRecord::ADDITIONAL, 172800); | |
498 | return 1; | |
499 | } | |
500 | else { | |
501 | downServers.insert(ip); | |
502 | return -1; | |
503 | } | |
504 | }); | |
505 | ||
506 | /* exact same test than the previous one, except instead of a time out we fake a network error */ | |
507 | DNSName target("powerdns.com."); | |
508 | ||
509 | vector<DNSRecord> ret; | |
510 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
511 | BOOST_CHECK_EQUAL(res, RCode::ServFail); | |
512 | BOOST_CHECK_EQUAL(ret.size(), 0); | |
513 | BOOST_CHECK_EQUAL(downServers.size(), 4); | |
514 | ||
515 | for (const auto& server : downServers) { | |
516 | BOOST_CHECK_EQUAL(t_sstorage->fails.value(server), 1); | |
517 | BOOST_CHECK(t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(server, target, QType::A))); | |
518 | } | |
519 | } | |
520 | ||
521 | BOOST_AUTO_TEST_CASE(test_os_limit_errors) { | |
522 | std::unique_ptr<SyncRes> sr; | |
523 | init(); | |
524 | initSR(sr, true, false); | |
525 | std::set<ComboAddress> downServers; | |
526 | ||
527 | primeHints(); | |
528 | ||
529 | sr->setAsyncCallback([&downServers](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
530 | ||
531 | if (isRootServer(ip)) { | |
532 | setLWResult(res, 0, true, false, true); | |
533 | addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
534 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
535 | addRecordToLW(res, "a.gtld-servers.net.", QType::AAAA, "2001:DB8::1", DNSResourceRecord::ADDITIONAL, 3600); | |
536 | return 1; | |
537 | } | |
538 | else if (ip == ComboAddress("192.0.2.1:53") || ip == ComboAddress("[2001:DB8::1]:53")) { | |
539 | setLWResult(res, 0, true, false, true); | |
540 | addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800); | |
541 | addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800); | |
542 | addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 172800); | |
543 | addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::AAAA, "2001:DB8::2", DNSResourceRecord::ADDITIONAL, 172800); | |
544 | addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::A, "192.0.2.3", DNSResourceRecord::ADDITIONAL, 172800); | |
545 | addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::AAAA, "2001:DB8::3", DNSResourceRecord::ADDITIONAL, 172800); | |
546 | return 1; | |
547 | } | |
548 | else { | |
549 | if (downServers.size() < 3) { | |
550 | /* only the last one will answer */ | |
551 | downServers.insert(ip); | |
552 | return -2; | |
553 | } | |
554 | else { | |
555 | setLWResult(res, 0, true, false, true); | |
556 | addRecordToLW(res, "powerdns.com.", QType::A, "192.0.2.42"); | |
557 | return 1; | |
558 | } | |
559 | } | |
560 | }); | |
561 | ||
562 | DNSName target("powerdns.com."); | |
563 | ||
564 | vector<DNSRecord> ret; | |
565 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
566 | BOOST_CHECK_EQUAL(res, 0); | |
567 | BOOST_CHECK_EQUAL(ret.size(), 1); | |
568 | BOOST_CHECK_EQUAL(downServers.size(), 3); | |
569 | ||
570 | /* Error is reported as "OS limit error" (-2) so the servers should _NOT_ be marked down */ | |
571 | for (const auto& server : downServers) { | |
572 | BOOST_CHECK_EQUAL(t_sstorage->fails.value(server), 0); | |
573 | BOOST_CHECK(!t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(server, target, QType::A))); | |
574 | } | |
575 | } | |
576 | ||
30ee601a RG |
577 | BOOST_AUTO_TEST_CASE(test_glued_referral) { |
578 | std::unique_ptr<SyncRes> sr; | |
579 | init(); | |
580 | initSR(sr, true, false); | |
581 | ||
582 | primeHints(); | |
583 | ||
584 | const DNSName target("powerdns.com."); | |
585 | ||
586 | sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
587 | /* this will cause issue with qname minimization if we ever implement it */ | |
588 | if (domain != target) { | |
589 | return 0; | |
590 | } | |
591 | ||
592 | if (isRootServer(ip)) { | |
593 | setLWResult(res, 0, true, false, true); | |
594 | addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
595 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
596 | addRecordToLW(res, "a.gtld-servers.net.", QType::AAAA, "2001:DB8::1", DNSResourceRecord::ADDITIONAL, 3600); | |
597 | return 1; | |
598 | } | |
599 | else if (ip == ComboAddress("192.0.2.1:53") || ip == ComboAddress("[2001:DB8::1]:53")) { | |
600 | setLWResult(res, 0, true, false, true); | |
601 | addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800); | |
602 | addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800); | |
603 | addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 172800); | |
604 | addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::AAAA, "2001:DB8::2", DNSResourceRecord::ADDITIONAL, 172800); | |
605 | addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::A, "192.0.2.3", DNSResourceRecord::ADDITIONAL, 172800); | |
606 | addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::AAAA, "2001:DB8::3", DNSResourceRecord::ADDITIONAL, 172800); | |
607 | return 1; | |
608 | } | |
609 | else if (ip == ComboAddress("192.0.2.2:53") || ip == ComboAddress("192.0.2.3:53") || ip == ComboAddress("[2001:DB8::2]:53") || ip == ComboAddress("[2001:DB8::3]:53")) { | |
610 | setLWResult(res, 0, true, false, true); | |
611 | addRecordToLW(res, target, QType::A, "192.0.2.4"); | |
612 | return 1; | |
613 | } | |
614 | else { | |
615 | return 0; | |
616 | } | |
617 | }); | |
618 | ||
619 | vector<DNSRecord> ret; | |
620 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
621 | BOOST_CHECK_EQUAL(res, 0); | |
622 | BOOST_REQUIRE_EQUAL(ret.size(), 1); | |
e9f9b8ec | 623 | BOOST_CHECK(ret[0].d_type == QType::A); |
30ee601a RG |
624 | BOOST_CHECK_EQUAL(ret[0].d_name, target); |
625 | } | |
626 | ||
627 | BOOST_AUTO_TEST_CASE(test_glueless_referral) { | |
628 | std::unique_ptr<SyncRes> sr; | |
629 | init(); | |
630 | initSR(sr, true, false); | |
631 | ||
632 | primeHints(); | |
633 | ||
634 | const DNSName target("powerdns.com."); | |
635 | ||
636 | sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
637 | ||
638 | if (isRootServer(ip)) { | |
639 | setLWResult(res, 0, true, false, true); | |
640 | ||
641 | if (domain.isPartOf(DNSName("com."))) { | |
642 | addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
643 | } else if (domain.isPartOf(DNSName("org."))) { | |
644 | addRecordToLW(res, "org.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
645 | } | |
646 | else { | |
647 | setLWResult(res, RCode::NXDomain, false, false, true); | |
648 | return 1; | |
649 | } | |
650 | ||
651 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
652 | addRecordToLW(res, "a.gtld-servers.net.", QType::AAAA, "2001:DB8::1", DNSResourceRecord::ADDITIONAL, 3600); | |
653 | return 1; | |
654 | } | |
655 | else if (ip == ComboAddress("192.0.2.1:53") || ip == ComboAddress("[2001:DB8::1]:53")) { | |
656 | if (domain == target) { | |
657 | setLWResult(res, 0, true, false, true); | |
658 | addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns1.powerdns.org.", DNSResourceRecord::AUTHORITY, 172800); | |
659 | addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns2.powerdns.org.", DNSResourceRecord::AUTHORITY, 172800); | |
660 | return 1; | |
661 | } | |
662 | else if (domain == DNSName("pdns-public-ns1.powerdns.org.")) { | |
663 | setLWResult(res, 0, true, false, true); | |
664 | addRecordToLW(res, "pdns-public-ns1.powerdns.org.", QType::A, "192.0.2.2"); | |
665 | addRecordToLW(res, "pdns-public-ns1.powerdns.org.", QType::AAAA, "2001:DB8::2"); | |
666 | return 1; | |
667 | } | |
668 | else if (domain == DNSName("pdns-public-ns2.powerdns.org.")) { | |
669 | setLWResult(res, 0, true, false, true); | |
670 | addRecordToLW(res, "pdns-public-ns2.powerdns.org.", QType::A, "192.0.2.3"); | |
671 | addRecordToLW(res, "pdns-public-ns2.powerdns.org.", QType::AAAA, "2001:DB8::3"); | |
672 | return 1; | |
673 | } | |
674 | ||
675 | setLWResult(res, RCode::NXDomain, false, false, true); | |
676 | return 1; | |
677 | } | |
678 | else if (ip == ComboAddress("192.0.2.2:53") || ip == ComboAddress("192.0.2.3:53") || ip == ComboAddress("[2001:DB8::2]:53") || ip == ComboAddress("[2001:DB8::3]:53")) { | |
679 | setLWResult(res, 0, true, false, true); | |
680 | addRecordToLW(res, target, QType::A, "192.0.2.4"); | |
681 | return 1; | |
682 | } | |
683 | else { | |
684 | return 0; | |
685 | } | |
686 | }); | |
687 | ||
688 | vector<DNSRecord> ret; | |
689 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
690 | BOOST_CHECK_EQUAL(res, 0); | |
691 | BOOST_REQUIRE_EQUAL(ret.size(), 1); | |
e9f9b8ec | 692 | BOOST_CHECK(ret[0].d_type == QType::A); |
30ee601a RG |
693 | BOOST_CHECK_EQUAL(ret[0].d_name, target); |
694 | } | |
695 | ||
e9f9b8ec RG |
696 | BOOST_AUTO_TEST_CASE(test_edns_submask_by_domain) { |
697 | std::unique_ptr<SyncRes> sr; | |
698 | init(); | |
699 | initSR(sr, true, false); | |
700 | ||
701 | primeHints(); | |
702 | ||
703 | const DNSName target("powerdns.com."); | |
704 | g_useIncomingECS = true; | |
705 | g_ednsdomains.add(target); | |
706 | ||
707 | EDNSSubnetOpts incomingECS; | |
708 | incomingECS.source = Netmask("192.0.2.128/32"); | |
709 | sr->setIncomingECSFound(true); | |
710 | sr->setIncomingECS(incomingECS); | |
711 | ||
712 | sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
713 | ||
714 | BOOST_REQUIRE(srcmask); | |
715 | BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24"); | |
716 | return 0; | |
717 | }); | |
718 | ||
719 | vector<DNSRecord> ret; | |
720 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
f58c8379 | 721 | BOOST_CHECK_EQUAL(res, RCode::ServFail); |
e9f9b8ec RG |
722 | } |
723 | ||
724 | BOOST_AUTO_TEST_CASE(test_edns_submask_by_addr) { | |
725 | std::unique_ptr<SyncRes> sr; | |
726 | init(); | |
727 | initSR(sr, true, false); | |
728 | ||
729 | primeHints(); | |
730 | ||
731 | const DNSName target("powerdns.com."); | |
732 | g_useIncomingECS = true; | |
733 | g_ednssubnets.addMask("192.0.2.1/32"); | |
734 | ||
735 | EDNSSubnetOpts incomingECS; | |
736 | incomingECS.source = Netmask("2001:DB8::FF/128"); | |
737 | sr->setIncomingECSFound(true); | |
738 | sr->setIncomingECS(incomingECS); | |
739 | ||
740 | sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
741 | ||
742 | if (isRootServer(ip)) { | |
743 | BOOST_REQUIRE(!srcmask); | |
744 | ||
745 | setLWResult(res, 0, true, false, true); | |
746 | addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
747 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
748 | return 1; | |
749 | } else if (ip == ComboAddress("192.0.2.1:53")) { | |
750 | ||
751 | BOOST_REQUIRE(srcmask); | |
752 | BOOST_CHECK_EQUAL(srcmask->toString(), "2001:db8::/56"); | |
753 | ||
754 | setLWResult(res, 0, true, false, false); | |
755 | addRecordToLW(res, domain, QType::A, "192.0.2.2"); | |
756 | return 1; | |
757 | } | |
758 | ||
759 | return 0; | |
760 | }); | |
761 | ||
762 | vector<DNSRecord> ret; | |
763 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
764 | BOOST_CHECK_EQUAL(res, 0); | |
778bcea6 RG |
765 | BOOST_REQUIRE_EQUAL(ret.size(), 1); |
766 | BOOST_CHECK(ret[0].d_type == QType::A); | |
767 | BOOST_CHECK_EQUAL(ret[0].d_name, target); | |
768 | } | |
769 | ||
770 | BOOST_AUTO_TEST_CASE(test_following_cname) { | |
771 | std::unique_ptr<SyncRes> sr; | |
772 | init(); | |
773 | initSR(sr, true, false); | |
774 | ||
775 | primeHints(); | |
776 | ||
777 | const DNSName target("cname.powerdns.com."); | |
778 | const DNSName cnameTarget("cname-target.powerdns.com"); | |
779 | ||
780 | sr->setAsyncCallback([target, cnameTarget](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
781 | ||
782 | if (isRootServer(ip)) { | |
778bcea6 RG |
783 | setLWResult(res, 0, true, false, true); |
784 | addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
785 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
786 | return 1; | |
787 | } else if (ip == ComboAddress("192.0.2.1:53")) { | |
788 | ||
789 | if (domain == target) { | |
790 | setLWResult(res, 0, true, false, false); | |
791 | addRecordToLW(res, domain, QType::CNAME, cnameTarget.toString()); | |
792 | return 1; | |
793 | } | |
794 | else if (domain == cnameTarget) { | |
795 | setLWResult(res, 0, true, false, false); | |
796 | addRecordToLW(res, domain, QType::A, "192.0.2.2"); | |
797 | } | |
798 | ||
799 | return 1; | |
800 | } | |
801 | ||
802 | return 0; | |
803 | }); | |
804 | ||
805 | vector<DNSRecord> ret; | |
806 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
807 | BOOST_CHECK_EQUAL(res, 0); | |
808 | BOOST_REQUIRE_EQUAL(ret.size(), 2); | |
809 | BOOST_CHECK(ret[0].d_type == QType::CNAME); | |
810 | BOOST_CHECK_EQUAL(ret[0].d_name, target); | |
811 | BOOST_CHECK(ret[1].d_type == QType::A); | |
812 | BOOST_CHECK_EQUAL(ret[1].d_name, cnameTarget); | |
813 | } | |
814 | ||
4fff116b RG |
815 | BOOST_AUTO_TEST_CASE(test_included_poisonous_cname) { |
816 | std::unique_ptr<SyncRes> sr; | |
817 | init(); | |
818 | initSR(sr, true, false); | |
819 | ||
820 | primeHints(); | |
821 | ||
822 | /* In this test we directly get the NS server for cname.powerdns.com., | |
823 | and we don't know whether it's also authoritative for | |
824 | cname-target.powerdns.com or powerdns.com, so we shouldn't accept | |
825 | the additional A record for cname-target.powerdns.com. */ | |
826 | const DNSName target("cname.powerdns.com."); | |
827 | const DNSName cnameTarget("cname-target.powerdns.com"); | |
828 | ||
829 | sr->setAsyncCallback([target, cnameTarget](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
830 | ||
831 | if (isRootServer(ip)) { | |
832 | ||
833 | setLWResult(res, 0, true, false, true); | |
834 | ||
835 | addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
836 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
837 | return 1; | |
838 | } else if (ip == ComboAddress("192.0.2.1:53")) { | |
839 | ||
840 | if (domain == target) { | |
841 | setLWResult(res, 0, true, false, false); | |
842 | addRecordToLW(res, domain, QType::CNAME, cnameTarget.toString()); | |
843 | addRecordToLW(res, cnameTarget, QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL); | |
844 | return 1; | |
845 | } else if (domain == cnameTarget) { | |
846 | setLWResult(res, 0, true, false, false); | |
847 | addRecordToLW(res, cnameTarget, QType::A, "192.0.2.3"); | |
848 | return 1; | |
849 | } | |
850 | ||
851 | return 1; | |
852 | } | |
853 | ||
854 | return 0; | |
855 | }); | |
856 | ||
857 | vector<DNSRecord> ret; | |
858 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
859 | BOOST_CHECK_EQUAL(res, 0); | |
860 | BOOST_REQUIRE_EQUAL(ret.size(), 2); | |
861 | BOOST_REQUIRE(ret[0].d_type == QType::CNAME); | |
862 | BOOST_CHECK_EQUAL(ret[0].d_name, target); | |
863 | BOOST_CHECK_EQUAL(getRR<CNAMERecordContent>(ret[0])->getTarget(), cnameTarget); | |
864 | BOOST_REQUIRE(ret[1].d_type == QType::A); | |
865 | BOOST_CHECK_EQUAL(ret[1].d_name, cnameTarget); | |
866 | BOOST_CHECK(getRR<ARecordContent>(ret[1])->getCA() == ComboAddress("192.0.2.3")); | |
867 | } | |
868 | ||
778bcea6 RG |
869 | BOOST_AUTO_TEST_CASE(test_cname_loop) { |
870 | std::unique_ptr<SyncRes> sr; | |
871 | init(); | |
872 | initSR(sr, true, false); | |
873 | ||
874 | primeHints(); | |
875 | ||
876 | size_t count = 0; | |
877 | const DNSName target("cname.powerdns.com."); | |
878 | ||
879 | sr->setAsyncCallback([target,&count](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
880 | ||
881 | count++; | |
882 | ||
883 | if (isRootServer(ip)) { | |
778bcea6 RG |
884 | |
885 | setLWResult(res, 0, true, false, true); | |
886 | addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
887 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
888 | return 1; | |
889 | } else if (ip == ComboAddress("192.0.2.1:53")) { | |
890 | ||
891 | if (domain == target) { | |
892 | setLWResult(res, 0, true, false, false); | |
893 | addRecordToLW(res, domain, QType::CNAME, domain.toString()); | |
894 | return 1; | |
895 | } | |
896 | ||
897 | return 1; | |
898 | } | |
899 | ||
900 | return 0; | |
901 | }); | |
902 | ||
903 | vector<DNSRecord> ret; | |
904 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
f58c8379 RG |
905 | BOOST_CHECK_EQUAL(res, RCode::ServFail); |
906 | BOOST_CHECK_GT(ret.size(), 0); | |
778bcea6 | 907 | BOOST_CHECK_EQUAL(count, 2); |
e9f9b8ec RG |
908 | } |
909 | ||
4fff116b RG |
910 | BOOST_AUTO_TEST_CASE(test_cname_depth) { |
911 | std::unique_ptr<SyncRes> sr; | |
912 | init(); | |
913 | initSR(sr, true, false); | |
914 | ||
915 | primeHints(); | |
916 | ||
917 | size_t depth = 0; | |
918 | const DNSName target("cname.powerdns.com."); | |
919 | ||
920 | sr->setAsyncCallback([target,&depth](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
921 | ||
922 | if (isRootServer(ip)) { | |
4fff116b RG |
923 | |
924 | setLWResult(res, 0, true, false, true); | |
925 | addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
926 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
927 | return 1; | |
928 | } else if (ip == ComboAddress("192.0.2.1:53")) { | |
929 | ||
930 | setLWResult(res, 0, true, false, false); | |
931 | addRecordToLW(res, domain, QType::CNAME, std::to_string(depth) + "-cname.powerdns.com"); | |
932 | depth++; | |
933 | return 1; | |
934 | } | |
935 | ||
936 | return 0; | |
937 | }); | |
938 | ||
939 | vector<DNSRecord> ret; | |
940 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
f58c8379 RG |
941 | BOOST_CHECK_EQUAL(res, RCode::ServFail); |
942 | BOOST_CHECK_EQUAL(ret.size(), depth); | |
4fff116b RG |
943 | /* we have an arbitrary limit at 10 when following a CNAME chain */ |
944 | BOOST_CHECK_EQUAL(depth, 10 + 2); | |
945 | } | |
946 | ||
d6e797b8 RG |
947 | BOOST_AUTO_TEST_CASE(test_time_limit) { |
948 | std::unique_ptr<SyncRes> sr; | |
949 | init(); | |
950 | initSR(sr, true, false); | |
951 | ||
952 | primeHints(); | |
953 | ||
954 | size_t queries = 0; | |
955 | const DNSName target("cname.powerdns.com."); | |
956 | ||
957 | sr->setAsyncCallback([target,&queries](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
958 | ||
959 | queries++; | |
960 | ||
961 | if (isRootServer(ip)) { | |
962 | setLWResult(res, 0, true, false, true); | |
963 | /* Pretend that this query took 2000 ms */ | |
964 | res->d_usec = 2000; | |
965 | ||
966 | addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
967 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
968 | return 1; | |
969 | } else if (ip == ComboAddress("192.0.2.1:53")) { | |
970 | ||
971 | setLWResult(res, 0, true, false, false); | |
972 | addRecordToLW(res, domain, QType::A, "192.0.2.2"); | |
973 | return 1; | |
974 | } | |
975 | ||
976 | return 0; | |
977 | }); | |
978 | ||
979 | /* Set the maximum time to 1 ms */ | |
980 | SyncRes::s_maxtotusec = 1000; | |
981 | ||
982 | try { | |
983 | vector<DNSRecord> ret; | |
984 | sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
985 | BOOST_CHECK(false); | |
986 | } | |
987 | catch(const ImmediateServFailException& e) { | |
988 | } | |
989 | BOOST_CHECK_EQUAL(queries, 1); | |
990 | } | |
991 | ||
992 | BOOST_AUTO_TEST_CASE(test_referral_depth) { | |
993 | std::unique_ptr<SyncRes> sr; | |
994 | init(); | |
995 | initSR(sr, true, false); | |
996 | ||
997 | primeHints(); | |
998 | ||
999 | size_t queries = 0; | |
1000 | const DNSName target("www.powerdns.com."); | |
1001 | ||
1002 | sr->setAsyncCallback([target,&queries](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1003 | ||
1004 | queries++; | |
1005 | ||
1006 | if (isRootServer(ip)) { | |
1007 | setLWResult(res, 0, true, false, true); | |
1008 | ||
1009 | if (domain == DNSName("www.powerdns.com.")) { | |
1010 | addRecordToLW(res, domain, QType::NS, "ns.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800); | |
1011 | } | |
1012 | else if (domain == DNSName("ns.powerdns.com.")) { | |
1013 | addRecordToLW(res, domain, QType::NS, "ns1.powerdns.org.", DNSResourceRecord::AUTHORITY, 172800); | |
1014 | } | |
1015 | else if (domain == DNSName("ns1.powerdns.org.")) { | |
1016 | addRecordToLW(res, domain, QType::NS, "ns2.powerdns.org.", DNSResourceRecord::AUTHORITY, 172800); | |
1017 | } | |
1018 | else if (domain == DNSName("ns2.powerdns.org.")) { | |
1019 | addRecordToLW(res, domain, QType::NS, "ns3.powerdns.org.", DNSResourceRecord::AUTHORITY, 172800); | |
1020 | } | |
1021 | else if (domain == DNSName("ns3.powerdns.org.")) { | |
1022 | addRecordToLW(res, domain, QType::NS, "ns4.powerdns.org.", DNSResourceRecord::AUTHORITY, 172800); | |
1023 | } | |
1024 | else if (domain == DNSName("ns4.powerdns.org.")) { | |
1025 | addRecordToLW(res, domain, QType::NS, "ns5.powerdns.org.", DNSResourceRecord::AUTHORITY, 172800); | |
1026 | addRecordToLW(res, domain, QType::A, "192.0.2.1", DNSResourceRecord::AUTHORITY, 172800); | |
1027 | } | |
1028 | ||
1029 | return 1; | |
1030 | } else if (ip == ComboAddress("192.0.2.1:53")) { | |
1031 | ||
1032 | setLWResult(res, 0, true, false, false); | |
1033 | addRecordToLW(res, domain, QType::A, "192.0.2.2"); | |
1034 | return 1; | |
1035 | } | |
1036 | ||
1037 | return 0; | |
1038 | }); | |
1039 | ||
1040 | /* Set the maximum depth low */ | |
1041 | SyncRes::s_maxdepth = 10; | |
1042 | ||
1043 | try { | |
1044 | vector<DNSRecord> ret; | |
1045 | sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1046 | BOOST_CHECK(false); | |
1047 | } | |
1048 | catch(const ImmediateServFailException& e) { | |
1049 | } | |
1050 | } | |
1051 | ||
1052 | BOOST_AUTO_TEST_CASE(test_cname_qperq) { | |
1053 | std::unique_ptr<SyncRes> sr; | |
1054 | init(); | |
1055 | initSR(sr, true, false); | |
1056 | ||
1057 | primeHints(); | |
1058 | ||
1059 | size_t queries = 0; | |
1060 | const DNSName target("cname.powerdns.com."); | |
1061 | ||
1062 | sr->setAsyncCallback([target,&queries](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1063 | ||
1064 | queries++; | |
1065 | ||
1066 | if (isRootServer(ip)) { | |
1067 | ||
1068 | setLWResult(res, 0, true, false, true); | |
1069 | addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
1070 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
1071 | return 1; | |
1072 | } else if (ip == ComboAddress("192.0.2.1:53")) { | |
1073 | ||
1074 | setLWResult(res, 0, true, false, false); | |
1075 | addRecordToLW(res, domain, QType::CNAME, std::to_string(queries) + "-cname.powerdns.com"); | |
1076 | return 1; | |
1077 | } | |
1078 | ||
1079 | return 0; | |
1080 | }); | |
1081 | ||
1082 | /* Set the maximum number of questions very low */ | |
1083 | SyncRes::s_maxqperq = 5; | |
1084 | ||
1085 | try { | |
1086 | vector<DNSRecord> ret; | |
1087 | sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1088 | BOOST_CHECK(false); | |
1089 | } | |
1090 | catch(const ImmediateServFailException& e) { | |
1091 | BOOST_CHECK_EQUAL(queries, SyncRes::s_maxqperq); | |
1092 | } | |
1093 | } | |
1094 | ||
ccb07d93 RG |
1095 | BOOST_AUTO_TEST_CASE(test_throttled_server) { |
1096 | std::unique_ptr<SyncRes> sr; | |
1097 | init(); | |
1098 | initSR(sr, true, false); | |
1099 | ||
1100 | primeHints(); | |
1101 | ||
1102 | const DNSName target("throttled.powerdns.com."); | |
1103 | const ComboAddress ns("192.0.2.1:53"); | |
1104 | size_t queriesToNS = 0; | |
1105 | ||
1106 | sr->setAsyncCallback([target,ns,&queriesToNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1107 | ||
1108 | if (isRootServer(ip)) { | |
ccb07d93 RG |
1109 | |
1110 | setLWResult(res, 0, true, false, true); | |
1111 | addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
1112 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600); | |
1113 | return 1; | |
1114 | } else if (ip == ns) { | |
1115 | ||
1116 | queriesToNS++; | |
1117 | ||
1118 | setLWResult(res, 0, true, false, false); | |
1119 | addRecordToLW(res, domain, QType::A, "192.0.2.2"); | |
1120 | ||
1121 | return 1; | |
1122 | } | |
1123 | ||
1124 | return 0; | |
1125 | }); | |
1126 | ||
1127 | /* mark ns as down */ | |
1128 | t_sstorage->throttle.throttle(time(nullptr), boost::make_tuple(ns, "", 0), SyncRes::s_serverdownthrottletime, 10000); | |
1129 | ||
1130 | vector<DNSRecord> ret; | |
1131 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
f58c8379 RG |
1132 | BOOST_CHECK_EQUAL(res, RCode::ServFail); |
1133 | BOOST_CHECK_EQUAL(ret.size(), 0); | |
1134 | /* we should not have sent any queries to ns */ | |
ccb07d93 RG |
1135 | BOOST_CHECK_EQUAL(queriesToNS, 0); |
1136 | } | |
1137 | ||
1138 | BOOST_AUTO_TEST_CASE(test_throttled_server_count) { | |
1139 | std::unique_ptr<SyncRes> sr; | |
1140 | init(); | |
1141 | initSR(sr, true, false); | |
1142 | ||
1143 | primeHints(); | |
1144 | ||
1145 | const ComboAddress ns("192.0.2.1:53"); | |
1146 | ||
1147 | const size_t blocks = 10; | |
1148 | /* mark ns as down for 'blocks' queries */ | |
1149 | t_sstorage->throttle.throttle(time(nullptr), boost::make_tuple(ns, "", 0), SyncRes::s_serverdownthrottletime, blocks); | |
1150 | ||
1151 | for (size_t idx = 0; idx < blocks; idx++) { | |
1152 | BOOST_CHECK(t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(ns, "", 0))); | |
1153 | } | |
1154 | ||
1155 | /* we have been throttled 'blocks' times, we should not be throttled anymore */ | |
1156 | BOOST_CHECK(!t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(ns, "", 0))); | |
1157 | } | |
1158 | ||
1159 | BOOST_AUTO_TEST_CASE(test_throttled_server_time) { | |
1160 | std::unique_ptr<SyncRes> sr; | |
1161 | init(); | |
1162 | initSR(sr, true, false); | |
1163 | ||
1164 | primeHints(); | |
1165 | ||
1166 | const ComboAddress ns("192.0.2.1:53"); | |
1167 | ||
1168 | const size_t seconds = 1; | |
1169 | /* mark ns as down for 'seconds' seconds */ | |
1170 | t_sstorage->throttle.throttle(time(nullptr), boost::make_tuple(ns, "", 0), seconds, 10000); | |
1171 | BOOST_CHECK(t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(ns, "", 0))); | |
1172 | ||
1173 | sleep(seconds + 1); | |
1174 | ||
1175 | /* we should not be throttled anymore */ | |
1176 | BOOST_CHECK(!t_sstorage->throttle.shouldThrottle(time(nullptr), boost::make_tuple(ns, "", 0))); | |
1177 | } | |
1178 | ||
f58c8379 RG |
1179 | BOOST_AUTO_TEST_CASE(test_dont_query_server) { |
1180 | std::unique_ptr<SyncRes> sr; | |
1181 | init(); | |
1182 | initSR(sr, true, false); | |
1183 | ||
1184 | primeHints(); | |
1185 | ||
1186 | const DNSName target("throttled.powerdns.com."); | |
1187 | const ComboAddress ns("192.0.2.1:53"); | |
1188 | size_t queriesToNS = 0; | |
1189 | ||
1190 | sr->setAsyncCallback([target,ns,&queriesToNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1191 | ||
1192 | if (isRootServer(ip)) { | |
1193 | ||
1194 | setLWResult(res, 0, true, false, true); | |
1195 | addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
1196 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600); | |
1197 | return 1; | |
1198 | } else if (ip == ns) { | |
1199 | ||
1200 | queriesToNS++; | |
1201 | ||
1202 | setLWResult(res, 0, true, false, false); | |
1203 | addRecordToLW(res, domain, QType::A, "192.0.2.2"); | |
1204 | ||
1205 | return 1; | |
1206 | } | |
1207 | ||
1208 | return 0; | |
1209 | }); | |
1210 | ||
1211 | /* prevent querying this NS */ | |
1212 | g_dontQuery->addMask(Netmask(ns)); | |
1213 | ||
1214 | vector<DNSRecord> ret; | |
1215 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1216 | BOOST_CHECK_EQUAL(res, RCode::ServFail); | |
1217 | BOOST_CHECK_EQUAL(ret.size(), 0); | |
1218 | /* we should not have sent any queries to ns */ | |
1219 | BOOST_CHECK_EQUAL(queriesToNS, 0); | |
1220 | } | |
1221 | ||
1222 | BOOST_AUTO_TEST_CASE(test_root_nx_trust) { | |
1223 | std::unique_ptr<SyncRes> sr; | |
1224 | init(); | |
1225 | initSR(sr, true, false); | |
1226 | ||
1227 | primeHints(); | |
1228 | ||
1229 | const DNSName target1("powerdns.com."); | |
1230 | const DNSName target2("notpowerdns.com."); | |
1231 | const ComboAddress ns("192.0.2.1:53"); | |
1232 | size_t queriesCount = 0; | |
1233 | ||
1234 | sr->setAsyncCallback([target1, target2, ns, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1235 | ||
1236 | queriesCount++; | |
1237 | ||
1238 | if (isRootServer(ip)) { | |
1239 | ||
1240 | if (domain == target1) { | |
1241 | setLWResult(res, RCode::NXDomain, true, false, true); | |
1242 | addRecordToLW(res, ".", QType::SOA, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400); | |
1243 | } | |
1244 | else { | |
1245 | setLWResult(res, 0, true, false, true); | |
1246 | addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
1247 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600); | |
1248 | } | |
1249 | ||
1250 | return 1; | |
1251 | } else if (ip == ns) { | |
1252 | ||
1253 | setLWResult(res, 0, true, false, false); | |
1254 | addRecordToLW(res, domain, QType::A, "192.0.2.2"); | |
1255 | ||
1256 | return 1; | |
1257 | } | |
1258 | ||
1259 | return 0; | |
1260 | }); | |
1261 | ||
1262 | vector<DNSRecord> ret; | |
1263 | int res = sr->beginResolve(target1, QType(QType::A), QClass::IN, ret); | |
1264 | BOOST_CHECK_EQUAL(res, RCode::NXDomain); | |
1265 | BOOST_CHECK_EQUAL(ret.size(), 1); | |
1266 | /* one for target1 and one for the entire TLD */ | |
1267 | BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 2); | |
1268 | ||
1269 | ret.clear(); | |
1270 | res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret); | |
1271 | BOOST_CHECK_EQUAL(res, RCode::NXDomain); | |
1272 | BOOST_CHECK_EQUAL(ret.size(), 1); | |
1273 | /* one for target1 and one for the entire TLD */ | |
1274 | BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 2); | |
1275 | ||
1276 | /* we should have sent only one query */ | |
1277 | BOOST_CHECK_EQUAL(queriesCount, 1); | |
1278 | } | |
1279 | ||
1280 | BOOST_AUTO_TEST_CASE(test_root_nx_dont_trust) { | |
1281 | std::unique_ptr<SyncRes> sr; | |
1282 | init(); | |
1283 | initSR(sr, true, false); | |
1284 | ||
1285 | primeHints(); | |
1286 | ||
1287 | const DNSName target1("powerdns.com."); | |
1288 | const DNSName target2("notpowerdns.com."); | |
1289 | const ComboAddress ns("192.0.2.1:53"); | |
1290 | size_t queriesCount = 0; | |
1291 | ||
1292 | sr->setAsyncCallback([target1, target2, ns, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1293 | ||
1294 | queriesCount++; | |
1295 | ||
1296 | if (isRootServer(ip)) { | |
1297 | ||
1298 | if (domain == target1) { | |
1299 | setLWResult(res, RCode::NXDomain, true, false, true); | |
1300 | addRecordToLW(res, ".", QType::SOA, "a.root-servers.net. nstld.verisign-grs.com. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400); | |
1301 | } | |
1302 | else { | |
1303 | setLWResult(res, 0, true, false, true); | |
1304 | addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
1305 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600); | |
1306 | } | |
1307 | ||
1308 | return 1; | |
1309 | } else if (ip == ns) { | |
1310 | ||
1311 | setLWResult(res, 0, true, false, false); | |
1312 | addRecordToLW(res, domain, QType::A, "192.0.2.2"); | |
1313 | ||
1314 | return 1; | |
1315 | } | |
1316 | ||
1317 | return 0; | |
1318 | }); | |
1319 | ||
1320 | SyncRes::s_rootNXTrust = false; | |
1321 | ||
1322 | vector<DNSRecord> ret; | |
1323 | int res = sr->beginResolve(target1, QType(QType::A), QClass::IN, ret); | |
1324 | BOOST_CHECK_EQUAL(res, RCode::NXDomain); | |
1325 | BOOST_CHECK_EQUAL(ret.size(), 1); | |
1326 | /* one for target1 */ | |
1327 | BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 1); | |
1328 | ||
1329 | ret.clear(); | |
1330 | res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret); | |
1331 | BOOST_CHECK_EQUAL(res, 0); | |
1332 | BOOST_CHECK_EQUAL(ret.size(), 1); | |
1333 | /* one for target1 */ | |
1334 | BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 1); | |
1335 | ||
1336 | /* we should have sent three queries */ | |
1337 | BOOST_CHECK_EQUAL(queriesCount, 3); | |
1338 | } | |
1339 | ||
1340 | BOOST_AUTO_TEST_CASE(test_skip_negcache_for_variable_response) { | |
1341 | std::unique_ptr<SyncRes> sr; | |
1342 | init(); | |
1343 | initSR(sr, true, false); | |
1344 | ||
1345 | primeHints(); | |
1346 | ||
1347 | const DNSName target("www.powerdns.com."); | |
1348 | const DNSName cnameTarget("cname.powerdns.com."); | |
1349 | ||
1350 | g_useIncomingECS = true; | |
1351 | g_ednsdomains.add(DNSName("powerdns.com.")); | |
1352 | ||
1353 | EDNSSubnetOpts incomingECS; | |
1354 | incomingECS.source = Netmask("192.0.2.128/32"); | |
1355 | sr->setIncomingECSFound(true); | |
1356 | sr->setIncomingECS(incomingECS); | |
1357 | ||
1358 | sr->setAsyncCallback([target,cnameTarget](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1359 | ||
1360 | BOOST_REQUIRE(srcmask); | |
1361 | BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24"); | |
1362 | ||
1363 | if (isRootServer(ip)) { | |
1364 | setLWResult(res, 0, true, false, true); | |
1365 | addRecordToLW(res, "powerdns.com.", QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800); | |
1366 | addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
1367 | ||
1368 | return 1; | |
1369 | } else if (ip == ComboAddress("192.0.2.1:53")) { | |
1370 | if (domain == target) { | |
1371 | /* Type 2 NXDOMAIN (rfc2308 section-2.1) */ | |
1372 | setLWResult(res, RCode::NXDomain, true, false, true); | |
1373 | addRecordToLW(res, domain, QType::CNAME, cnameTarget.toString()); | |
1374 | addRecordToLW(res, "powerdns.com", QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600); | |
1375 | } | |
1376 | else if (domain == cnameTarget) { | |
1377 | /* we shouldn't get there since the Type NXDOMAIN should have been enough, | |
1378 | but we might if we still chase the CNAME. */ | |
1379 | setLWResult(res, RCode::NXDomain, true, false, true); | |
1380 | addRecordToLW(res, "powerdns.com", QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600); | |
1381 | } | |
1382 | ||
1383 | return 1; | |
1384 | } | |
1385 | ||
1386 | return 0; | |
1387 | }); | |
1388 | ||
1389 | vector<DNSRecord> ret; | |
1390 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1391 | BOOST_CHECK_EQUAL(res, RCode::NXDomain); | |
1392 | BOOST_CHECK_EQUAL(ret.size(), 2); | |
1393 | /* no negative cache entry because the response was variable */ | |
1394 | BOOST_CHECK_EQUAL(t_sstorage->negcache.size(), 0); | |
1395 | } | |
1396 | ||
d6e797b8 RG |
1397 | BOOST_AUTO_TEST_CASE(test_ns_speed) { |
1398 | std::unique_ptr<SyncRes> sr; | |
1399 | init(); | |
1400 | initSR(sr, true, false); | |
30ee601a | 1401 | |
d6e797b8 | 1402 | primeHints(); |
30ee601a | 1403 | |
d6e797b8 | 1404 | const DNSName target("powerdns.com."); |
30ee601a | 1405 | |
d6e797b8 | 1406 | std::map<ComboAddress, uint64_t> nsCounts; |
30ee601a | 1407 | |
d6e797b8 | 1408 | sr->setAsyncCallback([target,&nsCounts](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { |
30ee601a | 1409 | |
d6e797b8 RG |
1410 | if (isRootServer(ip)) { |
1411 | setLWResult(res, 0, true, false, true); | |
1412 | addRecordToLW(res, domain, QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800); | |
1413 | addRecordToLW(res, domain, QType::NS, "pdns-public-ns2.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800); | |
1414 | addRecordToLW(res, domain, QType::NS, "pdns-public-ns3.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800); | |
30ee601a | 1415 | |
d6e797b8 RG |
1416 | addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); |
1417 | addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::AAAA, "2001:DB8::1", DNSResourceRecord::ADDITIONAL, 3600); | |
1418 | addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 3600); | |
1419 | addRecordToLW(res, "pdns-public-ns2.powerdns.com.", QType::AAAA, "2001:DB8::2", DNSResourceRecord::ADDITIONAL, 3600); | |
1420 | addRecordToLW(res, "pdns-public-ns3.powerdns.com.", QType::A, "192.0.2.3", DNSResourceRecord::ADDITIONAL, 3600); | |
1421 | addRecordToLW(res, "pdns-public-ns3.powerdns.com.", QType::AAAA, "2001:DB8::3", DNSResourceRecord::ADDITIONAL, 3600); | |
30ee601a | 1422 | |
d6e797b8 RG |
1423 | return 1; |
1424 | } else { | |
1425 | nsCounts[ip]++; | |
30ee601a | 1426 | |
d6e797b8 RG |
1427 | if (ip == ComboAddress("[2001:DB8::2]:53") || ip == ComboAddress("192.0.2.2:53")) { |
1428 | BOOST_CHECK_LT(nsCounts.size(), 3); | |
1429 | ||
1430 | /* let's time out on pdns-public-ns2.powerdns.com. */ | |
1431 | return 0; | |
1432 | } | |
1433 | else if (ip == ComboAddress("192.0.2.1:53")) { | |
1434 | BOOST_CHECK_EQUAL(nsCounts.size(), 3); | |
1435 | ||
1436 | setLWResult(res, 0, true, false, true); | |
1437 | addRecordToLW(res, domain, QType::A, "192.0.2.254"); | |
1438 | return 1; | |
1439 | } | |
1440 | ||
1441 | return 0; | |
1442 | } | |
30ee601a | 1443 | |
d6e797b8 RG |
1444 | return 0; |
1445 | }); | |
30ee601a | 1446 | |
d6e797b8 RG |
1447 | struct timeval now; |
1448 | gettimeofday(&now, 0); | |
30ee601a | 1449 | |
d6e797b8 RG |
1450 | /* make pdns-public-ns2.powerdns.com. the fastest NS, with its IPv6 address faster than the IPV4 one, |
1451 | then pdns-public-ns1.powerdns.com. on IPv4 */ | |
1452 | t_sstorage->nsSpeeds[DNSName("pdns-public-ns1.powerdns.com.")].submit(ComboAddress("192.0.2.1:53"), 100, &now); | |
1453 | t_sstorage->nsSpeeds[DNSName("pdns-public-ns1.powerdns.com.")].submit(ComboAddress("[2001:DB8::1]:53"), 10000, &now); | |
1454 | t_sstorage->nsSpeeds[DNSName("pdns-public-ns2.powerdns.com.")].submit(ComboAddress("192.0.2.2:53"), 10, &now); | |
1455 | t_sstorage->nsSpeeds[DNSName("pdns-public-ns2.powerdns.com.")].submit(ComboAddress("[2001:DB8::2]:53"), 1, &now); | |
1456 | t_sstorage->nsSpeeds[DNSName("pdns-public-ns3.powerdns.com.")].submit(ComboAddress("192.0.2.3:53"), 10000, &now); | |
1457 | t_sstorage->nsSpeeds[DNSName("pdns-public-ns3.powerdns.com.")].submit(ComboAddress("[2001:DB8::3]:53"), 10000, &now); | |
30ee601a | 1458 | |
d6e797b8 RG |
1459 | vector<DNSRecord> ret; |
1460 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1461 | BOOST_CHECK_EQUAL(res, 0); | |
1462 | BOOST_CHECK_EQUAL(ret.size(), 1); | |
1463 | BOOST_CHECK_EQUAL(nsCounts.size(), 3); | |
1464 | BOOST_CHECK_EQUAL(nsCounts[ComboAddress("192.0.2.1:53")], 1); | |
1465 | BOOST_CHECK_EQUAL(nsCounts[ComboAddress("192.0.2.2:53")], 1); | |
1466 | BOOST_CHECK_EQUAL(nsCounts[ComboAddress("[2001:DB8::2]:53")], 1); | |
1467 | } | |
30ee601a | 1468 | |
d6e797b8 RG |
1469 | BOOST_AUTO_TEST_CASE(test_flawed_nsset) { |
1470 | std::unique_ptr<SyncRes> sr; | |
1471 | init(); | |
1472 | initSR(sr, true, false); | |
30ee601a | 1473 | |
d6e797b8 | 1474 | primeHints(); |
30ee601a | 1475 | |
d6e797b8 | 1476 | const DNSName target("powerdns.com."); |
30ee601a | 1477 | |
d6e797b8 RG |
1478 | sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { |
1479 | ||
1480 | if (isRootServer(ip)) { | |
1481 | setLWResult(res, 0, true, false, true); | |
1482 | addRecordToLW(res, domain, QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800); | |
1483 | ||
1484 | addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
1485 | ||
1486 | return 1; | |
1487 | } else if (ip == ComboAddress("192.0.2.1:53")) { | |
1488 | setLWResult(res, 0, true, false, true); | |
1489 | addRecordToLW(res, domain, QType::A, "192.0.2.254"); | |
1490 | return 1; | |
1491 | } | |
1492 | ||
1493 | return 0; | |
1494 | }); | |
1495 | ||
1496 | /* we populate the cache with a flawed NSset, i.e. there is a NS entry but no corresponding glue */ | |
1497 | time_t now = time(nullptr); | |
1498 | std::vector<DNSRecord> records; | |
1499 | std::vector<shared_ptr<RRSIGRecordContent> > sigs; | |
1500 | addRecordToList(records, target, QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, now + 3600); | |
1501 | ||
1502 | t_RC->replace(now, target, QType(QType::NS), records, sigs, true, boost::optional<Netmask>()); | |
1503 | ||
1504 | vector<DNSRecord> ret; | |
1505 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1506 | BOOST_CHECK_EQUAL(res, 0); | |
1507 | BOOST_CHECK_EQUAL(ret.size(), 1); | |
1508 | } | |
1509 | ||
1510 | BOOST_AUTO_TEST_CASE(test_cache_hit) { | |
1511 | std::unique_ptr<SyncRes> sr; | |
1512 | init(); | |
1513 | initSR(sr, true, false); | |
1514 | ||
1515 | primeHints(); | |
1516 | ||
1517 | const DNSName target("powerdns.com."); | |
1518 | ||
1519 | sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1520 | ||
1521 | return 0; | |
1522 | }); | |
1523 | ||
1524 | /* we populate the cache with eveything we need */ | |
1525 | time_t now = time(nullptr); | |
1526 | std::vector<DNSRecord> records; | |
1527 | std::vector<shared_ptr<RRSIGRecordContent> > sigs; | |
1528 | ||
1529 | addRecordToList(records, target, QType::A, "192.0.2.1", DNSResourceRecord::ANSWER, now + 3600); | |
1530 | t_RC->replace(now, target , QType(QType::A), records, sigs, true, boost::optional<Netmask>()); | |
1531 | ||
1532 | vector<DNSRecord> ret; | |
1533 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1534 | BOOST_CHECK_EQUAL(res, 0); | |
1535 | BOOST_CHECK_EQUAL(ret.size(), 1); | |
1536 | } | |
1537 | ||
648bcbd1 RG |
1538 | BOOST_AUTO_TEST_CASE(test_no_rd) { |
1539 | std::unique_ptr<SyncRes> sr; | |
1540 | init(); | |
1541 | initSR(sr, true, false); | |
1542 | ||
1543 | primeHints(); | |
1544 | ||
1545 | const DNSName target("powerdns.com."); | |
1546 | size_t queriesCount = 0; | |
1547 | ||
1548 | sr->setCacheOnly(); | |
1549 | ||
1550 | sr->setAsyncCallback([target,&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1551 | ||
1552 | queriesCount++; | |
1553 | return 0; | |
1554 | }); | |
1555 | ||
1556 | vector<DNSRecord> ret; | |
1557 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1558 | BOOST_CHECK_EQUAL(res, 0); | |
1559 | BOOST_CHECK_EQUAL(ret.size(), 0); | |
1560 | BOOST_CHECK_EQUAL(queriesCount, 0); | |
1561 | } | |
1562 | ||
d6e797b8 RG |
1563 | BOOST_AUTO_TEST_CASE(test_cache_min_max_ttl) { |
1564 | std::unique_ptr<SyncRes> sr; | |
1565 | init(false); | |
1566 | initSR(sr, true, false); | |
1567 | ||
1568 | primeHints(); | |
1569 | ||
1570 | const DNSName target("cachettl.powerdns.com."); | |
1571 | const ComboAddress ns("192.0.2.1:53"); | |
1572 | ||
1573 | sr->setAsyncCallback([target,ns](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1574 | ||
1575 | if (isRootServer(ip)) { | |
1576 | ||
1577 | setLWResult(res, 0, true, false, true); | |
1578 | addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
1579 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 7200); | |
1580 | return 1; | |
1581 | } else if (ip == ns) { | |
1582 | ||
1583 | setLWResult(res, 0, true, false, false); | |
1584 | addRecordToLW(res, domain, QType::A, "192.0.2.2", DNSResourceRecord::ANSWER, 10); | |
1585 | ||
1586 | return 1; | |
1587 | } | |
1588 | ||
1589 | return 0; | |
1590 | }); | |
1591 | ||
1592 | SyncRes::s_minimumTTL = 60; | |
1593 | SyncRes::s_maxcachettl = 3600; | |
1594 | ||
1595 | vector<DNSRecord> ret; | |
1596 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1597 | BOOST_CHECK_EQUAL(res, 0); | |
1598 | BOOST_REQUIRE_EQUAL(ret.size(), 1); | |
1599 | BOOST_CHECK_EQUAL(ret[0].d_ttl, SyncRes::s_minimumTTL); | |
1600 | ||
1601 | const ComboAddress who; | |
1602 | vector<DNSRecord> cached; | |
1603 | const time_t now = time(nullptr); | |
1604 | BOOST_REQUIRE_GT(t_RC->get(now, target, QType(QType::A), &cached, who), 0); | |
1605 | BOOST_REQUIRE_EQUAL(cached.size(), 1); | |
1606 | BOOST_REQUIRE_GT(cached[0].d_ttl, now); | |
1607 | BOOST_CHECK_EQUAL((cached[0].d_ttl - now), SyncRes::s_minimumTTL); | |
1608 | ||
1609 | cached.clear(); | |
1610 | BOOST_REQUIRE_GT(t_RC->get(now, target, QType(QType::NS), &cached, who), 0); | |
1611 | BOOST_REQUIRE_EQUAL(cached.size(), 1); | |
1612 | BOOST_REQUIRE_GT(cached[0].d_ttl, now); | |
1613 | BOOST_CHECK_LE((cached[0].d_ttl - now), SyncRes::s_maxcachettl); | |
1614 | } | |
1615 | ||
1616 | BOOST_AUTO_TEST_CASE(test_cache_expired_ttl) { | |
1617 | std::unique_ptr<SyncRes> sr; | |
1618 | init(false); | |
1619 | initSR(sr, true, false); | |
1620 | ||
1621 | primeHints(); | |
1622 | ||
1623 | const DNSName target("powerdns.com."); | |
1624 | ||
1625 | sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1626 | ||
1627 | if (isRootServer(ip)) { | |
1628 | setLWResult(res, 0, true, false, true); | |
1629 | addRecordToLW(res, domain, QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800); | |
1630 | ||
1631 | addRecordToLW(res, "pdns-public-ns1.powerdns.com.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
1632 | ||
1633 | return 1; | |
1634 | } else if (ip == ComboAddress("192.0.2.1:53")) { | |
1635 | setLWResult(res, 0, true, false, true); | |
1636 | addRecordToLW(res, domain, QType::A, "192.0.2.2"); | |
1637 | return 1; | |
1638 | } | |
1639 | ||
1640 | return 0; | |
1641 | }); | |
1642 | ||
1643 | /* we populate the cache with entries that expired 60s ago*/ | |
1644 | time_t now = time(nullptr); | |
1645 | std::vector<DNSRecord> records; | |
1646 | std::vector<shared_ptr<RRSIGRecordContent> > sigs; | |
1647 | addRecordToList(records, target, QType::A, "192.0.2.42", DNSResourceRecord::ANSWER, now - 60); | |
1648 | ||
1649 | t_RC->replace(now - 3600, target, QType(QType::A), records, sigs, true, boost::optional<Netmask>()); | |
1650 | ||
1651 | vector<DNSRecord> ret; | |
1652 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1653 | BOOST_CHECK_EQUAL(res, 0); | |
1654 | BOOST_REQUIRE_EQUAL(ret.size(), 1); | |
1655 | BOOST_REQUIRE(ret[0].d_type == QType::A); | |
1656 | BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toStringWithPort(), ComboAddress("192.0.2.2").toStringWithPort()); | |
1657 | } | |
1658 | ||
1659 | BOOST_AUTO_TEST_CASE(test_delegation_only) { | |
1660 | std::unique_ptr<SyncRes> sr; | |
1661 | init(); | |
1662 | initSR(sr, true, false); | |
1663 | ||
1664 | primeHints(); | |
1665 | ||
1666 | /* Thanks, Verisign */ | |
1667 | g_delegationOnly.insert(DNSName("com.")); | |
1668 | g_delegationOnly.insert(DNSName("net.")); | |
1669 | ||
1670 | const DNSName target("nx-powerdns.com."); | |
1671 | ||
1672 | sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1673 | ||
1674 | if (isRootServer(ip)) { | |
1675 | setLWResult(res, 0, true, false, true); | |
1676 | addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
1677 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
1678 | return 1; | |
1679 | } else if (ip == ComboAddress("192.0.2.1:53")) { | |
1680 | ||
1681 | setLWResult(res, 0, true, false, true); | |
1682 | addRecordToLW(res, domain, QType::A, "192.0.2.42"); | |
1683 | return 1; | |
1684 | } | |
1685 | ||
1686 | return 0; | |
1687 | }); | |
1688 | ||
1689 | vector<DNSRecord> ret; | |
1690 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1691 | BOOST_CHECK_EQUAL(res, RCode::NXDomain); | |
1692 | BOOST_CHECK_EQUAL(ret.size(), 0); | |
1693 | } | |
1694 | ||
1695 | BOOST_AUTO_TEST_CASE(test_unauth_any) { | |
1696 | std::unique_ptr<SyncRes> sr; | |
1697 | init(); | |
1698 | initSR(sr, true, false); | |
1699 | ||
1700 | primeHints(); | |
1701 | ||
1702 | const DNSName target("powerdns.com."); | |
1703 | ||
1704 | sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1705 | ||
1706 | if (isRootServer(ip)) { | |
1707 | setLWResult(res, 0, true, false, true); | |
1708 | addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
1709 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600); | |
1710 | return 1; | |
1711 | } else if (ip == ComboAddress("192.0.2.1:53")) { | |
1712 | ||
1713 | setLWResult(res, 0, false, false, true); | |
1714 | addRecordToLW(res, domain, QType::A, "192.0.2.42"); | |
1715 | return 1; | |
1716 | } | |
1717 | ||
1718 | return 0; | |
1719 | }); | |
1720 | ||
1721 | vector<DNSRecord> ret; | |
1722 | int res = sr->beginResolve(target, QType(QType::ANY), QClass::IN, ret); | |
1723 | BOOST_CHECK_EQUAL(res, RCode::ServFail); | |
1724 | BOOST_CHECK_EQUAL(ret.size(), 0); | |
1725 | } | |
1726 | ||
1727 | BOOST_AUTO_TEST_CASE(test_no_data) { | |
1728 | std::unique_ptr<SyncRes> sr; | |
1729 | init(); | |
1730 | initSR(sr, true, false); | |
1731 | ||
1732 | primeHints(); | |
1733 | ||
1734 | const DNSName target("powerdns.com."); | |
1735 | ||
1736 | sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1737 | ||
1738 | setLWResult(res, 0, true, false, true); | |
1739 | return 1; | |
1740 | }); | |
1741 | ||
1742 | vector<DNSRecord> ret; | |
1743 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1744 | BOOST_CHECK_EQUAL(res, 0); | |
1745 | BOOST_CHECK_EQUAL(ret.size(), 0); | |
1746 | } | |
1747 | ||
1748 | BOOST_AUTO_TEST_CASE(test_skip_opt_any) { | |
1749 | std::unique_ptr<SyncRes> sr; | |
1750 | init(); | |
1751 | initSR(sr, true, false); | |
1752 | ||
1753 | primeHints(); | |
1754 | ||
1755 | const DNSName target("powerdns.com."); | |
1756 | ||
1757 | sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1758 | ||
1759 | setLWResult(res, 0, true, false, true); | |
1760 | addRecordToLW(res, domain, QType::A, "192.0.2.42"); | |
1761 | addRecordToLW(res, domain, QType::ANY, "0 0"); | |
1762 | addRecordToLW(res, domain, QType::OPT, ""); | |
1763 | return 1; | |
1764 | }); | |
1765 | ||
1766 | vector<DNSRecord> ret; | |
1767 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1768 | BOOST_CHECK_EQUAL(res, 0); | |
1769 | BOOST_CHECK_EQUAL(ret.size(), 1); | |
1770 | } | |
1771 | ||
1772 | BOOST_AUTO_TEST_CASE(test_nodata_nsec_nodnssec) { | |
1773 | std::unique_ptr<SyncRes> sr; | |
1774 | init(); | |
1775 | initSR(sr, true, false); | |
1776 | ||
1777 | primeHints(); | |
1778 | ||
1779 | const DNSName target("powerdns.com."); | |
1780 | ||
1781 | sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1782 | ||
1783 | setLWResult(res, 0, true, false, true); | |
1784 | addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600); | |
1785 | /* the NSEC and RRSIG contents are complete garbage, please ignore them */ | |
1786 | addRecordToLW(res, domain, QType::NSEC, "deadbeef", DNSResourceRecord::AUTHORITY); | |
1787 | addRecordToLW(res, domain, QType::RRSIG, "NSEC 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY); | |
1788 | addRecordToLW(res, domain, QType::RRSIG, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY); | |
1789 | return 1; | |
1790 | }); | |
1791 | ||
1792 | vector<DNSRecord> ret; | |
1793 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1794 | BOOST_CHECK_EQUAL(res, 0); | |
1795 | BOOST_CHECK_EQUAL(ret.size(), 1); | |
1796 | } | |
1797 | ||
1798 | BOOST_AUTO_TEST_CASE(test_nodata_nsec_dnssec) { | |
1799 | std::unique_ptr<SyncRes> sr; | |
1800 | init(); | |
1801 | initSR(sr, true, true); | |
1802 | ||
1803 | primeHints(); | |
1804 | ||
1805 | const DNSName target("powerdns.com."); | |
1806 | ||
1807 | sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1808 | ||
1809 | setLWResult(res, 0, true, false, true); | |
1810 | addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600); | |
1811 | /* the NSEC and RRSIG contents are complete garbage, please ignore them */ | |
1812 | addRecordToLW(res, domain, QType::NSEC, "deadbeef", DNSResourceRecord::AUTHORITY); | |
1813 | addRecordToLW(res, domain, QType::RRSIG, "NSEC 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY); | |
1814 | addRecordToLW(res, domain, QType::RRSIG, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY); | |
1815 | return 1; | |
1816 | }); | |
1817 | ||
1818 | vector<DNSRecord> ret; | |
1819 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1820 | BOOST_CHECK_EQUAL(res, 0); | |
1821 | BOOST_CHECK_EQUAL(ret.size(), 4); | |
1822 | } | |
1823 | ||
1824 | BOOST_AUTO_TEST_CASE(test_nx_nsec_nodnssec) { | |
1825 | std::unique_ptr<SyncRes> sr; | |
1826 | init(); | |
1827 | initSR(sr, true, false); | |
1828 | ||
1829 | primeHints(); | |
1830 | ||
1831 | const DNSName target("powerdns.com."); | |
1832 | ||
1833 | sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1834 | ||
1835 | setLWResult(res, RCode::NXDomain, true, false, true); | |
1836 | addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600); | |
1837 | /* the NSEC and RRSIG contents are complete garbage, please ignore them */ | |
1838 | addRecordToLW(res, domain, QType::NSEC, "deadbeef", DNSResourceRecord::AUTHORITY); | |
1839 | addRecordToLW(res, domain, QType::RRSIG, "NSEC 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY); | |
1840 | addRecordToLW(res, domain, QType::RRSIG, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY); | |
1841 | return 1; | |
1842 | }); | |
1843 | ||
1844 | vector<DNSRecord> ret; | |
1845 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1846 | BOOST_CHECK_EQUAL(res, RCode::NXDomain); | |
1847 | BOOST_CHECK_EQUAL(ret.size(), 1); | |
1848 | } | |
1849 | ||
1850 | BOOST_AUTO_TEST_CASE(test_nx_nsec_dnssec) { | |
1851 | std::unique_ptr<SyncRes> sr; | |
1852 | init(); | |
1853 | initSR(sr, true, true); | |
1854 | ||
1855 | primeHints(); | |
1856 | ||
1857 | const DNSName target("powerdns.com."); | |
1858 | ||
1859 | sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1860 | ||
1861 | setLWResult(res, RCode::NXDomain, true, false, true); | |
1862 | addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600); | |
1863 | /* the NSEC and RRSIG contents are complete garbage, please ignore them */ | |
1864 | addRecordToLW(res, domain, QType::NSEC, "deadbeef", DNSResourceRecord::AUTHORITY); | |
1865 | addRecordToLW(res, domain, QType::RRSIG, "NSEC 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY); | |
1866 | addRecordToLW(res, domain, QType::RRSIG, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY); | |
1867 | return 1; | |
1868 | }); | |
1869 | ||
1870 | vector<DNSRecord> ret; | |
1871 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
1872 | BOOST_CHECK_EQUAL(res, RCode::NXDomain); | |
1873 | BOOST_CHECK_EQUAL(ret.size(), 4); | |
1874 | } | |
1875 | ||
648bcbd1 RG |
1876 | BOOST_AUTO_TEST_CASE(test_qclass_none) { |
1877 | std::unique_ptr<SyncRes> sr; | |
1878 | init(); | |
1879 | initSR(sr, true, true); | |
1880 | ||
1881 | primeHints(); | |
1882 | ||
1883 | /* apart from special names and QClass::ANY, anything else than QClass::IN should be rejected right away */ | |
1884 | size_t queriesCount = 0; | |
1885 | ||
1886 | sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1887 | ||
1888 | queriesCount++; | |
1889 | return 0; | |
1890 | }); | |
1891 | ||
1892 | const DNSName target("powerdns.com."); | |
1893 | vector<DNSRecord> ret; | |
1894 | int res = sr->beginResolve(target, QType(QType::A), QClass::NONE, ret); | |
1895 | BOOST_CHECK_EQUAL(res, -1); | |
1896 | BOOST_CHECK_EQUAL(ret.size(), 0); | |
1897 | BOOST_CHECK_EQUAL(queriesCount, 0); | |
1898 | } | |
1899 | ||
1900 | BOOST_AUTO_TEST_CASE(test_xfr) { | |
1901 | std::unique_ptr<SyncRes> sr; | |
1902 | init(); | |
1903 | initSR(sr, true, true); | |
1904 | ||
1905 | primeHints(); | |
1906 | ||
1907 | /* {A,I}XFR should be rejected right away */ | |
1908 | size_t queriesCount = 0; | |
1909 | ||
1910 | sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1911 | ||
1912 | cerr<<"asyncresolve called to ask "<<ip.toStringWithPort()<<" about "<<domain.toString()<<" / "<<QType(type).getName()<<" over "<<(doTCP ? "TCP" : "UDP")<<" (rd: "<<sendRDQuery<<", EDNS0 level: "<<EDNS0Level<<")"<<endl; | |
1913 | queriesCount++; | |
1914 | return 0; | |
1915 | }); | |
1916 | ||
1917 | const DNSName target("powerdns.com."); | |
1918 | vector<DNSRecord> ret; | |
1919 | int res = sr->beginResolve(target, QType(QType::AXFR), QClass::IN, ret); | |
1920 | BOOST_CHECK_EQUAL(res, -1); | |
1921 | BOOST_CHECK_EQUAL(ret.size(), 0); | |
1922 | BOOST_CHECK_EQUAL(queriesCount, 0); | |
1923 | ||
1924 | res = sr->beginResolve(target, QType(QType::IXFR), QClass::IN, ret); | |
1925 | BOOST_CHECK_EQUAL(res, -1); | |
1926 | BOOST_CHECK_EQUAL(ret.size(), 0); | |
1927 | BOOST_CHECK_EQUAL(queriesCount, 0); | |
1928 | } | |
1929 | ||
1930 | BOOST_AUTO_TEST_CASE(test_special_names) { | |
1931 | std::unique_ptr<SyncRes> sr; | |
1932 | init(); | |
1933 | initSR(sr, true, true); | |
1934 | ||
1935 | primeHints(); | |
1936 | ||
1937 | /* special names should be handled internally */ | |
1938 | ||
1939 | size_t queriesCount = 0; | |
1940 | ||
1941 | sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
1942 | ||
1943 | queriesCount++; | |
1944 | return 0; | |
1945 | }); | |
1946 | ||
1947 | vector<DNSRecord> ret; | |
1948 | int res = sr->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::PTR), QClass::IN, ret); | |
1949 | BOOST_CHECK_EQUAL(res, 0); | |
1950 | BOOST_REQUIRE_EQUAL(ret.size(), 1); | |
1951 | BOOST_CHECK(ret[0].d_type == QType::PTR); | |
1952 | BOOST_CHECK_EQUAL(queriesCount, 0); | |
1953 | ||
1954 | ret.clear(); | |
1955 | res = sr->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::ANY), QClass::IN, ret); | |
1956 | BOOST_CHECK_EQUAL(res, 0); | |
1957 | BOOST_REQUIRE_EQUAL(ret.size(), 1); | |
1958 | BOOST_CHECK(ret[0].d_type == QType::PTR); | |
1959 | BOOST_CHECK_EQUAL(queriesCount, 0); | |
1960 | ||
1961 | ret.clear(); | |
1962 | res = sr->beginResolve(DNSName("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa."), QType(QType::PTR), QClass::IN, ret); | |
1963 | BOOST_CHECK_EQUAL(res, 0); | |
1964 | BOOST_REQUIRE_EQUAL(ret.size(), 1); | |
1965 | BOOST_CHECK(ret[0].d_type == QType::PTR); | |
1966 | BOOST_CHECK_EQUAL(queriesCount, 0); | |
1967 | ||
1968 | ret.clear(); | |
1969 | res = sr->beginResolve(DNSName("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa."), QType(QType::ANY), QClass::IN, ret); | |
1970 | BOOST_CHECK_EQUAL(res, 0); | |
1971 | BOOST_REQUIRE_EQUAL(ret.size(), 1); | |
1972 | BOOST_CHECK(ret[0].d_type == QType::PTR); | |
1973 | BOOST_CHECK_EQUAL(queriesCount, 0); | |
1974 | ||
1975 | ret.clear(); | |
1976 | res = sr->beginResolve(DNSName("localhost."), QType(QType::A), QClass::IN, ret); | |
1977 | BOOST_CHECK_EQUAL(res, 0); | |
1978 | BOOST_REQUIRE_EQUAL(ret.size(), 1); | |
1979 | BOOST_CHECK(ret[0].d_type == QType::A); | |
1980 | BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toString(), "127.0.0.1"); | |
1981 | BOOST_CHECK_EQUAL(queriesCount, 0); | |
1982 | ||
1983 | ret.clear(); | |
1984 | res = sr->beginResolve(DNSName("localhost."), QType(QType::AAAA), QClass::IN, ret); | |
1985 | BOOST_CHECK_EQUAL(res, 0); | |
1986 | BOOST_REQUIRE_EQUAL(ret.size(), 1); | |
1987 | BOOST_CHECK(ret[0].d_type == QType::AAAA); | |
1988 | BOOST_CHECK_EQUAL(getRR<AAAARecordContent>(ret[0])->getCA().toString(), "::1"); | |
1989 | BOOST_CHECK_EQUAL(queriesCount, 0); | |
1990 | ||
1991 | ret.clear(); | |
1992 | res = sr->beginResolve(DNSName("localhost."), QType(QType::ANY), QClass::IN, ret); | |
1993 | BOOST_CHECK_EQUAL(res, 0); | |
1994 | BOOST_REQUIRE_EQUAL(ret.size(), 2); | |
1995 | for (const auto& rec : ret) { | |
1996 | BOOST_REQUIRE((rec.d_type == QType::A) || rec.d_type == QType::AAAA); | |
1997 | if (rec.d_type == QType::A) { | |
1998 | BOOST_CHECK_EQUAL(getRR<ARecordContent>(rec)->getCA().toString(), "127.0.0.1"); | |
1999 | } | |
2000 | else { | |
2001 | BOOST_CHECK_EQUAL(getRR<AAAARecordContent>(rec)->getCA().toString(), "::1"); | |
2002 | } | |
2003 | } | |
2004 | BOOST_CHECK_EQUAL(queriesCount, 0); | |
2005 | ||
2006 | ret.clear(); | |
2007 | res = sr->beginResolve(DNSName("version.bind."), QType(QType::TXT), QClass::CHAOS, ret); | |
2008 | BOOST_CHECK_EQUAL(res, 0); | |
2009 | BOOST_REQUIRE_EQUAL(ret.size(), 1); | |
2010 | BOOST_CHECK(ret[0].d_type == QType::TXT); | |
2011 | BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests\""); | |
2012 | BOOST_CHECK_EQUAL(queriesCount, 0); | |
2013 | ||
2014 | ret.clear(); | |
2015 | res = sr->beginResolve(DNSName("version.bind."), QType(QType::ANY), QClass::CHAOS, ret); | |
2016 | BOOST_CHECK_EQUAL(res, 0); | |
2017 | BOOST_REQUIRE_EQUAL(ret.size(), 1); | |
2018 | BOOST_CHECK(ret[0].d_type == QType::TXT); | |
2019 | BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests\""); | |
2020 | BOOST_CHECK_EQUAL(queriesCount, 0); | |
2021 | ||
2022 | ret.clear(); | |
2023 | res = sr->beginResolve(DNSName("version.pdns."), QType(QType::TXT), QClass::CHAOS, ret); | |
2024 | BOOST_CHECK_EQUAL(res, 0); | |
2025 | BOOST_REQUIRE_EQUAL(ret.size(), 1); | |
2026 | BOOST_CHECK(ret[0].d_type == QType::TXT); | |
2027 | BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests\""); | |
2028 | BOOST_CHECK_EQUAL(queriesCount, 0); | |
2029 | ||
2030 | ret.clear(); | |
2031 | res = sr->beginResolve(DNSName("version.pdns."), QType(QType::ANY), QClass::CHAOS, ret); | |
2032 | BOOST_CHECK_EQUAL(res, 0); | |
2033 | BOOST_REQUIRE_EQUAL(ret.size(), 1); | |
2034 | BOOST_CHECK(ret[0].d_type == QType::TXT); | |
2035 | BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests\""); | |
2036 | BOOST_CHECK_EQUAL(queriesCount, 0); | |
2037 | ||
2038 | ret.clear(); | |
2039 | res = sr->beginResolve(DNSName("id.server."), QType(QType::TXT), QClass::CHAOS, ret); | |
2040 | BOOST_CHECK_EQUAL(res, 0); | |
2041 | BOOST_REQUIRE_EQUAL(ret.size(), 1); | |
2042 | BOOST_CHECK(ret[0].d_type == QType::TXT); | |
2043 | BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests Server ID\""); | |
2044 | BOOST_CHECK_EQUAL(queriesCount, 0); | |
2045 | ||
2046 | ret.clear(); | |
2047 | res = sr->beginResolve(DNSName("id.server."), QType(QType::ANY), QClass::CHAOS, ret); | |
2048 | BOOST_CHECK_EQUAL(res, 0); | |
2049 | BOOST_REQUIRE_EQUAL(ret.size(), 1); | |
2050 | BOOST_CHECK(ret[0].d_type == QType::TXT); | |
2051 | BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests Server ID\""); | |
2052 | BOOST_CHECK_EQUAL(queriesCount, 0); | |
2053 | } | |
2054 | ||
2055 | BOOST_AUTO_TEST_CASE(test_nameserver_ipv4_rpz) { | |
2056 | std::unique_ptr<SyncRes> sr; | |
2057 | init(); | |
2058 | initSR(sr, true, false); | |
2059 | ||
2060 | primeHints(); | |
2061 | ||
2062 | const DNSName target("rpz.powerdns.com."); | |
2063 | const ComboAddress ns("192.0.2.1:53"); | |
2064 | ||
2065 | sr->setAsyncCallback([target,ns](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
2066 | ||
2067 | if (isRootServer(ip)) { | |
2068 | setLWResult(res, 0, true, false, true); | |
2069 | addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
2070 | addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600); | |
2071 | return 1; | |
2072 | } else if (ip == ns) { | |
2073 | ||
2074 | setLWResult(res, 0, true, false, true); | |
2075 | addRecordToLW(res, domain, QType::A, "192.0.2.42"); | |
2076 | return 1; | |
2077 | } | |
2078 | ||
2079 | return 0; | |
2080 | }); | |
2081 | ||
2082 | DNSFilterEngine::Policy pol; | |
2083 | pol.d_kind = DNSFilterEngine::PolicyKind::Drop; | |
2084 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
2085 | luaconfsCopy.dfe.setPolicyName(0, "Unit test policy 0"); | |
2086 | luaconfsCopy.dfe.addNSIPTrigger(Netmask(ns, 32), pol, 0); | |
2087 | g_luaconfs.setState(luaconfsCopy); | |
2088 | ||
2089 | vector<DNSRecord> ret; | |
2090 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
2091 | BOOST_CHECK_EQUAL(res, -2); | |
2092 | BOOST_CHECK_EQUAL(ret.size(), 0); | |
2093 | } | |
2094 | ||
2095 | BOOST_AUTO_TEST_CASE(test_nameserver_ipv6_rpz) { | |
2096 | std::unique_ptr<SyncRes> sr; | |
2097 | init(); | |
2098 | initSR(sr, true, false); | |
2099 | ||
2100 | primeHints(); | |
2101 | ||
2102 | const DNSName target("rpz.powerdns.com."); | |
2103 | const ComboAddress ns("[2001:DB8::42]:53"); | |
2104 | ||
2105 | sr->setAsyncCallback([target,ns](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
2106 | ||
2107 | if (isRootServer(ip)) { | |
2108 | setLWResult(res, 0, true, false, true); | |
2109 | addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800); | |
2110 | addRecordToLW(res, "a.gtld-servers.net.", QType::AAAA, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600); | |
2111 | return 1; | |
2112 | } else if (ip == ns) { | |
2113 | ||
2114 | setLWResult(res, 0, true, false, true); | |
2115 | addRecordToLW(res, domain, QType::A, "192.0.2.42"); | |
2116 | return 1; | |
2117 | } | |
2118 | ||
2119 | return 0; | |
2120 | }); | |
2121 | ||
2122 | DNSFilterEngine::Policy pol; | |
2123 | pol.d_kind = DNSFilterEngine::PolicyKind::Drop; | |
2124 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
2125 | luaconfsCopy.dfe.setPolicyName(0, "Unit test policy 0"); | |
2126 | luaconfsCopy.dfe.addNSIPTrigger(Netmask(ns, 128), pol, 0); | |
2127 | g_luaconfs.setState(luaconfsCopy); | |
2128 | ||
2129 | vector<DNSRecord> ret; | |
2130 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
2131 | BOOST_CHECK_EQUAL(res, -2); | |
2132 | BOOST_CHECK_EQUAL(ret.size(), 0); | |
2133 | } | |
2134 | ||
2135 | BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz) { | |
2136 | std::unique_ptr<SyncRes> sr; | |
2137 | init(); | |
2138 | initSR(sr, true, false); | |
2139 | ||
2140 | primeHints(); | |
2141 | ||
2142 | const DNSName target("rpz.powerdns.com."); | |
2143 | const ComboAddress ns("192.0.2.1:53"); | |
2144 | const DNSName nsName("ns1.powerdns.com."); | |
2145 | ||
2146 | sr->setAsyncCallback([target,ns,nsName](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
2147 | ||
2148 | if (isRootServer(ip)) { | |
2149 | setLWResult(res, 0, true, false, true); | |
2150 | addRecordToLW(res, domain, QType::NS, nsName.toString(), DNSResourceRecord::AUTHORITY, 172800); | |
2151 | addRecordToLW(res, nsName, QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600); | |
2152 | return 1; | |
2153 | } else if (ip == ns) { | |
2154 | ||
2155 | setLWResult(res, 0, true, false, true); | |
2156 | addRecordToLW(res, domain, QType::A, "192.0.2.42"); | |
2157 | return 1; | |
2158 | } | |
2159 | ||
2160 | return 0; | |
2161 | }); | |
2162 | ||
2163 | DNSFilterEngine::Policy pol; | |
2164 | pol.d_kind = DNSFilterEngine::PolicyKind::Drop; | |
2165 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
2166 | luaconfsCopy.dfe.setPolicyName(0, "Unit test policy 0"); | |
2167 | luaconfsCopy.dfe.addNSTrigger(nsName, pol, 0); | |
2168 | g_luaconfs.setState(luaconfsCopy); | |
2169 | ||
2170 | vector<DNSRecord> ret; | |
2171 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
2172 | BOOST_CHECK_EQUAL(res, -2); | |
2173 | BOOST_CHECK_EQUAL(ret.size(), 0); | |
2174 | } | |
2175 | ||
2176 | BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz_disabled) { | |
2177 | std::unique_ptr<SyncRes> sr; | |
2178 | init(); | |
2179 | initSR(sr, true, false); | |
2180 | ||
2181 | primeHints(); | |
2182 | ||
2183 | const DNSName target("rpz.powerdns.com."); | |
2184 | const ComboAddress ns("192.0.2.1:53"); | |
2185 | const DNSName nsName("ns1.powerdns.com."); | |
2186 | ||
2187 | sr->setAsyncCallback([target,ns,nsName](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, std::shared_ptr<RemoteLogger> outgoingLogger, LWResult* res) { | |
2188 | ||
2189 | if (isRootServer(ip)) { | |
2190 | setLWResult(res, 0, true, false, true); | |
2191 | addRecordToLW(res, domain, QType::NS, nsName.toString(), DNSResourceRecord::AUTHORITY, 172800); | |
2192 | addRecordToLW(res, nsName, QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600); | |
2193 | return 1; | |
2194 | } else if (ip == ns) { | |
2195 | ||
2196 | setLWResult(res, 0, true, false, true); | |
2197 | addRecordToLW(res, domain, QType::A, "192.0.2.42"); | |
2198 | return 1; | |
2199 | } | |
2200 | ||
2201 | return 0; | |
2202 | }); | |
2203 | ||
2204 | DNSFilterEngine::Policy pol; | |
2205 | pol.d_kind = DNSFilterEngine::PolicyKind::Drop; | |
2206 | auto luaconfsCopy = g_luaconfs.getCopy(); | |
2207 | luaconfsCopy.dfe.setPolicyName(0, "Unit test policy 0"); | |
2208 | luaconfsCopy.dfe.addNSIPTrigger(Netmask(ns, 128), pol, 0); | |
2209 | luaconfsCopy.dfe.addNSTrigger(nsName, pol, 0); | |
2210 | g_luaconfs.setState(luaconfsCopy); | |
2211 | ||
2212 | /* RPZ is disabled for this query, we should not be blocked */ | |
2213 | sr->setWantsRPZ(false); | |
2214 | ||
2215 | vector<DNSRecord> ret; | |
2216 | int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret); | |
2217 | BOOST_CHECK_EQUAL(res, 0); | |
2218 | BOOST_CHECK_EQUAL(ret.size(), 1); | |
2219 | } | |
2220 | ||
d6e797b8 RG |
2221 | /* |
2222 | // cerr<<"asyncresolve called to ask "<<ip.toStringWithPort()<<" about "<<domain.toString()<<" / "<<QType(type).getName()<<" over "<<(doTCP ? "TCP" : "UDP")<<" (rd: "<<sendRDQuery<<", EDNS0 level: "<<EDNS0Level<<")"<<endl; | |
2223 | ||
648bcbd1 | 2224 | - check out of band support |
d6e797b8 | 2225 | |
648bcbd1 | 2226 | - check preoutquery |
d6e797b8 | 2227 | |
30ee601a RG |
2228 | */ |
2229 | ||
2230 | BOOST_AUTO_TEST_SUITE_END() |