1 #ifndef BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_DYN_LINK
5 #include <boost/test/unit_test.hpp>
7 #include "aggressive_nsec.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"
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;
24 pdns::TaskQueue g_test_tasks
;
25 pdns::TaskQueue g_resolve_tasks
;
27 /* Fake some required functions we didn't want the trouble to
31 static ArgvMap theArg
;
39 void BaseLua4::getFeatures(Features
& /* features */)
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
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
53 RecursorLua4::~RecursorLua4()
57 void RecursorLua4::postPrepareContext()
61 void RecursorLua4::postLoad()
65 void RecursorLua4::getFeatures(Features
& /* features */)
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 */)
71 return LWResult::Result::Timeout
;
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
80 #include "root-addresses.hh"
82 bool primeHints(time_t now
)
84 vector
<DNSRecord
> nsset
;
86 g_recCache
= std::make_unique
<MemRecursorCache
>();
88 g_negCache
= std::make_unique
<NegCache
>();
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;
97 for (char c
= 'a'; c
<= 'm'; ++c
) {
99 strncpy(templ
, "a.root-servers.net.", sizeof(templ
) - 1);
100 templ
[sizeof(templ
) - 1] = '\0';
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
;
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'])));
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
);
116 nsset
.push_back(nsrr
);
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
122 LuaConfigItems::LuaConfigItems()
124 for (const auto& dsRecord
: rootDSs
) {
125 auto ds
= std::dynamic_pointer_cast
<DSRecordContent
>(DSRecordContent::make(dsRecord
));
126 dsAnchors
[g_rootdnsname
].insert(*ds
);
130 /* Some helpers functions */
132 void initSR(bool debug
)
134 g_log
.setName("test");
135 g_log
.disableSyslog(true);
138 g_log
.setLoglevel((Logger::Urgency
)(6)); // info and up
139 g_log
.toConsole(Logger::Info
);
142 g_log
.setLoglevel(Logger::None
);
143 g_log
.toConsole(Logger::Error
);
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
>();
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;
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);
205 SyncRes::clearECSStats();
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
);
214 luaconfsCopy
.negAnchors
.clear();
215 g_luaconfs
.setState(luaconfsCopy
);
217 g_dnssecmode
= DNSSECMode::Off
;
218 g_maxNSEC3Iterations
= 2500;
220 g_aggressiveNSECCache
.reset();
221 AggressiveNSECCache::s_maxNSEC3CommonPrefix
= AggressiveNSECCache::s_default_maxNSEC3CommonPrefix
;
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") = "";
231 void initSR(std::unique_ptr
<SyncRes
>& sr
, bool dnssec
, bool debug
, time_t fakeNow
)
235 now
.tv_sec
= fakeNow
;
239 Utility::gettimeofday(&now
, 0);
244 sr
= std::make_unique
<SyncRes
>(now
);
245 sr
->setDoEDNS0(true);
247 sr
->setDoDNSSEC(dnssec
);
250 sr
->setLogMode(debug
== false ? SyncRes::LogNone
: SyncRes::Log
);
252 SyncRes::setDomainMap(std::make_shared
<SyncRes::domainmap_t
>());
256 void setDNSSECValidation(std::unique_ptr
<SyncRes
>& sr
, const DNSSECMode
& mode
)
258 sr
->setDNSSECValidationRequested(true);
262 void setLWResult(LWResult
* res
, int rcode
, bool aa
, bool tc
, bool edns
, bool validpacket
)
264 res
->d_rcode
= rcode
;
267 res
->d_haveEDNS
= edns
;
268 res
->d_validpacket
= validpacket
;
271 void addRecordToLW(LWResult
* res
, const DNSName
& name
, uint16_t type
, const std::string
& content
, DNSResourceRecord::Place place
, uint32_t ttl
)
273 addRecordToList(res
->d_records
, name
, type
, content
, place
, ttl
);
276 void addRecordToLW(LWResult
* res
, const std::string
& name
, uint16_t type
, const std::string
& content
, DNSResourceRecord::Place place
, uint32_t ttl
)
278 addRecordToLW(res
, DNSName(name
), type
, content
, place
, ttl
);
281 bool isRootServer(const ComboAddress
& ip
)
284 for (size_t idx
= 0; idx
< rootIps4
.size(); idx
++) {
285 if (ip
.toString() == rootIps4
[idx
]) {
291 for (size_t idx
= 0; idx
< rootIps6
.size(); idx
++) {
292 if (ip
.toString() == rootIps6
[idx
]) {
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
)
306 DNSKEYRecordContent drc
= dpk
.getDNSKEY();
307 const auto& rc
= dpk
.getKey();
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
;
318 std::string msg
= getMessageForRRSET(signQName
, rrc
, toSign
);
320 rrc
.d_signature
= rc
->sign(msg
);
323 typedef std::unordered_map
<DNSName
, std::pair
<DNSSECPrivateKey
, DSRecordContent
>> testkeysset_t
;
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
)
327 if (records
.empty()) {
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");
337 uint16_t type
{QType::ENT
};
338 DNSResourceRecord::Place place
{DNSResourceRecord::ANSWER
};
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
;
355 throw std::runtime_error("Unable to locate the record that the RRSIG should cover");
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());
365 RRSIGRecordContent rrc
;
366 computeRRSIG(it
->second
.first
, signer
, wildcard
? *wildcard
: name
, type
, ttl
, sigValidity
, rrc
, recordcontents
, algo
, boost::none
, now
);
368 rrc
.d_signature
[0] ^= 42;
372 rec
.d_type
= QType::RRSIG
;
377 rec
.setContent(std::make_shared
<RRSIGRecordContent
>(rrc
));
378 records
.push_back(rec
);
383 void addDNSKEY(const testkeysset_t
& keys
, const DNSName
& signer
, uint32_t ttl
, std::vector
<DNSRecord
>& records
)
385 const auto it
= keys
.find(signer
);
386 if (it
== keys
.cend()) {
387 throw std::runtime_error("No DNSKEY found for " + signer
.toLogString());
391 rec
.d_place
= DNSResourceRecord::ANSWER
;
393 rec
.d_type
= QType::DNSKEY
;
396 rec
.setContent(std::make_shared
<DNSKEYRecordContent
>(it
->second
.first
.getDNSKEY()));
397 records
.push_back(rec
);
400 bool addDS(const DNSName
& domain
, uint32_t ttl
, std::vector
<DNSRecord
>& records
, const testkeysset_t
& keys
, DNSResourceRecord::Place place
)
402 const auto it
= keys
.find(domain
);
403 if (it
== keys
.cend()) {
409 rec
.d_type
= QType::DS
;
412 rec
.setContent(std::make_shared
<DSRecordContent
>(it
->second
.second
));
414 records
.push_back(rec
);
418 void addNSECRecordToLW(const DNSName
& domain
, const DNSName
& next
, const std::set
<uint16_t>& types
, uint32_t ttl
, std::vector
<DNSRecord
>& records
)
420 NSECRecordContent nrc
;
422 for (const auto& type
: types
) {
429 rec
.d_type
= QType::NSEC
;
430 rec
.setContent(std::make_shared
<NSECRecordContent
>(std::move(nrc
)));
431 rec
.d_place
= DNSResourceRecord::AUTHORITY
;
433 records
.push_back(rec
);
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
)
438 NSEC3RecordContent nrc
;
440 nrc
.d_flags
= optOut
? 1 : 0;
441 nrc
.d_iterations
= iterations
;
443 nrc
.d_nexthash
= hashedNext
;
444 for (const auto& type
: types
) {
449 rec
.d_name
= hashedName
;
451 rec
.d_type
= QType::NSEC3
;
452 rec
.setContent(std::make_shared
<NSEC3RecordContent
>(std::move(nrc
)));
453 rec
.d_place
= DNSResourceRecord::AUTHORITY
;
455 records
.push_back(rec
);
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
)
460 static const std::string salt
= "deadbeef";
461 std::string hashed
= hashQNameWithSalt(salt
, iterations
, domain
);
463 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed
)) + zone
, next
, salt
, iterations
, types
, ttl
, records
, optOut
);
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
)
469 static const std::string salt
= "deadbeef";
470 std::string hashed
= hashQNameWithSalt(salt
, iterations
, domain
);
471 std::string
hashedNext(hashed
);
472 incrementHash(hashedNext
);
474 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed
)) + zone
, hashedNext
, salt
, iterations
, types
, ttl
, records
, optOut
);
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
)
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
);
485 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed
)) + zone
, hashedNext
, salt
, iterations
, types
, ttl
, records
, optOut
);
488 void generateKeyMaterial(const DNSName
& name
, unsigned int algo
, uint8_t digest
, testkeysset_t
& keys
)
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
);
498 void generateKeyMaterial(const DNSName
& name
, unsigned int algo
, uint8_t digest
, testkeysset_t
& keys
, map
<DNSName
, dsmap_t
>& dsAnchors
)
500 generateKeyMaterial(name
, algo
, digest
, keys
);
501 dsAnchors
[name
].insert(keys
[name
].second
);
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
)
506 if (type
== QType::DS
) {
509 setLWResult(res
, 0, true, false, true);
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
);
515 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
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()) {
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
};
525 types
.insert(QType::NS
);
529 addNSECRecordToLW(domain
, DNSName("+") + domain
, types
, 600, res
->d_records
);
532 DNSName
next(DNSName("z") + domain
);
533 next
.makeUsRelative(auth
);
534 addNSEC3UnhashedRecordToLW(domain
, auth
, next
.toString(), types
, 600, res
->d_records
, 10, optOut
);
537 addRRSIG(keys
, res
->d_records
, auth
, 300, false, boost::none
, boost::none
, now
);
541 return LWResult::Result::Success
;
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
;
551 return LWResult::Result::Timeout
;
554 LWResult::Result
basicRecordsForQnameMinimization(LWResult
* res
, const DNSName
& domain
, int type
)
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
;
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
;
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
;
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
;
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
;
584 return LWResult::Result::Timeout
;