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