]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/recursordist/test-syncres_cc3.cc
Merge pull request #9597 from rgacogne/rec-more-bogus-states
[thirdparty/pdns.git] / pdns / recursordist / test-syncres_cc3.cc
1 #define BOOST_TEST_DYN_LINK
2 #include <boost/test/unit_test.hpp>
3
4 #include "test-syncres_cc.hh"
5
6 BOOST_AUTO_TEST_SUITE(syncres_cc3)
7
8 BOOST_AUTO_TEST_CASE(test_cache_auth)
9 {
10 std::unique_ptr<SyncRes> sr;
11 initSR(sr);
12
13 primeHints();
14
15 /* the auth server is sending the same answer in answer and additional,
16 check that we only return one result, and we only cache one too. */
17 const DNSName target("cache-auth.powerdns.com.");
18
19 sr->setAsyncCallback([target](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, LWResult* res, bool* chained) {
20 setLWResult(res, 0, true, false, true);
21 addRecordToLW(res, domain, QType::A, "192.0.2.2", DNSResourceRecord::ANSWER, 10);
22 addRecordToLW(res, domain, QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 10);
23
24 return LWResult::Result::Success;
25 });
26
27 const time_t now = sr->getNow().tv_sec;
28
29 vector<DNSRecord> ret;
30 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
31 BOOST_CHECK_EQUAL(res, RCode::NoError);
32 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
33 BOOST_REQUIRE_EQUAL(QType(ret.at(0).d_type).getName(), QType(QType::A).getName());
34 BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret.at(0))->getCA().toString(), ComboAddress("192.0.2.2").toString());
35
36 /* check that we correctly cached only the answer entry, not the additional one */
37 const ComboAddress who;
38 vector<DNSRecord> cached;
39 BOOST_REQUIRE_GT(g_recCache->get(now, target, QType(QType::A), true, &cached, who), 0);
40 BOOST_REQUIRE_EQUAL(cached.size(), 1U);
41 BOOST_REQUIRE_EQUAL(QType(cached.at(0).d_type).getName(), QType(QType::A).getName());
42 BOOST_CHECK_EQUAL(getRR<ARecordContent>(cached.at(0))->getCA().toString(), ComboAddress("192.0.2.2").toString());
43 }
44
45 BOOST_AUTO_TEST_CASE(test_delegation_only)
46 {
47 std::unique_ptr<SyncRes> sr;
48 initSR(sr);
49
50 primeHints();
51
52 /* Thanks, Verisign */
53 SyncRes::addDelegationOnly(DNSName("com."));
54 SyncRes::addDelegationOnly(DNSName("net."));
55
56 const DNSName target("nx-powerdns.com.");
57
58 sr->setAsyncCallback([target](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, LWResult* res, bool* chained) {
59 if (isRootServer(ip)) {
60 setLWResult(res, 0, false, false, true);
61 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
62 addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
63 return LWResult::Result::Success;
64 }
65 else if (ip == ComboAddress("192.0.2.1:53")) {
66
67 setLWResult(res, 0, true, false, true);
68 addRecordToLW(res, domain, QType::A, "192.0.2.42");
69 return LWResult::Result::Success;
70 }
71
72 return LWResult::Result::Timeout;
73 });
74
75 vector<DNSRecord> ret;
76 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
77 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
78 BOOST_CHECK_EQUAL(ret.size(), 0U);
79 }
80
81 BOOST_AUTO_TEST_CASE(test_unauth_any)
82 {
83 std::unique_ptr<SyncRes> sr;
84 initSR(sr);
85
86 primeHints();
87
88 const DNSName target("powerdns.com.");
89
90 sr->setAsyncCallback([target](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, LWResult* res, bool* chained) {
91 if (isRootServer(ip)) {
92 setLWResult(res, 0, false, false, true);
93 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
94 addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
95 return LWResult::Result::Success;
96 }
97 else if (ip == ComboAddress("192.0.2.1:53")) {
98
99 setLWResult(res, 0, false, false, true);
100 addRecordToLW(res, domain, QType::A, "192.0.2.42");
101 return LWResult::Result::Success;
102 }
103
104 return LWResult::Result::Timeout;
105 });
106
107 vector<DNSRecord> ret;
108 int res = sr->beginResolve(target, QType(QType::ANY), QClass::IN, ret);
109 BOOST_CHECK_EQUAL(res, RCode::ServFail);
110 BOOST_CHECK_EQUAL(ret.size(), 0U);
111 }
112
113 static void test_no_data_f(bool qmin)
114 {
115 std::unique_ptr<SyncRes> sr;
116 initSR(sr);
117 if (qmin)
118 sr->setQNameMinimization();
119
120 primeHints();
121
122 const DNSName target("powerdns.com.");
123
124 sr->setAsyncCallback(
125 [target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level,
126 struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context,
127 LWResult* res, bool* chained) {
128 setLWResult(res, 0, true, false, true);
129 return LWResult::Result::Success;
130 });
131
132 vector<DNSRecord> ret;
133 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
134 BOOST_CHECK_EQUAL(res, RCode::NoError);
135 BOOST_CHECK_EQUAL(ret.size(), 0U);
136 }
137
138 BOOST_AUTO_TEST_CASE(test_no_data)
139 {
140 test_no_data_f(false);
141 }
142
143 BOOST_AUTO_TEST_CASE(test_no_data_qmin)
144 {
145 test_no_data_f(true);
146 }
147
148 BOOST_AUTO_TEST_CASE(test_skip_opt_any)
149 {
150 std::unique_ptr<SyncRes> sr;
151 initSR(sr);
152
153 primeHints();
154
155 const DNSName target("powerdns.com.");
156
157 sr->setAsyncCallback([target](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, LWResult* res, bool* chained) {
158 setLWResult(res, 0, true, false, true);
159 addRecordToLW(res, domain, QType::A, "192.0.2.42");
160 addRecordToLW(res, domain, QType::ANY, "\\# 0");
161 addRecordToLW(res, domain, QType::OPT, "");
162 return LWResult::Result::Success;
163 });
164
165 vector<DNSRecord> ret;
166 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
167 BOOST_CHECK_EQUAL(res, RCode::NoError);
168 BOOST_CHECK_EQUAL(ret.size(), 1U);
169 }
170
171 BOOST_AUTO_TEST_CASE(test_nodata_nsec_nodnssec)
172 {
173 std::unique_ptr<SyncRes> sr;
174 initSR(sr);
175
176 primeHints();
177
178 const DNSName target("powerdns.com.");
179
180 sr->setAsyncCallback([target](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, LWResult* res, bool* chained) {
181 setLWResult(res, 0, true, false, true);
182 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
183 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
184 addRecordToLW(res, domain, QType::NSEC, "deadbeef", DNSResourceRecord::AUTHORITY);
185 addRecordToLW(res, domain, QType::RRSIG, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY);
186 addRecordToLW(res, domain, QType::RRSIG, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY);
187 return LWResult::Result::Success;
188 });
189
190 vector<DNSRecord> ret;
191 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
192 BOOST_CHECK_EQUAL(res, RCode::NoError);
193 BOOST_CHECK_EQUAL(ret.size(), 1U);
194 }
195
196 BOOST_AUTO_TEST_CASE(test_nodata_nsec_dnssec)
197 {
198 std::unique_ptr<SyncRes> sr;
199 initSR(sr, true);
200
201 primeHints();
202
203 const DNSName target("powerdns.com.");
204
205 sr->setAsyncCallback([target](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, LWResult* res, bool* chained) {
206 setLWResult(res, 0, true, false, true);
207 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
208 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
209 addRecordToLW(res, domain, QType::NSEC, "deadbeef", DNSResourceRecord::AUTHORITY);
210 addRecordToLW(res, domain, QType::RRSIG, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY);
211 addRecordToLW(res, domain, QType::RRSIG, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY);
212 return LWResult::Result::Success;
213 });
214
215 vector<DNSRecord> ret;
216 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
217 BOOST_CHECK_EQUAL(res, RCode::NoError);
218 BOOST_CHECK_EQUAL(ret.size(), 4U);
219 }
220
221 BOOST_AUTO_TEST_CASE(test_nx_nsec_nodnssec)
222 {
223 std::unique_ptr<SyncRes> sr;
224 initSR(sr);
225
226 primeHints();
227
228 const DNSName target("powerdns.com.");
229
230 sr->setAsyncCallback([target](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, LWResult* res, bool* chained) {
231 setLWResult(res, RCode::NXDomain, true, false, true);
232 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
233 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
234 addRecordToLW(res, domain, QType::NSEC, "deadbeef", DNSResourceRecord::AUTHORITY);
235 addRecordToLW(res, domain, QType::RRSIG, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY);
236 addRecordToLW(res, domain, QType::RRSIG, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY);
237 return LWResult::Result::Success;
238 });
239
240 vector<DNSRecord> ret;
241 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
242 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
243 BOOST_CHECK_EQUAL(ret.size(), 1U);
244 }
245
246 BOOST_AUTO_TEST_CASE(test_nx_nsec_dnssec)
247 {
248 std::unique_ptr<SyncRes> sr;
249 initSR(sr, true);
250
251 primeHints();
252
253 const DNSName target("powerdns.com.");
254
255 sr->setAsyncCallback([target](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, LWResult* res, bool* chained) {
256 setLWResult(res, RCode::NXDomain, true, false, true);
257 addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
258 /* the NSEC and RRSIG contents are complete garbage, please ignore them */
259 addRecordToLW(res, domain, QType::NSEC, "deadbeef", DNSResourceRecord::AUTHORITY);
260 addRecordToLW(res, domain, QType::RRSIG, "NSEC 5 2 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY);
261 addRecordToLW(res, domain, QType::RRSIG, "SOA 5 3 600 2100010100000000 2100010100000000 24567 dummy data", DNSResourceRecord::AUTHORITY);
262 return LWResult::Result::Success;
263 });
264
265 vector<DNSRecord> ret;
266 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
267 BOOST_CHECK_EQUAL(res, RCode::NXDomain);
268 BOOST_CHECK_EQUAL(ret.size(), 4U);
269 }
270
271 BOOST_AUTO_TEST_CASE(test_qclass_none)
272 {
273 std::unique_ptr<SyncRes> sr;
274 initSR(sr);
275
276 primeHints();
277
278 /* apart from special names and QClass::ANY, anything else than QClass::IN should be rejected right away */
279 size_t queriesCount = 0;
280
281 sr->setAsyncCallback([&queriesCount](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, LWResult* res, bool* chained) {
282 queriesCount++;
283 return LWResult::Result::Timeout;
284 });
285
286 const DNSName target("powerdns.com.");
287 vector<DNSRecord> ret;
288 int res = sr->beginResolve(target, QType(QType::A), QClass::NONE, ret);
289 BOOST_CHECK_EQUAL(res, -1);
290 BOOST_CHECK_EQUAL(ret.size(), 0U);
291 BOOST_CHECK_EQUAL(queriesCount, 0U);
292 }
293
294 BOOST_AUTO_TEST_CASE(test_answer_no_aa)
295 {
296 std::unique_ptr<SyncRes> sr;
297 initSR(sr, true);
298
299 primeHints();
300
301 const DNSName target("powerdns.com.");
302
303 sr->setAsyncCallback([target](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, LWResult* res, bool* chained) {
304 setLWResult(res, 0, false, false, true);
305 addRecordToLW(res, domain, QType::A, "192.0.2.1");
306 return LWResult::Result::Success;
307 });
308
309 const time_t now = sr->getNow().tv_sec;
310
311 vector<DNSRecord> ret;
312 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
313 BOOST_CHECK_EQUAL(res, RCode::ServFail);
314 BOOST_CHECK_EQUAL(ret.size(), 0U);
315
316 /* check that the record in the answer section has not been cached */
317 const ComboAddress who;
318 vector<DNSRecord> cached;
319 vector<std::shared_ptr<RRSIGRecordContent>> signatures;
320 BOOST_REQUIRE_EQUAL(g_recCache->get(now, target, QType(QType::A), false, &cached, who, boost::none, &signatures), -1);
321 }
322
323 BOOST_AUTO_TEST_CASE(test_special_types)
324 {
325 std::unique_ptr<SyncRes> sr;
326 initSR(sr);
327
328 primeHints();
329
330 /* {A,I}XFR, RRSIG and NSEC3 should be rejected right away */
331 size_t queriesCount = 0;
332
333 sr->setAsyncCallback([&queriesCount](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, LWResult* res, bool* chained) {
334 cerr << "asyncresolve called to ask " << ip.toStringWithPort() << " about " << domain.toString() << " / " << QType(type).getName() << " over " << (doTCP ? "TCP" : "UDP") << " (rd: " << sendRDQuery << ", EDNS0 level: " << EDNS0Level << ")" << endl;
335 queriesCount++;
336 return LWResult::Result::Timeout;
337 });
338
339 const DNSName target("powerdns.com.");
340 vector<DNSRecord> ret;
341 int res = sr->beginResolve(target, QType(QType::AXFR), QClass::IN, ret);
342 BOOST_CHECK_EQUAL(res, -1);
343 BOOST_CHECK_EQUAL(ret.size(), 0U);
344 BOOST_CHECK_EQUAL(queriesCount, 0U);
345
346 res = sr->beginResolve(target, QType(QType::IXFR), QClass::IN, ret);
347 BOOST_CHECK_EQUAL(res, -1);
348 BOOST_CHECK_EQUAL(ret.size(), 0U);
349 BOOST_CHECK_EQUAL(queriesCount, 0U);
350
351 res = sr->beginResolve(target, QType(QType::RRSIG), QClass::IN, ret);
352 BOOST_CHECK_EQUAL(res, -1);
353 BOOST_CHECK_EQUAL(ret.size(), 0U);
354 BOOST_CHECK_EQUAL(queriesCount, 0U);
355
356 res = sr->beginResolve(target, QType(QType::NSEC3), QClass::IN, ret);
357 BOOST_CHECK_EQUAL(res, -1);
358 BOOST_CHECK_EQUAL(ret.size(), 0U);
359 BOOST_CHECK_EQUAL(queriesCount, 0U);
360 }
361
362 BOOST_AUTO_TEST_CASE(test_special_names)
363 {
364 std::unique_ptr<SyncRes> sr;
365 initSR(sr);
366
367 primeHints();
368
369 /* special names should be handled internally */
370
371 size_t queriesCount = 0;
372
373 sr->setAsyncCallback([&queriesCount](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, LWResult* res, bool* chained) {
374 queriesCount++;
375 return LWResult::Result::Timeout;
376 });
377
378 vector<DNSRecord> ret;
379 int res = sr->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::PTR), QClass::IN, ret);
380 BOOST_CHECK_EQUAL(res, RCode::NoError);
381 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
382 BOOST_CHECK(ret[0].d_type == QType::PTR);
383 BOOST_CHECK_EQUAL(queriesCount, 0U);
384
385 ret.clear();
386 res = sr->beginResolve(DNSName("1.0.0.127.in-addr.arpa."), QType(QType::ANY), QClass::IN, ret);
387 BOOST_CHECK_EQUAL(res, RCode::NoError);
388 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
389 BOOST_CHECK(ret[0].d_type == QType::PTR);
390 BOOST_CHECK_EQUAL(queriesCount, 0U);
391
392 ret.clear();
393 res = sr->beginResolve(DNSName("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa."), QType(QType::PTR), QClass::IN, ret);
394 BOOST_CHECK_EQUAL(res, RCode::NoError);
395 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
396 BOOST_CHECK(ret[0].d_type == QType::PTR);
397 BOOST_CHECK_EQUAL(queriesCount, 0U);
398
399 ret.clear();
400 res = sr->beginResolve(DNSName("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa."), QType(QType::ANY), QClass::IN, ret);
401 BOOST_CHECK_EQUAL(res, RCode::NoError);
402 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
403 BOOST_CHECK(ret[0].d_type == QType::PTR);
404 BOOST_CHECK_EQUAL(queriesCount, 0U);
405
406 ret.clear();
407 res = sr->beginResolve(DNSName("localhost."), QType(QType::A), QClass::IN, ret);
408 BOOST_CHECK_EQUAL(res, RCode::NoError);
409 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
410 BOOST_CHECK(ret[0].d_type == QType::A);
411 BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toString(), "127.0.0.1");
412 BOOST_CHECK_EQUAL(queriesCount, 0U);
413
414 ret.clear();
415 res = sr->beginResolve(DNSName("localhost."), QType(QType::AAAA), QClass::IN, ret);
416 BOOST_CHECK_EQUAL(res, RCode::NoError);
417 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
418 BOOST_CHECK(ret[0].d_type == QType::AAAA);
419 BOOST_CHECK_EQUAL(getRR<AAAARecordContent>(ret[0])->getCA().toString(), "::1");
420 BOOST_CHECK_EQUAL(queriesCount, 0U);
421
422 ret.clear();
423 res = sr->beginResolve(DNSName("localhost."), QType(QType::ANY), QClass::IN, ret);
424 BOOST_CHECK_EQUAL(res, RCode::NoError);
425 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
426 for (const auto& rec : ret) {
427 BOOST_REQUIRE((rec.d_type == QType::A) || rec.d_type == QType::AAAA);
428 if (rec.d_type == QType::A) {
429 BOOST_CHECK_EQUAL(getRR<ARecordContent>(rec)->getCA().toString(), "127.0.0.1");
430 }
431 else {
432 BOOST_CHECK_EQUAL(getRR<AAAARecordContent>(rec)->getCA().toString(), "::1");
433 }
434 }
435 BOOST_CHECK_EQUAL(queriesCount, 0U);
436
437 ret.clear();
438 res = sr->beginResolve(DNSName("version.bind."), QType(QType::TXT), QClass::CHAOS, ret);
439 BOOST_CHECK_EQUAL(res, RCode::NoError);
440 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
441 BOOST_CHECK(ret[0].d_type == QType::TXT);
442 BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests\"");
443 BOOST_CHECK_EQUAL(queriesCount, 0U);
444
445 ret.clear();
446 res = sr->beginResolve(DNSName("version.bind."), QType(QType::ANY), QClass::CHAOS, ret);
447 BOOST_CHECK_EQUAL(res, RCode::NoError);
448 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
449 BOOST_CHECK(ret[0].d_type == QType::TXT);
450 BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests\"");
451 BOOST_CHECK_EQUAL(queriesCount, 0U);
452
453 ret.clear();
454 res = sr->beginResolve(DNSName("version.pdns."), QType(QType::TXT), QClass::CHAOS, ret);
455 BOOST_CHECK_EQUAL(res, RCode::NoError);
456 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
457 BOOST_CHECK(ret[0].d_type == QType::TXT);
458 BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests\"");
459 BOOST_CHECK_EQUAL(queriesCount, 0U);
460
461 ret.clear();
462 res = sr->beginResolve(DNSName("version.pdns."), QType(QType::ANY), QClass::CHAOS, ret);
463 BOOST_CHECK_EQUAL(res, RCode::NoError);
464 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
465 BOOST_CHECK(ret[0].d_type == QType::TXT);
466 BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests\"");
467 BOOST_CHECK_EQUAL(queriesCount, 0U);
468
469 ret.clear();
470 res = sr->beginResolve(DNSName("id.server."), QType(QType::TXT), QClass::CHAOS, ret);
471 BOOST_CHECK_EQUAL(res, RCode::NoError);
472 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
473 BOOST_CHECK(ret[0].d_type == QType::TXT);
474 BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests Server ID\"");
475 BOOST_CHECK_EQUAL(queriesCount, 0U);
476
477 ret.clear();
478 res = sr->beginResolve(DNSName("id.server."), QType(QType::ANY), QClass::CHAOS, ret);
479 BOOST_CHECK_EQUAL(res, RCode::NoError);
480 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
481 BOOST_CHECK(ret[0].d_type == QType::TXT);
482 BOOST_CHECK_EQUAL(getRR<TXTRecordContent>(ret[0])->d_text, "\"PowerDNS Unit Tests Server ID\"");
483 BOOST_CHECK_EQUAL(queriesCount, 0U);
484 }
485
486 BOOST_AUTO_TEST_CASE(test_nameserver_ipv4_rpz)
487 {
488 std::unique_ptr<SyncRes> sr;
489 initSR(sr);
490
491 primeHints();
492
493 const DNSName target("rpz.powerdns.com.");
494 const ComboAddress ns("192.0.2.1:53");
495
496 sr->setAsyncCallback([target, ns](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, LWResult* res, bool* chained) {
497 if (isRootServer(ip)) {
498 setLWResult(res, false, true, false, true);
499 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
500 addRecordToLW(res, "a.gtld-servers.net.", QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
501 return LWResult::Result::Success;
502 }
503 else if (ip == ns) {
504
505 setLWResult(res, 0, true, false, true);
506 addRecordToLW(res, domain, QType::A, "192.0.2.42");
507 return LWResult::Result::Success;
508 }
509
510 return LWResult::Result::Timeout;
511 });
512
513 DNSFilterEngine::Policy pol;
514 pol.d_kind = DNSFilterEngine::PolicyKind::Drop;
515 std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>();
516 zone->setName("Unit test policy 0");
517 zone->addNSIPTrigger(Netmask(ns, 32), std::move(pol));
518 auto luaconfsCopy = g_luaconfs.getCopy();
519 luaconfsCopy.dfe.clearZones();
520 luaconfsCopy.dfe.addZone(zone);
521 g_luaconfs.setState(luaconfsCopy);
522
523 vector<DNSRecord> ret;
524 BOOST_CHECK_THROW(sr->beginResolve(target, QType(QType::A), QClass::IN, ret), PolicyHitException);
525 }
526
527 BOOST_AUTO_TEST_CASE(test_nameserver_ipv6_rpz)
528 {
529 std::unique_ptr<SyncRes> sr;
530 initSR(sr);
531
532 primeHints();
533
534 const DNSName target("rpz.powerdns.com.");
535 const ComboAddress ns("[2001:DB8::42]:53");
536
537 sr->setAsyncCallback([target, ns](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, LWResult* res, bool* chained) {
538 if (isRootServer(ip)) {
539 setLWResult(res, 0, false, false, true);
540 addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
541 addRecordToLW(res, "a.gtld-servers.net.", QType::AAAA, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
542 return LWResult::Result::Success;
543 }
544 else if (ip == ns) {
545
546 setLWResult(res, 0, true, false, true);
547 addRecordToLW(res, domain, QType::A, "192.0.2.42");
548 return LWResult::Result::Success;
549 }
550
551 return LWResult::Result::Timeout;
552 });
553
554 DNSFilterEngine::Policy pol;
555 pol.d_kind = DNSFilterEngine::PolicyKind::Drop;
556 std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>();
557 zone->setName("Unit test policy 0");
558 zone->addNSIPTrigger(Netmask(ns, 128), std::move(pol));
559 auto luaconfsCopy = g_luaconfs.getCopy();
560 luaconfsCopy.dfe.clearZones();
561 luaconfsCopy.dfe.addZone(zone);
562 g_luaconfs.setState(luaconfsCopy);
563
564 vector<DNSRecord> ret;
565 BOOST_CHECK_THROW(sr->beginResolve(target, QType(QType::A), QClass::IN, ret), PolicyHitException);
566 }
567
568 BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz)
569 {
570 std::unique_ptr<SyncRes> sr;
571 initSR(sr);
572
573 primeHints();
574
575 const DNSName target("rpz.powerdns.com.");
576 const ComboAddress ns("192.0.2.1:53");
577 const DNSName nsName("ns1.powerdns.com.");
578
579 sr->setAsyncCallback([target, ns, nsName](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, LWResult* res, bool* chained) {
580 if (isRootServer(ip)) {
581 setLWResult(res, 0, false, false, true);
582 addRecordToLW(res, domain, QType::NS, nsName.toString(), DNSResourceRecord::AUTHORITY, 172800);
583 addRecordToLW(res, nsName, QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
584 return LWResult::Result::Success;
585 }
586 else if (ip == ns) {
587
588 setLWResult(res, 0, true, false, true);
589 addRecordToLW(res, domain, QType::A, "192.0.2.42");
590 return LWResult::Result::Success;
591 }
592
593 return LWResult::Result::Timeout;
594 });
595
596 DNSFilterEngine::Policy pol;
597 pol.d_kind = DNSFilterEngine::PolicyKind::Drop;
598 std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>();
599 zone->setName("Unit test policy 0");
600 zone->addNSTrigger(nsName, std::move(pol));
601 auto luaconfsCopy = g_luaconfs.getCopy();
602 luaconfsCopy.dfe.clearZones();
603 luaconfsCopy.dfe.addZone(zone);
604 g_luaconfs.setState(luaconfsCopy);
605
606 vector<DNSRecord> ret;
607 BOOST_CHECK_THROW(sr->beginResolve(target, QType(QType::A), QClass::IN, ret), PolicyHitException);
608 }
609
610 BOOST_AUTO_TEST_CASE(test_nameserver_name_rpz_disabled)
611 {
612 std::unique_ptr<SyncRes> sr;
613 initSR(sr);
614
615 primeHints();
616
617 const DNSName target("rpz.powerdns.com.");
618 const ComboAddress ns("192.0.2.1:53");
619 const DNSName nsName("ns1.powerdns.com.");
620
621 sr->setAsyncCallback([target, ns, nsName](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, LWResult* res, bool* chained) {
622 if (isRootServer(ip)) {
623 setLWResult(res, 0, false, false, true);
624 addRecordToLW(res, domain, QType::NS, nsName.toString(), DNSResourceRecord::AUTHORITY, 172800);
625 addRecordToLW(res, nsName, QType::A, ns.toString(), DNSResourceRecord::ADDITIONAL, 3600);
626 return LWResult::Result::Success;
627 }
628 else if (ip == ns) {
629
630 setLWResult(res, 0, true, false, true);
631 addRecordToLW(res, domain, QType::A, "192.0.2.42");
632 return LWResult::Result::Success;
633 }
634
635 return LWResult::Result::Timeout;
636 });
637
638 DNSFilterEngine::Policy pol;
639 pol.d_kind = DNSFilterEngine::PolicyKind::Drop;
640 std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>();
641 zone->setName("Unit test policy 0");
642 zone->addNSIPTrigger(Netmask(ns, 128), DNSFilterEngine::Policy(pol));
643 zone->addNSTrigger(nsName, std::move(pol));
644 auto luaconfsCopy = g_luaconfs.getCopy();
645 luaconfsCopy.dfe.clearZones();
646 luaconfsCopy.dfe.addZone(zone);
647 g_luaconfs.setState(luaconfsCopy);
648
649 /* RPZ is disabled for this query, we should not be blocked */
650 sr->setWantsRPZ(false);
651
652 vector<DNSRecord> ret;
653 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
654 BOOST_CHECK_EQUAL(res, RCode::NoError);
655 BOOST_CHECK_EQUAL(ret.size(), 1U);
656 }
657
658 BOOST_AUTO_TEST_CASE(test_forward_zone_nord)
659 {
660 std::unique_ptr<SyncRes> sr;
661 initSR(sr);
662
663 primeHints();
664
665 const DNSName target("powerdns.com.");
666 const ComboAddress ns("192.0.2.1:53");
667 const ComboAddress forwardedNS("192.0.2.42:53");
668
669 SyncRes::AuthDomain ad;
670 ad.d_rdForward = false;
671 ad.d_servers.push_back(forwardedNS);
672 (*SyncRes::t_sstorage.domainmap)[target] = ad;
673
674 sr->setAsyncCallback([forwardedNS](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, LWResult* res, bool* chained) {
675 if (ip == forwardedNS) {
676 BOOST_CHECK_EQUAL(sendRDQuery, false);
677
678 setLWResult(res, 0, true, false, true);
679 addRecordToLW(res, domain, QType::A, "192.0.2.42");
680 return LWResult::Result::Success;
681 }
682
683 return LWResult::Result::Timeout;
684 });
685
686 /* simulate a no-RD query */
687 sr->setCacheOnly();
688
689 vector<DNSRecord> ret;
690 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
691 BOOST_CHECK_EQUAL(res, RCode::NoError);
692 BOOST_CHECK_EQUAL(ret.size(), 1U);
693 }
694
695 BOOST_AUTO_TEST_CASE(test_forward_zone_rd)
696 {
697 std::unique_ptr<SyncRes> sr;
698 initSR(sr);
699
700 primeHints();
701
702 const DNSName target("powerdns.com.");
703 const ComboAddress ns("192.0.2.1:53");
704 const ComboAddress forwardedNS("192.0.2.42:53");
705
706 size_t queriesCount = 0;
707 SyncRes::AuthDomain ad;
708 ad.d_rdForward = true;
709 ad.d_servers.push_back(forwardedNS);
710 (*SyncRes::t_sstorage.domainmap)[target] = ad;
711
712 sr->setAsyncCallback([forwardedNS, &queriesCount](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, LWResult* res, bool* chained) {
713 queriesCount++;
714
715 if (ip == forwardedNS) {
716 BOOST_CHECK_EQUAL(sendRDQuery, true);
717
718 /* set AA=0, we are a recursor */
719 setLWResult(res, 0, false, false, true);
720 addRecordToLW(res, domain, QType::A, "192.0.2.42");
721 return LWResult::Result::Success;
722 }
723
724 return LWResult::Result::Timeout;
725 });
726
727 vector<DNSRecord> ret;
728 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
729 BOOST_CHECK_EQUAL(res, RCode::NoError);
730 BOOST_CHECK_EQUAL(ret.size(), 1U);
731 BOOST_CHECK_EQUAL(queriesCount, 1U);
732
733 /* now make sure we can resolve from the cache (see #6340
734 where the entries were added to the cache but not retrieved,
735 because the recursor doesn't set the AA bit and we require
736 it. We fixed it by not requiring the AA bit for forward-recurse
737 answers. */
738 ret.clear();
739 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
740 BOOST_CHECK_EQUAL(res, RCode::NoError);
741 BOOST_CHECK_EQUAL(ret.size(), 1U);
742 BOOST_CHECK_EQUAL(queriesCount, 1U);
743 }
744
745 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_nord)
746 {
747 std::unique_ptr<SyncRes> sr;
748 initSR(sr);
749
750 primeHints();
751
752 const DNSName target("powerdns.com.");
753 const ComboAddress ns("192.0.2.1:53");
754 const ComboAddress forwardedNS("192.0.2.42:53");
755
756 SyncRes::AuthDomain ad;
757 ad.d_rdForward = true;
758 ad.d_servers.push_back(forwardedNS);
759 (*SyncRes::t_sstorage.domainmap)[target] = ad;
760
761 sr->setAsyncCallback([forwardedNS](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, LWResult* res, bool* chained) {
762 if (ip == forwardedNS) {
763 BOOST_CHECK_EQUAL(sendRDQuery, false);
764
765 setLWResult(res, 0, true, false, true);
766 addRecordToLW(res, domain, QType::A, "192.0.2.42");
767 return LWResult::Result::Success;
768 }
769
770 return LWResult::Result::Timeout;
771 });
772
773 /* simulate a no-RD query */
774 sr->setCacheOnly();
775
776 vector<DNSRecord> ret;
777 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
778 BOOST_CHECK_EQUAL(res, RCode::NoError);
779 BOOST_CHECK_EQUAL(ret.size(), 1U);
780 }
781
782 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd)
783 {
784 std::unique_ptr<SyncRes> sr;
785 initSR(sr);
786
787 primeHints();
788
789 const DNSName target("powerdns.com.");
790 const ComboAddress ns("192.0.2.1:53");
791 const ComboAddress forwardedNS("192.0.2.42:53");
792
793 SyncRes::AuthDomain ad;
794 ad.d_rdForward = true;
795 ad.d_servers.push_back(forwardedNS);
796 (*SyncRes::t_sstorage.domainmap)[target] = ad;
797
798 sr->setAsyncCallback([forwardedNS](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, LWResult* res, bool* chained) {
799 if (ip == forwardedNS) {
800 BOOST_CHECK_EQUAL(sendRDQuery, true);
801
802 setLWResult(res, 0, true, false, true);
803 addRecordToLW(res, domain, QType::A, "192.0.2.42");
804 return LWResult::Result::Success;
805 }
806
807 return LWResult::Result::Timeout;
808 });
809
810 vector<DNSRecord> ret;
811 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
812 BOOST_CHECK_EQUAL(res, RCode::NoError);
813 BOOST_CHECK_EQUAL(ret.size(), 1U);
814 }
815
816 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd_dnssec)
817 {
818 std::unique_ptr<SyncRes> sr;
819 initSR(sr, true);
820
821 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
822
823 primeHints();
824 /* signed */
825 const DNSName target("test.");
826 /* unsigned */
827 const DNSName cnameTarget("cname.");
828 testkeysset_t keys;
829
830 auto luaconfsCopy = g_luaconfs.getCopy();
831 luaconfsCopy.dsAnchors.clear();
832 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
833 generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
834 g_luaconfs.setState(luaconfsCopy);
835
836 const ComboAddress forwardedNS("192.0.2.42:53");
837 size_t queriesCount = 0;
838
839 SyncRes::AuthDomain ad;
840 ad.d_rdForward = true;
841 ad.d_servers.push_back(forwardedNS);
842 (*SyncRes::t_sstorage.domainmap)[g_rootdnsname] = ad;
843
844 sr->setAsyncCallback([target, cnameTarget, keys, forwardedNS, &queriesCount](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, LWResult* res, bool* chained) {
845 queriesCount++;
846
847 BOOST_CHECK_EQUAL(sendRDQuery, true);
848
849 if (ip != forwardedNS) {
850 return LWResult::Result::Timeout;
851 }
852
853 if (type == QType::DS || type == QType::DNSKEY) {
854 return genericDSAndDNSKEYHandler(res, domain, DNSName("."), type, keys);
855 }
856
857 if (domain == target && type == QType::A) {
858
859 setLWResult(res, 0, false, false, true);
860 addRecordToLW(res, target, QType::CNAME, cnameTarget.toString());
861 addRRSIG(keys, res->d_records, domain, 300);
862 addRecordToLW(res, cnameTarget, QType::A, "192.0.2.1");
863
864 return LWResult::Result::Success;
865 }
866 return LWResult::Result::Timeout;
867 });
868
869 vector<DNSRecord> ret;
870 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
871 BOOST_CHECK_EQUAL(res, RCode::NoError);
872 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
873 BOOST_REQUIRE_EQUAL(ret.size(), 3U);
874 BOOST_CHECK_EQUAL(queriesCount, 5U);
875
876 /* again, to test the cache */
877 ret.clear();
878 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
879 BOOST_CHECK_EQUAL(res, RCode::NoError);
880 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Insecure);
881 BOOST_REQUIRE_EQUAL(ret.size(), 3U);
882 BOOST_CHECK_EQUAL(queriesCount, 5U);
883 }
884
885 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_nord_dnssec)
886 {
887 std::unique_ptr<SyncRes> sr;
888 initSR(sr, true);
889
890 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
891
892 primeHints();
893 /* signed */
894 const DNSName parent("test.");
895 const DNSName target1("a.test.");
896 const DNSName target2("b.test.");
897
898 testkeysset_t keys;
899
900 auto luaconfsCopy = g_luaconfs.getCopy();
901 luaconfsCopy.dsAnchors.clear();
902 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
903 generateKeyMaterial(DNSName("test."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
904 g_luaconfs.setState(luaconfsCopy);
905
906 const ComboAddress forwardedNS("192.0.2.42:53");
907 size_t queriesCount = 0;
908 size_t DSforParentCount = 0;
909
910 SyncRes::AuthDomain ad;
911 ad.d_rdForward = false;
912 ad.d_servers.push_back(forwardedNS);
913 (*SyncRes::t_sstorage.domainmap)[DNSName("test.")] = ad;
914
915 sr->setAsyncCallback([parent, target1, target2, keys, forwardedNS, &queriesCount, &DSforParentCount](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, LWResult* res, bool* chained) {
916 queriesCount++;
917
918 BOOST_CHECK_EQUAL(sendRDQuery, false);
919
920 if (type == QType::DS && domain == parent) {
921 DSforParentCount++;
922 }
923 if (type == QType::DS || type == QType::DNSKEY) {
924 if (domain != parent && domain.isPartOf(parent)) {
925 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys, false /* no cut / delegation */);
926 }
927 else {
928 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
929 }
930 }
931
932 if (isRootServer(ip)) {
933 setLWResult(res, 0, false, false, true);
934 addRecordToLW(res, parent, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 42);
935 addRRSIG(keys, res->d_records, g_rootdnsname, 300);
936 addRecordToLW(res, "a.gtld-servers.net.", QType::A, "192.0.2.1", DNSResourceRecord::ADDITIONAL, 3600);
937 }
938
939 if (ip != forwardedNS) {
940 return LWResult::Result::Timeout;
941 }
942
943 if (domain == target1 && type == QType::A) {
944
945 setLWResult(res, 0, true, false, true);
946 addRecordToLW(res, target1, QType::A, "192.0.2.1");
947 addRRSIG(keys, res->d_records, parent, 300);
948
949 return LWResult::Result::Success;
950 }
951 if (domain == target2 && type == QType::A) {
952
953 setLWResult(res, 0, true, false, true);
954 addRecordToLW(res, target2, QType::A, "192.0.2.2");
955 addRRSIG(keys, res->d_records, parent, 300);
956
957 return LWResult::Result::Success;
958 }
959
960 return LWResult::Result::Timeout;
961 });
962
963 vector<DNSRecord> ret;
964 int res = sr->beginResolve(target1, QType(QType::A), QClass::IN, ret);
965 BOOST_CHECK_EQUAL(res, RCode::NoError);
966 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
967 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
968 BOOST_CHECK_EQUAL(queriesCount, 5U);
969 BOOST_CHECK_EQUAL(DSforParentCount, 1U);
970
971 /* again, to test the cache */
972 ret.clear();
973 res = sr->beginResolve(target1, QType(QType::A), QClass::IN, ret);
974 BOOST_CHECK_EQUAL(res, RCode::NoError);
975 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
976 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
977 BOOST_CHECK_EQUAL(queriesCount, 5U);
978 BOOST_CHECK_EQUAL(DSforParentCount, 1U);
979
980 /* new target should no cause a DS query for tets. */
981 ret.clear();
982 res = sr->beginResolve(target2, QType(QType::A), QClass::IN, ret);
983 BOOST_CHECK_EQUAL(res, RCode::NoError);
984 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Secure);
985 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
986 BOOST_CHECK_EQUAL(queriesCount, 7U);
987 BOOST_CHECK_EQUAL(DSforParentCount, 1U);
988 }
989
990 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd_dnssec_bogus)
991 {
992 std::unique_ptr<SyncRes> sr;
993 initSR(sr, true);
994
995 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
996
997 primeHints();
998 /* signed */
999 const DNSName target("test.");
1000 /* signed */
1001 const DNSName cnameTarget("cname.");
1002 testkeysset_t keys;
1003
1004 auto luaconfsCopy = g_luaconfs.getCopy();
1005 luaconfsCopy.dsAnchors.clear();
1006 generateKeyMaterial(g_rootdnsname, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
1007 generateKeyMaterial(target, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
1008 generateKeyMaterial(cnameTarget, DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
1009 g_luaconfs.setState(luaconfsCopy);
1010
1011 const ComboAddress forwardedNS("192.0.2.42:53");
1012 size_t queriesCount = 0;
1013
1014 SyncRes::AuthDomain ad;
1015 ad.d_rdForward = true;
1016 ad.d_servers.push_back(forwardedNS);
1017 (*SyncRes::t_sstorage.domainmap)[g_rootdnsname] = ad;
1018
1019 sr->setAsyncCallback([target, cnameTarget, keys, forwardedNS, &queriesCount](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, LWResult* res, bool* chained) {
1020 queriesCount++;
1021
1022 BOOST_CHECK_EQUAL(sendRDQuery, true);
1023
1024 if (ip != forwardedNS) {
1025 return LWResult::Result::Timeout;
1026 }
1027
1028 if (type == QType::DS || type == QType::DNSKEY) {
1029 return genericDSAndDNSKEYHandler(res, domain, DNSName("."), type, keys);
1030 }
1031
1032 if (domain == target && type == QType::A) {
1033
1034 setLWResult(res, 0, false, false, true);
1035 addRecordToLW(res, target, QType::CNAME, cnameTarget.toString());
1036 addRRSIG(keys, res->d_records, domain, 300);
1037 addRecordToLW(res, cnameTarget, QType::A, "192.0.2.1");
1038 /* no RRSIG in a signed zone, Bogus ! */
1039
1040 return LWResult::Result::Success;
1041 }
1042 return LWResult::Result::Timeout;
1043 });
1044
1045 vector<DNSRecord> ret;
1046 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1047 BOOST_CHECK_EQUAL(res, RCode::NoError);
1048 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
1049 BOOST_REQUIRE_EQUAL(ret.size(), 3U);
1050 BOOST_CHECK_EQUAL(queriesCount, 5U);
1051
1052 /* again, to test the cache */
1053 ret.clear();
1054 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1055 BOOST_CHECK_EQUAL(res, RCode::NoError);
1056 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusNoRRSIG);
1057 BOOST_REQUIRE_EQUAL(ret.size(), 3U);
1058 BOOST_CHECK_EQUAL(queriesCount, 5U);
1059 }
1060
1061 BOOST_AUTO_TEST_CASE(test_forward_zone_recurse_rd_dnssec_nodata_bogus)
1062 {
1063 std::unique_ptr<SyncRes> sr;
1064 initSR(sr, true);
1065
1066 setDNSSECValidation(sr, DNSSECMode::ValidateAll);
1067
1068 primeHints();
1069 const DNSName target("powerdns.com.");
1070 testkeysset_t keys;
1071
1072 auto luaconfsCopy = g_luaconfs.getCopy();
1073 luaconfsCopy.dsAnchors.clear();
1074 generateKeyMaterial(DNSName("."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
1075 generateKeyMaterial(DNSName("com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
1076 generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
1077 g_luaconfs.setState(luaconfsCopy);
1078
1079 const ComboAddress forwardedNS("192.0.2.42:53");
1080 SyncRes::AuthDomain ad;
1081 ad.d_rdForward = true;
1082 ad.d_servers.push_back(forwardedNS);
1083 (*SyncRes::t_sstorage.domainmap)[g_rootdnsname] = ad;
1084
1085 size_t queriesCount = 0;
1086
1087 sr->setAsyncCallback([target, forwardedNS, &queriesCount, keys](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, LWResult* res, bool* chained) {
1088 queriesCount++;
1089
1090 BOOST_CHECK_EQUAL(sendRDQuery, true);
1091
1092 if (ip != forwardedNS) {
1093 return LWResult::Result::Timeout;
1094 }
1095
1096 if (type == QType::DS || type == QType::DNSKEY) {
1097 return genericDSAndDNSKEYHandler(res, domain, domain, type, keys);
1098 }
1099 else {
1100
1101 setLWResult(res, 0, false, false, true);
1102 return LWResult::Result::Success;
1103 }
1104
1105 return LWResult::Result::Timeout;
1106 });
1107
1108 vector<DNSRecord> ret;
1109 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1110 BOOST_CHECK_EQUAL(res, RCode::NoError);
1111 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusMissingNegativeIndication);
1112 BOOST_REQUIRE_EQUAL(ret.size(), 0U);
1113 /* com|NS, powerdns.com|NS, powerdns.com|A */
1114 BOOST_CHECK_EQUAL(queriesCount, 3U);
1115
1116 /* again, to test the cache */
1117 ret.clear();
1118 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1119 BOOST_CHECK_EQUAL(res, RCode::NoError);
1120 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::BogusMissingNegativeIndication);
1121 BOOST_REQUIRE_EQUAL(ret.size(), 0U);
1122 /* we don't store empty results */
1123 BOOST_CHECK_EQUAL(queriesCount, 4U);
1124 }
1125
1126 BOOST_AUTO_TEST_CASE(test_auth_zone_oob)
1127 {
1128 std::unique_ptr<SyncRes> sr;
1129 initSR(sr, true);
1130
1131 primeHints();
1132
1133 size_t queriesCount = 0;
1134 const DNSName target("test.xx.");
1135 const ComboAddress targetAddr("127.0.0.1");
1136 const DNSName authZone("test.xx");
1137
1138 SyncRes::AuthDomain ad;
1139 DNSRecord dr;
1140
1141 dr.d_place = DNSResourceRecord::ANSWER;
1142 dr.d_name = target;
1143 dr.d_type = QType::A;
1144 dr.d_ttl = 1800;
1145 dr.d_content = std::make_shared<ARecordContent>(targetAddr);
1146 ad.d_records.insert(dr);
1147
1148 (*SyncRes::t_sstorage.domainmap)[authZone] = ad;
1149
1150 sr->setAsyncCallback([&queriesCount](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, LWResult* res, bool* chained) {
1151 queriesCount++;
1152 return LWResult::Result::Timeout;
1153 });
1154
1155 vector<DNSRecord> ret;
1156 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1157 BOOST_CHECK_EQUAL(res, 0);
1158 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
1159 BOOST_CHECK(ret[0].d_type == QType::A);
1160 BOOST_CHECK_EQUAL(queriesCount, 0U);
1161 BOOST_CHECK(sr->wasOutOfBand());
1162 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Indeterminate);
1163
1164 /* a second time, to check that the OOB flag is set when the query cache is used */
1165 ret.clear();
1166 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1167 BOOST_CHECK_EQUAL(res, 0);
1168 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
1169 BOOST_CHECK(ret[0].d_type == QType::A);
1170 BOOST_CHECK_EQUAL(queriesCount, 0U);
1171 BOOST_CHECK(sr->wasOutOfBand());
1172 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Indeterminate);
1173
1174 /* a third time, to check that the validation is disabled when the OOB flag is set */
1175 ret.clear();
1176 sr->setDNSSECValidationRequested(true);
1177 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1178 BOOST_CHECK_EQUAL(res, 0);
1179 BOOST_REQUIRE_EQUAL(ret.size(), 1U);
1180 BOOST_CHECK(ret[0].d_type == QType::A);
1181 BOOST_CHECK_EQUAL(queriesCount, 0U);
1182 BOOST_CHECK(sr->wasOutOfBand());
1183 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Indeterminate);
1184 }
1185
1186 BOOST_AUTO_TEST_CASE(test_auth_zone_oob_cname)
1187 {
1188 std::unique_ptr<SyncRes> sr;
1189 initSR(sr, true);
1190
1191 primeHints();
1192
1193 size_t queriesCount = 0;
1194 const DNSName target("cname.test.xx.");
1195 const DNSName targetCname("cname-target.test.xx.");
1196 const ComboAddress targetCnameAddr("127.0.0.1");
1197 const DNSName authZone("test.xx");
1198
1199 SyncRes::AuthDomain ad;
1200 DNSRecord dr;
1201
1202 dr.d_place = DNSResourceRecord::ANSWER;
1203 dr.d_name = target;
1204 dr.d_type = QType::CNAME;
1205 dr.d_ttl = 1800;
1206 dr.d_content = std::make_shared<CNAMERecordContent>(targetCname);
1207 ad.d_records.insert(dr);
1208
1209 dr.d_place = DNSResourceRecord::ANSWER;
1210 dr.d_name = targetCname;
1211 dr.d_type = QType::A;
1212 dr.d_ttl = 1800;
1213 dr.d_content = std::make_shared<ARecordContent>(targetCnameAddr);
1214 ad.d_records.insert(dr);
1215
1216 (*SyncRes::t_sstorage.domainmap)[authZone] = ad;
1217
1218 sr->setAsyncCallback([&queriesCount](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, LWResult* res, bool* chained) {
1219 queriesCount++;
1220 return LWResult::Result::Timeout;
1221 });
1222
1223 vector<DNSRecord> ret;
1224 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1225 BOOST_CHECK_EQUAL(res, 0);
1226 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
1227 BOOST_CHECK(ret[0].d_type == QType::CNAME);
1228 BOOST_CHECK(ret[1].d_type == QType::A);
1229 BOOST_CHECK_EQUAL(queriesCount, 0U);
1230 BOOST_CHECK(sr->wasOutOfBand());
1231 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Indeterminate);
1232
1233 /* a second time, to check that the OOB flag is set when the query cache is used */
1234 ret.clear();
1235 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1236 BOOST_CHECK_EQUAL(res, 0);
1237 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
1238 BOOST_CHECK(ret[0].d_type == QType::CNAME);
1239 BOOST_CHECK(ret[1].d_type == QType::A);
1240 BOOST_CHECK_EQUAL(queriesCount, 0U);
1241 BOOST_CHECK(sr->wasOutOfBand());
1242 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Indeterminate);
1243
1244 /* a third time, to check that the validation is disabled when the OOB flag is set */
1245 ret.clear();
1246 sr->setDNSSECValidationRequested(true);
1247 res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1248 BOOST_CHECK_EQUAL(res, 0);
1249 BOOST_REQUIRE_EQUAL(ret.size(), 2U);
1250 BOOST_CHECK(ret[0].d_type == QType::CNAME);
1251 BOOST_CHECK(ret[1].d_type == QType::A);
1252 BOOST_CHECK_EQUAL(queriesCount, 0U);
1253 BOOST_CHECK(sr->wasOutOfBand());
1254 BOOST_CHECK_EQUAL(sr->getValidationState(), vState::Indeterminate);
1255 }
1256
1257 BOOST_AUTO_TEST_CASE(test_auth_zone)
1258 {
1259 std::unique_ptr<SyncRes> sr;
1260 initSR(sr);
1261
1262 primeHints();
1263
1264 size_t queriesCount = 0;
1265 const DNSName target("powerdns.com.");
1266 const ComboAddress addr("192.0.2.5");
1267
1268 SyncRes::AuthDomain ad;
1269 ad.d_name = target;
1270 DNSRecord dr;
1271 dr.d_place = DNSResourceRecord::ANSWER;
1272 dr.d_name = target;
1273 dr.d_type = QType::SOA;
1274 dr.d_ttl = 3600;
1275 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
1276 ad.d_records.insert(dr);
1277
1278 dr.d_place = DNSResourceRecord::ANSWER;
1279 dr.d_name = target;
1280 dr.d_type = QType::A;
1281 dr.d_ttl = 3600;
1282 dr.d_content = std::make_shared<ARecordContent>(addr);
1283 ad.d_records.insert(dr);
1284
1285 auto map = std::make_shared<SyncRes::domainmap_t>();
1286 (*map)[target] = ad;
1287 SyncRes::setDomainMap(map);
1288
1289 sr->setAsyncCallback([&queriesCount](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, LWResult* res, bool* chained) {
1290 queriesCount++;
1291 setLWResult(res, 0, true, false, true);
1292 addRecordToLW(res, domain, QType::A, "192.0.2.42");
1293 return LWResult::Result::Success;
1294 });
1295
1296 vector<DNSRecord> ret;
1297 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1298 BOOST_CHECK_EQUAL(res, RCode::NoError);
1299 BOOST_CHECK_EQUAL(ret.size(), 1U);
1300 BOOST_CHECK(ret[0].d_type == QType::A);
1301 BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[0])->getCA().toString(), addr.toString());
1302 BOOST_CHECK_EQUAL(queriesCount, 0U);
1303 }
1304
1305 BOOST_AUTO_TEST_CASE(test_auth_zone_cname_lead_to_oob)
1306 {
1307 std::unique_ptr<SyncRes> sr;
1308 initSR(sr);
1309
1310 primeHints();
1311
1312 size_t queriesCount = 0;
1313 const DNSName target("powerdns.com.");
1314 const DNSName authZone("internal.powerdns.com.");
1315 const ComboAddress addr("192.0.2.5");
1316
1317 SyncRes::AuthDomain ad;
1318 ad.d_name = authZone;
1319 DNSRecord dr;
1320 dr.d_place = DNSResourceRecord::ANSWER;
1321 dr.d_name = authZone;
1322 dr.d_type = QType::SOA;
1323 dr.d_ttl = 3600;
1324 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
1325 ad.d_records.insert(dr);
1326
1327 dr.d_place = DNSResourceRecord::ANSWER;
1328 dr.d_name = authZone;
1329 dr.d_type = QType::A;
1330 dr.d_ttl = 3600;
1331 dr.d_content = std::make_shared<ARecordContent>(addr);
1332 ad.d_records.insert(dr);
1333
1334 auto map = std::make_shared<SyncRes::domainmap_t>();
1335 (*map)[authZone] = ad;
1336 SyncRes::setDomainMap(map);
1337
1338 sr->setAsyncCallback([&queriesCount, target, authZone](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, LWResult* res, bool* chained) {
1339 queriesCount++;
1340
1341 if (domain == target) {
1342 setLWResult(res, 0, true, false, true);
1343 addRecordToLW(res, target, QType::CNAME, authZone.toString(), DNSResourceRecord::ANSWER, 3600);
1344 return LWResult::Result::Success;
1345 }
1346
1347 return LWResult::Result::Timeout;
1348 });
1349
1350 vector<DNSRecord> ret;
1351 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1352 BOOST_CHECK_EQUAL(res, RCode::NoError);
1353 BOOST_CHECK_EQUAL(ret.size(), 2U);
1354 BOOST_CHECK(ret[0].d_type == QType::CNAME);
1355 BOOST_CHECK_EQUAL(getRR<CNAMERecordContent>(ret[0])->getTarget().toString(), authZone.toString());
1356 BOOST_CHECK(ret[1].d_type == QType::A);
1357 BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[1])->getCA().toString(), addr.toString());
1358 BOOST_CHECK_EQUAL(queriesCount, 1U);
1359 }
1360
1361 BOOST_AUTO_TEST_CASE(test_auth_zone_oob_lead_to_outgoing_queryb)
1362 {
1363 std::unique_ptr<SyncRes> sr;
1364 initSR(sr);
1365
1366 primeHints();
1367
1368 size_t queriesCount = 0;
1369 const DNSName target("powerdns.com.");
1370 const DNSName externalCNAME("www.open-xchange.com.");
1371 const ComboAddress addr("192.0.2.5");
1372
1373 SyncRes::AuthDomain ad;
1374 ad.d_name = target;
1375 DNSRecord dr;
1376 dr.d_place = DNSResourceRecord::ANSWER;
1377 dr.d_name = target;
1378 dr.d_type = QType::SOA;
1379 dr.d_ttl = 3600;
1380 dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
1381 ad.d_records.insert(dr);
1382
1383 dr.d_place = DNSResourceRecord::ANSWER;
1384 dr.d_name = target;
1385 dr.d_type = QType::CNAME;
1386 dr.d_ttl = 3600;
1387 dr.d_content = std::make_shared<CNAMERecordContent>(externalCNAME);
1388 ad.d_records.insert(dr);
1389
1390 auto map = std::make_shared<SyncRes::domainmap_t>();
1391 (*map)[target] = ad;
1392 SyncRes::setDomainMap(map);
1393
1394 sr->setAsyncCallback([&queriesCount, externalCNAME, addr](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, LWResult* res, bool* chained) {
1395 queriesCount++;
1396
1397 if (domain == externalCNAME) {
1398 setLWResult(res, 0, true, false, true);
1399 addRecordToLW(res, externalCNAME, QType::A, addr.toString(), DNSResourceRecord::ANSWER, 3600);
1400 return LWResult::Result::Success;
1401 }
1402
1403 return LWResult::Result::Timeout;
1404 });
1405
1406 vector<DNSRecord> ret;
1407 int res = sr->beginResolve(target, QType(QType::A), QClass::IN, ret);
1408 BOOST_CHECK_EQUAL(res, RCode::NoError);
1409 BOOST_CHECK_EQUAL(ret.size(), 2U);
1410 BOOST_CHECK(ret[0].d_type == QType::CNAME);
1411 BOOST_CHECK_EQUAL(getRR<CNAMERecordContent>(ret[0])->getTarget().toString(), externalCNAME.toString());
1412 BOOST_CHECK(ret[1].d_type == QType::A);
1413 BOOST_CHECK_EQUAL(getRR<ARecordContent>(ret[1])->getCA().toString(), addr.toString());
1414 BOOST_CHECK_EQUAL(queriesCount, 1U);
1415 }
1416
1417 BOOST_AUTO_TEST_SUITE_END()