]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/recursordist/test-syncres_cc.cc
Merge pull request #13481 from berthubert/lua-localwho
[thirdparty/pdns.git] / pdns / recursordist / test-syncres_cc.cc
1 #ifndef BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_DYN_LINK
3 #endif
4
5 #include <boost/test/unit_test.hpp>
6
7 #include "aggressive_nsec.hh"
8 #include "base32.hh"
9 #include "lua-recursor4.hh"
10 #include "root-dnssec.hh"
11 #include "rec-taskqueue.hh"
12 #include "test-syncres_cc.hh"
13 #include "recpacketcache.hh"
14
15 GlobalStateHolder<LuaConfigItems> g_luaconfs;
16 GlobalStateHolder<SuffixMatchNode> g_xdnssec;
17 GlobalStateHolder<SuffixMatchNode> g_dontThrottleNames;
18 GlobalStateHolder<NetmaskGroup> g_dontThrottleNetmasks;
19 GlobalStateHolder<SuffixMatchNode> g_DoTToAuthNames;
20 std::unique_ptr<MemRecursorCache> g_recCache;
21 std::unique_ptr<NegCache> g_negCache;
22 bool g_lowercaseOutgoing = false;
23 #if 0
24 pdns::TaskQueue g_test_tasks;
25 pdns::TaskQueue g_resolve_tasks;
26 #endif
27 /* Fake some required functions we didn't want the trouble to
28 link with */
29 ArgvMap& arg()
30 {
31 static ArgvMap theArg;
32 return theArg;
33 }
34
35 BaseLua4::~BaseLua4()
36 {
37 }
38
39 void BaseLua4::getFeatures(Features& /* features */)
40 {
41 }
42
43 bool RecursorLua4::preoutquery(const ComboAddress& /* ns */, const ComboAddress& /* requestor */, const DNSName& /* query */, const QType& /* qtype */, bool /* isTcp */, vector<DNSRecord>& /* res */, int& /* ret */, RecEventTrace& /* et */, const struct timeval& /* tv */) const
44 {
45 return false;
46 }
47
48 bool RecursorLua4::policyHitEventFilter(const ComboAddress& /* remote */, const DNSName& /* qname */, const QType& /* qtype */, bool /* tcp */, DNSFilterEngine::Policy& /* policy */, std::unordered_set<std::string>& /* tags */, std::unordered_map<std::string, bool>& /* discardedPolicies */) const
49 {
50 return false;
51 }
52
53 RecursorLua4::~RecursorLua4()
54 {
55 }
56
57 void RecursorLua4::postPrepareContext()
58 {
59 }
60
61 void RecursorLua4::postLoad()
62 {
63 }
64
65 void RecursorLua4::getFeatures(Features& /* features */)
66 {
67 }
68
69 LWResult::Result 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 */, const std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>>& /* outgoingLoggers */, const std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>>& /* fstrmLoggers */, const std::set<uint16_t>& /* exportTypes */, LWResult* /* res */, bool* /* chained */)
70 {
71 return LWResult::Result::Timeout;
72 }
73
74 /* primeHints() is only here for now because it
75 was way too much trouble to link with the real one.
76 We should fix this, empty functions are one thing, but this is
77 bad.
78 */
79
80 #include "root-addresses.hh"
81
82 bool primeHints(time_t now)
83 {
84 vector<DNSRecord> nsset;
85 if (!g_recCache)
86 g_recCache = std::make_unique<MemRecursorCache>();
87 if (!g_negCache)
88 g_negCache = std::make_unique<NegCache>();
89
90 DNSRecord arr, aaaarr, nsrr;
91 nsrr.d_name = g_rootdnsname;
92 arr.d_type = QType::A;
93 aaaarr.d_type = QType::AAAA;
94 nsrr.d_type = QType::NS;
95 arr.d_ttl = aaaarr.d_ttl = nsrr.d_ttl = now + 3600000;
96
97 for (char c = 'a'; c <= 'm'; ++c) {
98 char templ[40];
99 strncpy(templ, "a.root-servers.net.", sizeof(templ) - 1);
100 templ[sizeof(templ) - 1] = '\0';
101 *templ = c;
102 aaaarr.d_name = arr.d_name = DNSName(templ);
103 nsrr.setContent(std::make_shared<NSRecordContent>(DNSName(templ)));
104 arr.setContent(std::make_shared<ARecordContent>(ComboAddress(rootIps4[c - 'a'])));
105 vector<DNSRecord> aset;
106 aset.push_back(arr);
107 g_recCache->replace(now, DNSName(templ), QType(QType::A), aset, vector<std::shared_ptr<const RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), false, g_rootdnsname);
108 if (!rootIps6[c - 'a'].empty()) {
109 aaaarr.setContent(std::make_shared<AAAARecordContent>(ComboAddress(rootIps6[c - 'a'])));
110
111 vector<DNSRecord> aaaaset;
112 aaaaset.push_back(aaaarr);
113 g_recCache->replace(now, DNSName(templ), QType(QType::AAAA), aaaaset, vector<std::shared_ptr<const RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), false, g_rootdnsname);
114 }
115
116 nsset.push_back(nsrr);
117 }
118 g_recCache->replace(now, g_rootdnsname, QType(QType::NS), nsset, vector<std::shared_ptr<const RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), false, g_rootdnsname); // and stuff in the cache
119 return true;
120 }
121
122 LuaConfigItems::LuaConfigItems()
123 {
124 for (const auto& dsRecord : rootDSs) {
125 auto ds = std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(dsRecord));
126 dsAnchors[g_rootdnsname].insert(*ds);
127 }
128 }
129
130 /* Some helpers functions */
131
132 void initSR(bool debug)
133 {
134 g_log.setName("test");
135 g_log.disableSyslog(true);
136
137 if (debug) {
138 g_log.setLoglevel((Logger::Urgency)(6)); // info and up
139 g_log.toConsole(Logger::Info);
140 }
141 else {
142 g_log.setLoglevel(Logger::None);
143 g_log.toConsole(Logger::Error);
144 }
145
146 RecursorPacketCache::s_refresh_ttlperc = 0;
147 MemRecursorCache::s_maxServedStaleExtensions = 0;
148 NegCache::s_maxServedStaleExtensions = 0;
149 g_recCache = std::make_unique<MemRecursorCache>();
150 g_negCache = std::make_unique<NegCache>();
151
152 SyncRes::s_maxqperq = 50;
153 SyncRes::s_maxnsaddressqperq = 10;
154 SyncRes::s_maxtotusec = 1000 * 7000;
155 SyncRes::s_maxdepth = 40;
156 SyncRes::s_maxnegttl = 3600;
157 SyncRes::s_maxbogusttl = 3600;
158 SyncRes::s_maxcachettl = 86400;
159 SyncRes::s_packetcachettl = 3600;
160 SyncRes::s_packetcacheservfailttl = 60;
161 SyncRes::s_serverdownmaxfails = 64;
162 SyncRes::s_serverdownthrottletime = 60;
163 SyncRes::s_doIPv4 = true;
164 SyncRes::s_doIPv6 = true;
165 SyncRes::s_ecsipv4limit = 24;
166 SyncRes::s_ecsipv6limit = 56;
167 SyncRes::s_ecsipv4cachelimit = 24;
168 SyncRes::s_ecsipv6cachelimit = 56;
169 SyncRes::s_ecscachelimitttl = 0;
170 SyncRes::s_rootNXTrust = true;
171 SyncRes::s_hardenNXD = SyncRes::HardenNXD::DNSSEC;
172 SyncRes::s_minimumTTL = 0;
173 SyncRes::s_minimumECSTTL = 0;
174 SyncRes::s_serverID = "PowerDNS Unit Tests Server ID";
175 SyncRes::clearEDNSLocalSubnets();
176 SyncRes::addEDNSLocalSubnet("0.0.0.0/0");
177 SyncRes::addEDNSLocalSubnet("::/0");
178 SyncRes::clearEDNSRemoteSubnets();
179 SyncRes::clearEDNSDomains();
180 SyncRes::clearDontQuery();
181 SyncRes::setECSScopeZeroAddress(Netmask("127.0.0.1/32"));
182 SyncRes::s_qnameminimization = false;
183 SyncRes::s_nonresolvingnsmaxfails = 0;
184 SyncRes::s_nonresolvingnsthrottletime = 0;
185 SyncRes::s_refresh_ttlperc = 0;
186 SyncRes::s_save_parent_ns_set = true;
187 SyncRes::s_maxnsperresolve = 13;
188 SyncRes::s_locked_ttlperc = 0;
189 SyncRes::s_minimize_one_label = 4;
190 SyncRes::s_max_minimize_count = 10;
191
192 SyncRes::clearNSSpeeds();
193 BOOST_CHECK_EQUAL(SyncRes::getNSSpeedsSize(), 0U);
194 SyncRes::clearEDNSStatuses();
195 BOOST_CHECK_EQUAL(SyncRes::getEDNSStatusesSize(), 0U);
196 SyncRes::clearThrottle();
197 BOOST_CHECK_EQUAL(SyncRes::getThrottledServersSize(), 0U);
198 SyncRes::clearFailedServers();
199 BOOST_CHECK_EQUAL(SyncRes::getFailedServersSize(), 0U);
200 SyncRes::clearNonResolvingNS();
201 BOOST_CHECK_EQUAL(SyncRes::getNonResolvingNSSize(), 0U);
202 SyncRes::clearSaveParentsNSSets();
203 BOOST_CHECK_EQUAL(SyncRes::getSaveParentsNSSetsSize(), 0U);
204
205 SyncRes::clearECSStats();
206
207 auto luaconfsCopy = g_luaconfs.getCopy();
208 luaconfsCopy.dfe.clear();
209 luaconfsCopy.dsAnchors.clear();
210 for (const auto& dsRecord : rootDSs) {
211 auto ds = std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(dsRecord));
212 luaconfsCopy.dsAnchors[g_rootdnsname].insert(*ds);
213 }
214 luaconfsCopy.negAnchors.clear();
215 g_luaconfs.setState(luaconfsCopy);
216
217 g_dnssecmode = DNSSECMode::Off;
218 g_maxNSEC3Iterations = 2500;
219
220 g_aggressiveNSECCache.reset();
221 AggressiveNSECCache::s_maxNSEC3CommonPrefix = AggressiveNSECCache::s_default_maxNSEC3CommonPrefix;
222
223 taskQueueClear();
224
225 ::arg().set("version-string", "string reported on version.pdns or version.bind") = "PowerDNS Unit Tests";
226 ::arg().set("rng") = "auto";
227 ::arg().set("entropy-source") = "/dev/urandom";
228 ::arg().set("hint-file") = "";
229 }
230
231 void initSR(std::unique_ptr<SyncRes>& sr, bool dnssec, bool debug, time_t fakeNow)
232 {
233 struct timeval now;
234 if (fakeNow > 0) {
235 now.tv_sec = fakeNow;
236 now.tv_usec = 0;
237 }
238 else {
239 Utility::gettimeofday(&now, 0);
240 }
241
242 initSR(debug);
243
244 sr = std::make_unique<SyncRes>(now);
245 sr->setDoEDNS0(true);
246 if (dnssec) {
247 sr->setDoDNSSEC(dnssec);
248 }
249
250 sr->setLogMode(debug == false ? SyncRes::LogNone : SyncRes::Log);
251
252 SyncRes::setDomainMap(std::make_shared<SyncRes::domainmap_t>());
253 g_negCache->clear();
254 }
255
256 void setDNSSECValidation(std::unique_ptr<SyncRes>& sr, const DNSSECMode& mode)
257 {
258 sr->setDNSSECValidationRequested(true);
259 g_dnssecmode = mode;
260 }
261
262 void setLWResult(LWResult* res, int rcode, bool aa, bool tc, bool edns, bool validpacket)
263 {
264 res->d_rcode = rcode;
265 res->d_aabit = aa;
266 res->d_tcbit = tc;
267 res->d_haveEDNS = edns;
268 res->d_validpacket = validpacket;
269 }
270
271 void addRecordToLW(LWResult* res, const DNSName& name, uint16_t type, const std::string& content, DNSResourceRecord::Place place, uint32_t ttl)
272 {
273 addRecordToList(res->d_records, name, type, content, place, ttl);
274 }
275
276 void addRecordToLW(LWResult* res, const std::string& name, uint16_t type, const std::string& content, DNSResourceRecord::Place place, uint32_t ttl)
277 {
278 addRecordToLW(res, DNSName(name), type, content, place, ttl);
279 }
280
281 bool isRootServer(const ComboAddress& ip)
282 {
283 if (ip.isIPv4()) {
284 for (size_t idx = 0; idx < rootIps4.size(); idx++) {
285 if (ip.toString() == rootIps4[idx]) {
286 return true;
287 }
288 }
289 }
290 else {
291 for (size_t idx = 0; idx < rootIps6.size(); idx++) {
292 if (ip.toString() == rootIps6[idx]) {
293 return true;
294 }
295 }
296 }
297
298 return false;
299 }
300
301 void computeRRSIG(const DNSSECPrivateKey& dpk, const DNSName& signer, const DNSName& signQName, uint16_t signQType, uint32_t signTTL, uint32_t sigValidity, RRSIGRecordContent& rrc, const sortedRecords_t& toSign, boost::optional<uint8_t> algo, boost::optional<uint32_t> inception, boost::optional<time_t> now)
302 {
303 if (!now) {
304 now = time(nullptr);
305 }
306 DNSKEYRecordContent drc = dpk.getDNSKEY();
307 const auto& rc = dpk.getKey();
308
309 rrc.d_type = signQType;
310 rrc.d_labels = signQName.countLabels() - (signQName.isWildcard() ? 1 : 0);
311 rrc.d_originalttl = signTTL;
312 rrc.d_siginception = inception ? *inception : (*now - 10);
313 rrc.d_sigexpire = *now + sigValidity;
314 rrc.d_signer = signer;
315 rrc.d_tag = drc.getTag();
316 rrc.d_algorithm = algo ? *algo : drc.d_algorithm;
317
318 std::string msg = getMessageForRRSET(signQName, rrc, toSign);
319
320 rrc.d_signature = rc->sign(msg);
321 }
322
323 typedef std::unordered_map<DNSName, std::pair<DNSSECPrivateKey, DSRecordContent>> testkeysset_t;
324
325 bool addRRSIG(const testkeysset_t& keys, std::vector<DNSRecord>& records, const DNSName& signer, uint32_t sigValidity, bool broken, boost::optional<uint8_t> algo, boost::optional<DNSName> wildcard, boost::optional<time_t> now)
326 {
327 if (records.empty()) {
328 return false;
329 }
330
331 const auto it = keys.find(signer);
332 if (it == keys.cend()) {
333 throw std::runtime_error("No DNSKEY found for " + signer.toLogString() + ", unable to compute the requested RRSIG");
334 }
335
336 size_t recordsCount = records.size();
337 const DNSName& name = records[recordsCount - 1].d_name;
338 const uint16_t type = records[recordsCount - 1].d_type;
339
340 sortedRecords_t recordcontents;
341 for (const auto& record : records) {
342 if (record.d_name == name && record.d_type == type) {
343 recordcontents.insert(record.getContent());
344 }
345 }
346
347 RRSIGRecordContent rrc;
348 computeRRSIG(it->second.first, signer, wildcard ? *wildcard : records[recordsCount - 1].d_name, records[recordsCount - 1].d_type, records[recordsCount - 1].d_ttl, sigValidity, rrc, recordcontents, algo, boost::none, now);
349 if (broken) {
350 rrc.d_signature[0] ^= 42;
351 }
352
353 DNSRecord rec;
354 rec.d_type = QType::RRSIG;
355 rec.d_place = records[recordsCount - 1].d_place;
356 rec.d_name = records[recordsCount - 1].d_name;
357 rec.d_ttl = records[recordsCount - 1].d_ttl;
358
359 rec.setContent(std::make_shared<RRSIGRecordContent>(rrc));
360 records.push_back(rec);
361
362 return true;
363 }
364
365 void addDNSKEY(const testkeysset_t& keys, const DNSName& signer, uint32_t ttl, std::vector<DNSRecord>& records)
366 {
367 const auto it = keys.find(signer);
368 if (it == keys.cend()) {
369 throw std::runtime_error("No DNSKEY found for " + signer.toLogString());
370 }
371
372 DNSRecord rec;
373 rec.d_place = DNSResourceRecord::ANSWER;
374 rec.d_name = signer;
375 rec.d_type = QType::DNSKEY;
376 rec.d_ttl = ttl;
377
378 rec.setContent(std::make_shared<DNSKEYRecordContent>(it->second.first.getDNSKEY()));
379 records.push_back(rec);
380 }
381
382 bool addDS(const DNSName& domain, uint32_t ttl, std::vector<DNSRecord>& records, const testkeysset_t& keys, DNSResourceRecord::Place place)
383 {
384 const auto it = keys.find(domain);
385 if (it == keys.cend()) {
386 return false;
387 }
388
389 DNSRecord rec;
390 rec.d_name = domain;
391 rec.d_type = QType::DS;
392 rec.d_place = place;
393 rec.d_ttl = ttl;
394 rec.setContent(std::make_shared<DSRecordContent>(it->second.second));
395
396 records.push_back(rec);
397 return true;
398 }
399
400 void addNSECRecordToLW(const DNSName& domain, const DNSName& next, const std::set<uint16_t>& types, uint32_t ttl, std::vector<DNSRecord>& records)
401 {
402 NSECRecordContent nrc;
403 nrc.d_next = next;
404 for (const auto& type : types) {
405 nrc.set(type);
406 }
407
408 DNSRecord rec;
409 rec.d_name = domain;
410 rec.d_ttl = ttl;
411 rec.d_type = QType::NSEC;
412 rec.setContent(std::make_shared<NSECRecordContent>(std::move(nrc)));
413 rec.d_place = DNSResourceRecord::AUTHORITY;
414
415 records.push_back(rec);
416 }
417
418 void addNSEC3RecordToLW(const DNSName& hashedName, const std::string& hashedNext, const std::string& salt, unsigned int iterations, const std::set<uint16_t>& types, uint32_t ttl, std::vector<DNSRecord>& records, bool optOut)
419 {
420 NSEC3RecordContent nrc;
421 nrc.d_algorithm = 1;
422 nrc.d_flags = optOut ? 1 : 0;
423 nrc.d_iterations = iterations;
424 nrc.d_salt = salt;
425 nrc.d_nexthash = hashedNext;
426 for (const auto& type : types) {
427 nrc.set(type);
428 }
429
430 DNSRecord rec;
431 rec.d_name = hashedName;
432 rec.d_ttl = ttl;
433 rec.d_type = QType::NSEC3;
434 rec.setContent(std::make_shared<NSEC3RecordContent>(std::move(nrc)));
435 rec.d_place = DNSResourceRecord::AUTHORITY;
436
437 records.push_back(rec);
438 }
439
440 void addNSEC3UnhashedRecordToLW(const DNSName& domain, const DNSName& zone, const std::string& next, const std::set<uint16_t>& types, uint32_t ttl, std::vector<DNSRecord>& records, unsigned int iterations, bool optOut)
441 {
442 static const std::string salt = "deadbeef";
443 std::string hashed = hashQNameWithSalt(salt, iterations, domain);
444
445 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed)) + zone, next, salt, iterations, types, ttl, records, optOut);
446 }
447
448 /* Proves a NODATA (name exists, type does not) but the next owner name is right behind, so it should not prove anything else unless we are very unlucky */
449 void addNSEC3NoDataNarrowRecordToLW(const DNSName& domain, const DNSName& zone, const std::set<uint16_t>& types, uint32_t ttl, std::vector<DNSRecord>& records, unsigned int iterations, bool optOut)
450 {
451 static const std::string salt = "deadbeef";
452 std::string hashed = hashQNameWithSalt(salt, iterations, domain);
453 std::string hashedNext(hashed);
454 incrementHash(hashedNext);
455
456 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed)) + zone, hashedNext, salt, iterations, types, ttl, records, optOut);
457 }
458
459 void addNSEC3NarrowRecordToLW(const DNSName& domain, const DNSName& zone, const std::set<uint16_t>& types, uint32_t ttl, std::vector<DNSRecord>& records, unsigned int iterations, bool optOut)
460 {
461 static const std::string salt = "deadbeef";
462 std::string hashed = hashQNameWithSalt(salt, iterations, domain);
463 std::string hashedNext(hashed);
464 incrementHash(hashedNext);
465 decrementHash(hashed);
466
467 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed)) + zone, hashedNext, salt, iterations, types, ttl, records, optOut);
468 }
469
470 void generateKeyMaterial(const DNSName& name, unsigned int algo, uint8_t digest, testkeysset_t& keys)
471 {
472 auto dcke = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(algo));
473 dcke->create((algo <= 10) ? 2048 : dcke->getBits());
474 DNSSECPrivateKey dpk;
475 dpk.setKey(dcke, 256);
476 DSRecordContent ds = makeDSFromDNSKey(name, dpk.getDNSKEY(), digest);
477 keys[name] = std::pair<DNSSECPrivateKey, DSRecordContent>(dpk, ds);
478 }
479
480 void generateKeyMaterial(const DNSName& name, unsigned int algo, uint8_t digest, testkeysset_t& keys, map<DNSName, dsmap_t>& dsAnchors)
481 {
482 generateKeyMaterial(name, algo, digest, keys);
483 dsAnchors[name].insert(keys[name].second);
484 }
485
486 LWResult::Result genericDSAndDNSKEYHandler(LWResult* res, const DNSName& domain, DNSName auth, int type, const testkeysset_t& keys, bool proveCut, boost::optional<time_t> now, bool nsec3, bool optOut)
487 {
488 if (type == QType::DS) {
489 auth.chopOff();
490
491 setLWResult(res, 0, true, false, true);
492
493 if (addDS(domain, 300, res->d_records, keys, DNSResourceRecord::ANSWER)) {
494 addRRSIG(keys, res->d_records, auth, 300, false, boost::none, boost::none, now);
495 }
496 else {
497 addRecordToLW(res, auth, QType::SOA, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400);
498
499 /* if the auth zone is signed, we need to provide a secure denial */
500 const auto it = keys.find(auth);
501 if (it != keys.cend()) {
502 /* sign the SOA */
503 addRRSIG(keys, res->d_records, auth, 300, false, boost::none, boost::none, now);
504 /* add a NSEC denying the DS */
505 std::set<uint16_t> types = {QType::RRSIG};
506 if (proveCut) {
507 types.insert(QType::NS);
508 }
509
510 if (!nsec3) {
511 addNSECRecordToLW(domain, DNSName("+") + domain, types, 600, res->d_records);
512 }
513 else {
514 DNSName next(DNSName("z") + domain);
515 next.makeUsRelative(auth);
516 addNSEC3UnhashedRecordToLW(domain, auth, next.toString(), types, 600, res->d_records, 10, optOut);
517 }
518
519 addRRSIG(keys, res->d_records, auth, 300, false, boost::none, boost::none, now);
520 }
521 }
522
523 return LWResult::Result::Success;
524 }
525
526 if (type == QType::DNSKEY) {
527 setLWResult(res, 0, true, false, true);
528 addDNSKEY(keys, domain, 300, res->d_records);
529 addRRSIG(keys, res->d_records, domain, 300, false, boost::none, boost::none, now);
530 return LWResult::Result::Success;
531 }
532
533 return LWResult::Result::Timeout;
534 }
535
536 LWResult::Result basicRecordsForQnameMinimization(LWResult* res, const DNSName& domain, int type)
537 {
538 if (domain == DNSName(".") && type == QType::A) {
539 setLWResult(res, 0, true);
540 addRecordToLW(res, DNSName("."), QType::SOA, "a.root-servers.net. nstld.verisign-grs.com. 2019042400 1800 900 604800 86400", DNSResourceRecord::AUTHORITY);
541 return LWResult::Result::Success;
542 }
543 if (domain == DNSName("com") && type == QType::A) {
544 setLWResult(res, 0, true);
545 addRecordToLW(res, DNSName("com"), QType::NS, "ns1.com", DNSResourceRecord::AUTHORITY);
546 addRecordToLW(res, DNSName("ns1.com"), QType::A, "1.2.3.4", DNSResourceRecord::ADDITIONAL);
547 return LWResult::Result::Success;
548 }
549 if (domain == DNSName("ns1.com") && type == QType::A) {
550 setLWResult(res, 0, true);
551 addRecordToLW(res, DNSName("ns1.com"), QType::A, "1.2.3.4");
552 return LWResult::Result::Success;
553 }
554 if (domain == DNSName("powerdns.com") && type == QType::A) {
555 setLWResult(res, 0, true);
556 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com", DNSResourceRecord::AUTHORITY);
557 addRecordToLW(res, DNSName("ns1.powerdns.com"), QType::A, "4.5.6.7", DNSResourceRecord::ADDITIONAL);
558 return LWResult::Result::Success;
559 }
560 if (domain == DNSName("powerdns.com") && type == QType::NS) {
561 setLWResult(res, 0, true);
562 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com");
563 addRecordToLW(res, DNSName("ns1.powerdns.com"), QType::A, "4.5.6.7", DNSResourceRecord::ADDITIONAL);
564 return LWResult::Result::Success;
565 }
566 return LWResult::Result::Timeout;
567 }