]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/recursordist/test-syncres_cc.cc
rec: Fix cache-only queries against a forward-zone
[thirdparty/pdns.git] / pdns / recursordist / test-syncres_cc.cc
CommitLineData
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
13std::unordered_set<DNSName> g_delegationOnly;
14RecursorStats g_stats;
15GlobalStateHolder<LuaConfigItems> g_luaconfs;
16NetmaskGroup* g_dontQuery{nullptr};
17__thread MemRecursorCache* t_RC{nullptr};
18SyncRes::domainmap_t* g_initialDomainMap{nullptr};
19unsigned int g_numThreads = 1;
20
21/* Fake some required functions we didn't want the trouble to
22 link with */
23ArgvMap &arg()
24{
25 static ArgvMap theArg;
26 return theArg;
27}
28
29int getMTaskerTID()
30{
31 return 0;
32}
33
34bool 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
39int 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
52void 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
89LuaConfigItems::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
99static 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 151static 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
175static 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 183static 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
213static 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
218static 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
223static 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
228static 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
246BOOST_AUTO_TEST_SUITE(syncres_cc)
247
248BOOST_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
262BOOST_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
293BOOST_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
320BOOST_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
362BOOST_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
399BOOST_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
426BOOST_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
473BOOST_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
521BOOST_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
577BOOST_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
627BOOST_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
696BOOST_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
724BOOST_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
770BOOST_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
815BOOST_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
869BOOST_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
910BOOST_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
947BOOST_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
992BOOST_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
1052BOOST_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
1095BOOST_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
1138BOOST_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
1159BOOST_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
1179BOOST_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
1222BOOST_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
1280BOOST_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
1340BOOST_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
1397BOOST_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
1469BOOST_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
1510BOOST_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
1538BOOST_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
1563BOOST_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
1616BOOST_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
1659BOOST_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
1695BOOST_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
1727BOOST_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
1748BOOST_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
1772BOOST_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
1798BOOST_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
1824BOOST_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
1850BOOST_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
1876BOOST_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
1900BOOST_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
1930BOOST_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
2055BOOST_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
2095BOOST_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
2135BOOST_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
2176BOOST_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
2230BOOST_AUTO_TEST_SUITE_END()