1 #define BOOST_TEST_DYN_LINK
2 #include <boost/test/unit_test.hpp>
4 #include "aggressive_nsec.hh"
6 #include "lua-recursor4.hh"
7 #include "root-dnssec.hh"
8 #include "rec-taskqueue.hh"
9 #include "test-syncres_cc.hh"
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;
20 pdns::TaskQueue g_test_tasks
;
21 pdns::TaskQueue g_resolve_tasks
;
23 /* Fake some required functions we didn't want the trouble to
27 static ArgvMap theArg
;
35 void BaseLua4::getFeatures(Features
& /* features */)
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
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
49 RecursorLua4::~RecursorLua4()
53 void RecursorLua4::postPrepareContext()
57 void RecursorLua4::postLoad()
61 void RecursorLua4::getFeatures(Features
& /* features */)
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 */)
67 return LWResult::Result::Timeout
;
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
76 #include "root-addresses.hh"
78 bool primeHints(time_t now
)
80 vector
<DNSRecord
> nsset
;
82 g_recCache
= std::make_unique
<MemRecursorCache
>();
84 g_negCache
= std::make_unique
<NegCache
>();
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;
93 for (char c
= 'a'; c
<= 'm'; ++c
) {
95 strncpy(templ
, "a.root-servers.net.", sizeof(templ
) - 1);
96 templ
[sizeof(templ
) - 1] = '\0';
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
;
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'])));
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
);
112 nsset
.push_back(nsrr
);
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
118 LuaConfigItems::LuaConfigItems()
120 for (const auto& dsRecord
: rootDSs
) {
121 auto ds
= std::dynamic_pointer_cast
<DSRecordContent
>(DSRecordContent::make(dsRecord
));
122 dsAnchors
[g_rootdnsname
].insert(*ds
);
126 /* Some helpers functions */
128 void initSR(bool debug
)
130 g_log
.setName("test");
131 g_log
.disableSyslog(true);
134 g_log
.setLoglevel((Logger::Urgency
)(6)); // info and up
135 g_log
.toConsole(Logger::Info
);
138 g_log
.setLoglevel(Logger::None
);
139 g_log
.toConsole(Logger::Error
);
142 MemRecursorCache::s_maxServedStaleExtensions
= 0;
143 NegCache::s_maxServedStaleExtensions
= 0;
144 g_recCache
= std::make_unique
<MemRecursorCache
>();
145 g_negCache
= std::make_unique
<NegCache
>();
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;
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);
198 SyncRes::clearECSStats();
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
);
207 luaconfsCopy
.negAnchors
.clear();
208 g_luaconfs
.setState(luaconfsCopy
);
210 g_dnssecmode
= DNSSECMode::Off
;
211 g_maxNSEC3Iterations
= 2500;
213 g_aggressiveNSECCache
.reset();
214 AggressiveNSECCache::s_maxNSEC3CommonPrefix
= AggressiveNSECCache::s_default_maxNSEC3CommonPrefix
;
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 ::arg().set("hint-file") = "";
224 void initSR(std::unique_ptr
<SyncRes
>& sr
, bool dnssec
, bool debug
, time_t fakeNow
)
228 now
.tv_sec
= fakeNow
;
232 Utility::gettimeofday(&now
, 0);
237 sr
= std::make_unique
<SyncRes
>(now
);
238 sr
->setDoEDNS0(true);
240 sr
->setDoDNSSEC(dnssec
);
243 sr
->setLogMode(debug
== false ? SyncRes::LogNone
: SyncRes::Log
);
245 SyncRes::setDomainMap(std::make_shared
<SyncRes::domainmap_t
>());
249 void setDNSSECValidation(std::unique_ptr
<SyncRes
>& sr
, const DNSSECMode
& mode
)
251 sr
->setDNSSECValidationRequested(true);
255 void setLWResult(LWResult
* res
, int rcode
, bool aa
, bool tc
, bool edns
, bool validpacket
)
257 res
->d_rcode
= rcode
;
260 res
->d_haveEDNS
= edns
;
261 res
->d_validpacket
= validpacket
;
264 void addRecordToLW(LWResult
* res
, const DNSName
& name
, uint16_t type
, const std::string
& content
, DNSResourceRecord::Place place
, uint32_t ttl
)
266 addRecordToList(res
->d_records
, name
, type
, content
, place
, ttl
);
269 void addRecordToLW(LWResult
* res
, const std::string
& name
, uint16_t type
, const std::string
& content
, DNSResourceRecord::Place place
, uint32_t ttl
)
271 addRecordToLW(res
, DNSName(name
), type
, content
, place
, ttl
);
274 bool isRootServer(const ComboAddress
& ip
)
277 for (size_t idx
= 0; idx
< rootIps4
.size(); idx
++) {
278 if (ip
.toString() == rootIps4
[idx
]) {
284 for (size_t idx
= 0; idx
< rootIps6
.size(); idx
++) {
285 if (ip
.toString() == rootIps6
[idx
]) {
294 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
)
299 DNSKEYRecordContent drc
= dpk
.getDNSKEY();
300 const auto& rc
= dpk
.getKey();
302 rrc
.d_type
= signQType
;
303 rrc
.d_labels
= signQName
.countLabels() - (signQName
.isWildcard() ? 1 : 0);
304 rrc
.d_originalttl
= signTTL
;
305 rrc
.d_siginception
= inception
? *inception
: (*now
- 10);
306 rrc
.d_sigexpire
= *now
+ sigValidity
;
307 rrc
.d_signer
= signer
;
308 rrc
.d_tag
= drc
.getTag();
309 rrc
.d_algorithm
= algo
? *algo
: drc
.d_algorithm
;
311 std::string msg
= getMessageForRRSET(signQName
, rrc
, toSign
);
313 rrc
.d_signature
= rc
->sign(msg
);
316 typedef std::unordered_map
<DNSName
, std::pair
<DNSSECPrivateKey
, DSRecordContent
>> testkeysset_t
;
318 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
)
320 if (records
.empty()) {
324 const auto it
= keys
.find(signer
);
325 if (it
== keys
.cend()) {
326 throw std::runtime_error("No DNSKEY found for " + signer
.toLogString() + ", unable to compute the requested RRSIG");
329 size_t recordsCount
= records
.size();
330 const DNSName
& name
= records
[recordsCount
- 1].d_name
;
331 const uint16_t type
= records
[recordsCount
- 1].d_type
;
333 sortedRecords_t recordcontents
;
334 for (const auto& record
: records
) {
335 if (record
.d_name
== name
&& record
.d_type
== type
) {
336 recordcontents
.insert(record
.getContent());
340 RRSIGRecordContent rrc
;
341 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
);
343 rrc
.d_signature
[0] ^= 42;
347 rec
.d_type
= QType::RRSIG
;
348 rec
.d_place
= records
[recordsCount
- 1].d_place
;
349 rec
.d_name
= records
[recordsCount
- 1].d_name
;
350 rec
.d_ttl
= records
[recordsCount
- 1].d_ttl
;
352 rec
.setContent(std::make_shared
<RRSIGRecordContent
>(rrc
));
353 records
.push_back(rec
);
358 void addDNSKEY(const testkeysset_t
& keys
, const DNSName
& signer
, uint32_t ttl
, std::vector
<DNSRecord
>& records
)
360 const auto it
= keys
.find(signer
);
361 if (it
== keys
.cend()) {
362 throw std::runtime_error("No DNSKEY found for " + signer
.toLogString());
366 rec
.d_place
= DNSResourceRecord::ANSWER
;
368 rec
.d_type
= QType::DNSKEY
;
371 rec
.setContent(std::make_shared
<DNSKEYRecordContent
>(it
->second
.first
.getDNSKEY()));
372 records
.push_back(rec
);
375 bool addDS(const DNSName
& domain
, uint32_t ttl
, std::vector
<DNSRecord
>& records
, const testkeysset_t
& keys
, DNSResourceRecord::Place place
)
377 const auto it
= keys
.find(domain
);
378 if (it
== keys
.cend()) {
384 rec
.d_type
= QType::DS
;
387 rec
.setContent(std::make_shared
<DSRecordContent
>(it
->second
.second
));
389 records
.push_back(rec
);
393 void addNSECRecordToLW(const DNSName
& domain
, const DNSName
& next
, const std::set
<uint16_t>& types
, uint32_t ttl
, std::vector
<DNSRecord
>& records
)
395 NSECRecordContent nrc
;
397 for (const auto& type
: types
) {
404 rec
.d_type
= QType::NSEC
;
405 rec
.setContent(std::make_shared
<NSECRecordContent
>(std::move(nrc
)));
406 rec
.d_place
= DNSResourceRecord::AUTHORITY
;
408 records
.push_back(rec
);
411 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
)
413 NSEC3RecordContent nrc
;
415 nrc
.d_flags
= optOut
? 1 : 0;
416 nrc
.d_iterations
= iterations
;
418 nrc
.d_nexthash
= hashedNext
;
419 for (const auto& type
: types
) {
424 rec
.d_name
= hashedName
;
426 rec
.d_type
= QType::NSEC3
;
427 rec
.setContent(std::make_shared
<NSEC3RecordContent
>(std::move(nrc
)));
428 rec
.d_place
= DNSResourceRecord::AUTHORITY
;
430 records
.push_back(rec
);
433 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
)
435 static const std::string salt
= "deadbeef";
436 std::string hashed
= hashQNameWithSalt(salt
, iterations
, domain
);
438 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed
)) + zone
, next
, salt
, iterations
, types
, ttl
, records
, optOut
);
441 /* 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 */
442 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
)
444 static const std::string salt
= "deadbeef";
445 std::string hashed
= hashQNameWithSalt(salt
, iterations
, domain
);
446 std::string
hashedNext(hashed
);
447 incrementHash(hashedNext
);
449 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed
)) + zone
, hashedNext
, salt
, iterations
, types
, ttl
, records
, optOut
);
452 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
)
454 static const std::string salt
= "deadbeef";
455 std::string hashed
= hashQNameWithSalt(salt
, iterations
, domain
);
456 std::string
hashedNext(hashed
);
457 incrementHash(hashedNext
);
458 decrementHash(hashed
);
460 addNSEC3RecordToLW(DNSName(toBase32Hex(hashed
)) + zone
, hashedNext
, salt
, iterations
, types
, ttl
, records
, optOut
);
463 void generateKeyMaterial(const DNSName
& name
, unsigned int algo
, uint8_t digest
, testkeysset_t
& keys
)
465 auto dcke
= std::shared_ptr
<DNSCryptoKeyEngine
>(DNSCryptoKeyEngine::make(algo
));
466 dcke
->create((algo
<= 10) ? 2048 : dcke
->getBits());
467 DNSSECPrivateKey dpk
;
468 dpk
.setKey(dcke
, 256);
469 DSRecordContent ds
= makeDSFromDNSKey(name
, dpk
.getDNSKEY(), digest
);
470 keys
[name
] = std::pair
<DNSSECPrivateKey
, DSRecordContent
>(dpk
, ds
);
473 void generateKeyMaterial(const DNSName
& name
, unsigned int algo
, uint8_t digest
, testkeysset_t
& keys
, map
<DNSName
, dsmap_t
>& dsAnchors
)
475 generateKeyMaterial(name
, algo
, digest
, keys
);
476 dsAnchors
[name
].insert(keys
[name
].second
);
479 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
)
481 if (type
== QType::DS
) {
484 setLWResult(res
, 0, true, false, true);
486 if (addDS(domain
, 300, res
->d_records
, keys
, DNSResourceRecord::ANSWER
)) {
487 addRRSIG(keys
, res
->d_records
, auth
, 300, false, boost::none
, boost::none
, now
);
490 addRecordToLW(res
, auth
, QType::SOA
, "foo. bar. 2017032800 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
, 86400);
492 /* if the auth zone is signed, we need to provide a secure denial */
493 const auto it
= keys
.find(auth
);
494 if (it
!= keys
.cend()) {
496 addRRSIG(keys
, res
->d_records
, auth
, 300, false, boost::none
, boost::none
, now
);
497 /* add a NSEC denying the DS */
498 std::set
<uint16_t> types
= {QType::RRSIG
};
500 types
.insert(QType::NS
);
504 addNSECRecordToLW(domain
, DNSName("+") + domain
, types
, 600, res
->d_records
);
507 DNSName
next(DNSName("z") + domain
);
508 next
.makeUsRelative(auth
);
509 addNSEC3UnhashedRecordToLW(domain
, auth
, next
.toString(), types
, 600, res
->d_records
, 10, optOut
);
512 addRRSIG(keys
, res
->d_records
, auth
, 300, false, boost::none
, boost::none
, now
);
516 return LWResult::Result::Success
;
519 if (type
== QType::DNSKEY
) {
520 setLWResult(res
, 0, true, false, true);
521 addDNSKEY(keys
, domain
, 300, res
->d_records
);
522 addRRSIG(keys
, res
->d_records
, domain
, 300, false, boost::none
, boost::none
, now
);
523 return LWResult::Result::Success
;
526 return LWResult::Result::Timeout
;
529 LWResult::Result
basicRecordsForQnameMinimization(LWResult
* res
, const DNSName
& domain
, int type
)
531 if (domain
== DNSName(".") && type
== QType::A
) {
532 setLWResult(res
, 0, true);
533 addRecordToLW(res
, DNSName("."), QType::SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2019042400 1800 900 604800 86400", DNSResourceRecord::AUTHORITY
);
534 return LWResult::Result::Success
;
536 if (domain
== DNSName("com") && type
== QType::A
) {
537 setLWResult(res
, 0, true);
538 addRecordToLW(res
, DNSName("com"), QType::NS
, "ns1.com", DNSResourceRecord::AUTHORITY
);
539 addRecordToLW(res
, DNSName("ns1.com"), QType::A
, "1.2.3.4", DNSResourceRecord::ADDITIONAL
);
540 return LWResult::Result::Success
;
542 if (domain
== DNSName("ns1.com") && type
== QType::A
) {
543 setLWResult(res
, 0, true);
544 addRecordToLW(res
, DNSName("ns1.com"), QType::A
, "1.2.3.4");
545 return LWResult::Result::Success
;
547 if (domain
== DNSName("powerdns.com") && type
== QType::A
) {
548 setLWResult(res
, 0, true);
549 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com", DNSResourceRecord::AUTHORITY
);
550 addRecordToLW(res
, DNSName("ns1.powerdns.com"), QType::A
, "4.5.6.7", DNSResourceRecord::ADDITIONAL
);
551 return LWResult::Result::Success
;
553 if (domain
== DNSName("powerdns.com") && type
== QType::NS
) {
554 setLWResult(res
, 0, true);
555 addRecordToLW(res
, domain
, QType::NS
, "ns1.powerdns.com");
556 addRecordToLW(res
, DNSName("ns1.powerdns.com"), QType::A
, "4.5.6.7", DNSResourceRecord::ADDITIONAL
);
557 return LWResult::Result::Success
;
559 return LWResult::Result::Timeout
;