]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/recursordist/test-syncres_cc.cc
rec: CVE-2023-50387 and CVE-2023-50868
[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 */, 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 DNSName name;
337 uint16_t type{QType::ENT};
338 DNSResourceRecord::Place place{DNSResourceRecord::ANSWER};
339 uint32_t ttl{0};
340 bool found = false;
341
342 /* locate the last non-RRSIG record */
343 for (auto recordIterator = records.rbegin(); recordIterator != records.rend(); ++recordIterator) {
344 if (recordIterator->d_type != QType::RRSIG) {
345 name = recordIterator->d_name;
346 type = recordIterator->d_type;
347 place = recordIterator->d_place;
348 ttl = recordIterator->d_ttl;
349 found = true;
350 break;
351 }
352 }
353
354 if (!found) {
355 throw std::runtime_error("Unable to locate the record that the RRSIG should cover");
356 }
357
358 sortedRecords_t recordcontents;
359 for (const auto& record : records) {
360 if (record.d_name == name && record.d_type == type) {
361 recordcontents.insert(record.getContent());
362 }
363 }
364
365 RRSIGRecordContent rrc;
366 computeRRSIG(it->second.first, signer, wildcard ? *wildcard : name, type, ttl, sigValidity, rrc, recordcontents, algo, boost::none, now);
367 if (broken) {
368 rrc.d_signature[0] ^= 42;
369 }
370
371 DNSRecord rec;
372 rec.d_type = QType::RRSIG;
373 rec.d_place = place;
374 rec.d_name = name;
375 rec.d_ttl = ttl;
376
377 rec.setContent(std::make_shared<RRSIGRecordContent>(rrc));
378 records.push_back(rec);
379
380 return true;
381 }
382
383 void addDNSKEY(const testkeysset_t& keys, const DNSName& signer, uint32_t ttl, std::vector<DNSRecord>& records)
384 {
385 const auto it = keys.find(signer);
386 if (it == keys.cend()) {
387 throw std::runtime_error("No DNSKEY found for " + signer.toLogString());
388 }
389
390 DNSRecord rec;
391 rec.d_place = DNSResourceRecord::ANSWER;
392 rec.d_name = signer;
393 rec.d_type = QType::DNSKEY;
394 rec.d_ttl = ttl;
395
396 rec.setContent(std::make_shared<DNSKEYRecordContent>(it->second.first.getDNSKEY()));
397 records.push_back(rec);
398 }
399
400 bool addDS(const DNSName& domain, uint32_t ttl, std::vector<DNSRecord>& records, const testkeysset_t& keys, DNSResourceRecord::Place place)
401 {
402 const auto it = keys.find(domain);
403 if (it == keys.cend()) {
404 return false;
405 }
406
407 DNSRecord rec;
408 rec.d_name = domain;
409 rec.d_type = QType::DS;
410 rec.d_place = place;
411 rec.d_ttl = ttl;
412 rec.setContent(std::make_shared<DSRecordContent>(it->second.second));
413
414 records.push_back(rec);
415 return true;
416 }
417
418 void addNSECRecordToLW(const DNSName& domain, const DNSName& next, const std::set<uint16_t>& types, uint32_t ttl, std::vector<DNSRecord>& records)
419 {
420 NSECRecordContent nrc;
421 nrc.d_next = next;
422 for (const auto& type : types) {
423 nrc.set(type);
424 }
425
426 DNSRecord rec;
427 rec.d_name = domain;
428 rec.d_ttl = ttl;
429 rec.d_type = QType::NSEC;
430 rec.setContent(std::make_shared<NSECRecordContent>(std::move(nrc)));
431 rec.d_place = DNSResourceRecord::AUTHORITY;
432
433 records.push_back(rec);
434 }
435
436 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)
437 {
438 NSEC3RecordContent nrc;
439 nrc.d_algorithm = 1;
440 nrc.d_flags = optOut ? 1 : 0;
441 nrc.d_iterations = iterations;
442 nrc.d_salt = salt;
443 nrc.d_nexthash = hashedNext;
444 for (const auto& type : types) {
445 nrc.set(type);
446 }
447
448 DNSRecord rec;
449 rec.d_name = hashedName;
450 rec.d_ttl = ttl;
451 rec.d_type = QType::NSEC3;
452 rec.setContent(std::make_shared<NSEC3RecordContent>(std::move(nrc)));
453 rec.d_place = DNSResourceRecord::AUTHORITY;
454
455 records.push_back(rec);
456 }
457
458 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)
459 {
460 static const std::string salt = "deadbeef";
461 std::string hashed = hashQNameWithSalt(salt, iterations, domain);
462
463 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed)) + zone, next, salt, iterations, types, ttl, records, optOut);
464 }
465
466 /* 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 */
467 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)
468 {
469 static const std::string salt = "deadbeef";
470 std::string hashed = hashQNameWithSalt(salt, iterations, domain);
471 std::string hashedNext(hashed);
472 incrementHash(hashedNext);
473
474 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed)) + zone, hashedNext, salt, iterations, types, ttl, records, optOut);
475 }
476
477 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)
478 {
479 static const std::string salt = "deadbeef";
480 std::string hashed = hashQNameWithSalt(salt, iterations, domain);
481 std::string hashedNext(hashed);
482 incrementHash(hashedNext);
483 decrementHash(hashed);
484
485 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed)) + zone, hashedNext, salt, iterations, types, ttl, records, optOut);
486 }
487
488 void generateKeyMaterial(const DNSName& name, unsigned int algo, uint8_t digest, testkeysset_t& keys)
489 {
490 auto dcke = std::shared_ptr<DNSCryptoKeyEngine>(DNSCryptoKeyEngine::make(algo));
491 dcke->create((algo <= 10) ? 2048 : dcke->getBits());
492 DNSSECPrivateKey dpk;
493 dpk.setKey(dcke, 256);
494 DSRecordContent ds = makeDSFromDNSKey(name, dpk.getDNSKEY(), digest);
495 keys[name] = std::pair<DNSSECPrivateKey, DSRecordContent>(dpk, ds);
496 }
497
498 void generateKeyMaterial(const DNSName& name, unsigned int algo, uint8_t digest, testkeysset_t& keys, map<DNSName, dsmap_t>& dsAnchors)
499 {
500 generateKeyMaterial(name, algo, digest, keys);
501 dsAnchors[name].insert(keys[name].second);
502 }
503
504 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)
505 {
506 if (type == QType::DS) {
507 auth.chopOff();
508
509 setLWResult(res, 0, true, false, true);
510
511 if (addDS(domain, 300, res->d_records, keys, DNSResourceRecord::ANSWER)) {
512 addRRSIG(keys, res->d_records, auth, 300, false, boost::none, boost::none, now);
513 }
514 else {
515 addRecordToLW(res, auth, QType::SOA, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY, 86400);
516
517 /* if the auth zone is signed, we need to provide a secure denial */
518 const auto it = keys.find(auth);
519 if (it != keys.cend()) {
520 /* sign the SOA */
521 addRRSIG(keys, res->d_records, auth, 300, false, boost::none, boost::none, now);
522 /* add a NSEC denying the DS */
523 std::set<uint16_t> types = {QType::RRSIG};
524 if (proveCut) {
525 types.insert(QType::NS);
526 }
527
528 if (!nsec3) {
529 addNSECRecordToLW(domain, DNSName("+") + domain, types, 600, res->d_records);
530 }
531 else {
532 DNSName next(DNSName("z") + domain);
533 next.makeUsRelative(auth);
534 addNSEC3UnhashedRecordToLW(domain, auth, next.toString(), types, 600, res->d_records, 10, optOut);
535 }
536
537 addRRSIG(keys, res->d_records, auth, 300, false, boost::none, boost::none, now);
538 }
539 }
540
541 return LWResult::Result::Success;
542 }
543
544 if (type == QType::DNSKEY) {
545 setLWResult(res, 0, true, false, true);
546 addDNSKEY(keys, domain, 300, res->d_records);
547 addRRSIG(keys, res->d_records, domain, 300, false, boost::none, boost::none, now);
548 return LWResult::Result::Success;
549 }
550
551 return LWResult::Result::Timeout;
552 }
553
554 LWResult::Result basicRecordsForQnameMinimization(LWResult* res, const DNSName& domain, int type)
555 {
556 if (domain == DNSName(".") && type == QType::A) {
557 setLWResult(res, 0, true);
558 addRecordToLW(res, DNSName("."), QType::SOA, "a.root-servers.net. nstld.verisign-grs.com. 2019042400 1800 900 604800 86400", DNSResourceRecord::AUTHORITY);
559 return LWResult::Result::Success;
560 }
561 if (domain == DNSName("com") && type == QType::A) {
562 setLWResult(res, 0, true);
563 addRecordToLW(res, DNSName("com"), QType::NS, "ns1.com", DNSResourceRecord::AUTHORITY);
564 addRecordToLW(res, DNSName("ns1.com"), QType::A, "1.2.3.4", DNSResourceRecord::ADDITIONAL);
565 return LWResult::Result::Success;
566 }
567 if (domain == DNSName("ns1.com") && type == QType::A) {
568 setLWResult(res, 0, true);
569 addRecordToLW(res, DNSName("ns1.com"), QType::A, "1.2.3.4");
570 return LWResult::Result::Success;
571 }
572 if (domain == DNSName("powerdns.com") && type == QType::A) {
573 setLWResult(res, 0, true);
574 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com", DNSResourceRecord::AUTHORITY);
575 addRecordToLW(res, DNSName("ns1.powerdns.com"), QType::A, "4.5.6.7", DNSResourceRecord::ADDITIONAL);
576 return LWResult::Result::Success;
577 }
578 if (domain == DNSName("powerdns.com") && type == QType::NS) {
579 setLWResult(res, 0, true);
580 addRecordToLW(res, domain, QType::NS, "ns1.powerdns.com");
581 addRecordToLW(res, DNSName("ns1.powerdns.com"), QType::A, "4.5.6.7", DNSResourceRecord::ADDITIONAL);
582 return LWResult::Result::Success;
583 }
584 return LWResult::Result::Timeout;
585 }