1 #define BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_NO_MAIN
4 #include <boost/test/unit_test.hpp>
6 #include "ednscookies.hh"
7 #include "ednsoptions.hh"
8 #include "ednssubnet.hh"
11 #include "dnswriter.hh"
12 #include "dnsdist-cache.hh"
15 BOOST_AUTO_TEST_SUITE(test_dnsdistpacketcache_cc
)
17 BOOST_AUTO_TEST_CASE(test_PacketCacheSimple
) {
18 const size_t maxEntries
= 150000;
19 DNSDistPacketCache
PC(maxEntries
, 86400, 1);
20 BOOST_CHECK_EQUAL(PC
.getSize(), 0U);
21 struct timespec queryTime
;
22 gettime(&queryTime
); // does not have to be accurate ("realTime") in tests
27 bool dnssecOK
= false;
29 for(counter
= 0; counter
< 100000; ++counter
) {
30 DNSName a
=DNSName(std::to_string(counter
))+DNSName(" hello");
31 BOOST_CHECK_EQUAL(DNSName(a
.toString()), a
);
33 vector
<uint8_t> query
;
34 DNSPacketWriter
pwQ(query
, a
, QType::A
, QClass::IN
, 0);
35 pwQ
.getHeader()->rd
= 1;
37 vector
<uint8_t> response
;
38 DNSPacketWriter
pwR(response
, a
, QType::A
, QClass::IN
, 0);
39 pwR
.getHeader()->rd
= 1;
40 pwR
.getHeader()->ra
= 1;
41 pwR
.getHeader()->qr
= 1;
42 pwR
.getHeader()->id
= pwQ
.getHeader()->id
;
43 pwR
.startRecord(a
, QType::A
, 7200, QClass::IN
, DNSResourceRecord::ANSWER
);
44 pwR
.xfr32BitInt(0x01020304);
46 uint16_t responseLen
= response
.size();
48 char responseBuf
[4096];
49 uint16_t responseBufSize
= sizeof(responseBuf
);
51 boost::optional
<Netmask
> subnet
;
52 auto dh
= reinterpret_cast<dnsheader
*>(query
.data());
53 DNSQuestion
dq(&a
, QType::A
, QClass::IN
, 0, &remote
, &remote
, dh
, query
.size(), query
.size(), false, &queryTime
);
54 bool found
= PC
.get(dq
, a
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
);
55 BOOST_CHECK_EQUAL(found
, false);
58 PC
.insert(key
, subnet
, *(getFlagsFromDNSHeader(dh
)), dnssecOK
, a
, QType::A
, QClass::IN
, (const char*) response
.data(), responseLen
, false, 0, boost::none
);
60 found
= PC
.get(dq
, a
.wirelength(), pwR
.getHeader()->id
, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
, 0, true);
62 BOOST_CHECK_EQUAL(responseBufSize
, responseLen
);
63 int match
= memcmp(responseBuf
, response
.data(), responseLen
);
64 BOOST_CHECK_EQUAL(match
, 0);
72 BOOST_CHECK_EQUAL(skipped
, PC
.getInsertCollisions());
73 BOOST_CHECK_EQUAL(PC
.getSize(), counter
- skipped
);
77 for(delcounter
=0; delcounter
< counter
/1000; ++delcounter
) {
78 DNSName a
=DNSName(std::to_string(delcounter
))+DNSName(" hello");
79 vector
<uint8_t> query
;
80 DNSPacketWriter
pwQ(query
, a
, QType::A
, QClass::IN
, 0);
81 pwQ
.getHeader()->rd
= 1;
82 char responseBuf
[4096];
83 uint16_t responseBufSize
= sizeof(responseBuf
);
85 boost::optional
<Netmask
> subnet
;
86 DNSQuestion
dq(&a
, QType::A
, QClass::IN
, 0, &remote
, &remote
, (struct dnsheader
*) query
.data(), query
.size(), query
.size(), false, &queryTime
);
87 bool found
= PC
.get(dq
, a
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
);
89 auto removed
= PC
.expungeByName(a
);
90 BOOST_CHECK_EQUAL(removed
, 1U);
94 BOOST_CHECK_EQUAL(PC
.getSize(), counter
- skipped
- deleted
);
97 vector
<DNSResourceRecord
> entry
;
98 size_t expected
=counter
-skipped
-deleted
;
99 for(; delcounter
< counter
; ++delcounter
) {
100 DNSName
a(DNSName(std::to_string(delcounter
))+DNSName(" hello"));
101 vector
<uint8_t> query
;
102 DNSPacketWriter
pwQ(query
, a
, QType::A
, QClass::IN
, 0);
103 pwQ
.getHeader()->rd
= 1;
104 uint16_t len
= query
.size();
106 boost::optional
<Netmask
> subnet
;
108 uint16_t responseSize
= sizeof(response
);
109 DNSQuestion
dq(&a
, QType::A
, QClass::IN
, 0, &remote
, &remote
, (struct dnsheader
*) query
.data(), len
, query
.size(), false, &queryTime
);
110 if(PC
.get(dq
, a
.wirelength(), pwQ
.getHeader()->id
, response
, &responseSize
, &key
, subnet
, dnssecOK
)) {
115 /* in the unlikely event that the test took so long that the entries did expire.. */
116 auto expired
= PC
.purgeExpired();
117 BOOST_CHECK_EQUAL(matches
+ expired
, expected
);
119 auto remaining
= PC
.getSize();
120 auto removed
= PC
.expungeByName(DNSName(" hello"), QType::ANY
, true);
121 BOOST_CHECK_EQUAL(PC
.getSize(), 0U);
122 BOOST_CHECK_EQUAL(removed
, remaining
);
124 catch(PDNSException
& e
) {
125 cerr
<<"Had error: "<<e
.reason
<<endl
;
130 BOOST_AUTO_TEST_CASE(test_PacketCacheServFailTTL
) {
131 const size_t maxEntries
= 150000;
132 DNSDistPacketCache
PC(maxEntries
, 86400, 1);
133 struct timespec queryTime
;
134 gettime(&queryTime
); // does not have to be accurate ("realTime") in tests
137 bool dnssecOK
= false;
139 DNSName a
= DNSName("servfail");
140 BOOST_CHECK_EQUAL(DNSName(a
.toString()), a
);
142 vector
<uint8_t> query
;
143 DNSPacketWriter
pwQ(query
, a
, QType::A
, QClass::IN
, 0);
144 pwQ
.getHeader()->rd
= 1;
146 vector
<uint8_t> response
;
147 DNSPacketWriter
pwR(response
, a
, QType::A
, QClass::IN
, 0);
148 pwR
.getHeader()->rd
= 1;
149 pwR
.getHeader()->ra
= 0;
150 pwR
.getHeader()->qr
= 1;
151 pwR
.getHeader()->rcode
= RCode::ServFail
;
152 pwR
.getHeader()->id
= pwQ
.getHeader()->id
;
154 uint16_t responseLen
= response
.size();
156 char responseBuf
[4096];
157 uint16_t responseBufSize
= sizeof(responseBuf
);
159 boost::optional
<Netmask
> subnet
;
160 auto dh
= reinterpret_cast<dnsheader
*>(query
.data());
161 DNSQuestion
dq(&a
, QType::A
, QClass::IN
, 0, &remote
, &remote
, dh
, query
.size(), query
.size(), false, &queryTime
);
162 bool found
= PC
.get(dq
, a
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
);
163 BOOST_CHECK_EQUAL(found
, false);
164 BOOST_CHECK(!subnet
);
166 // Insert with failure-TTL of 0 (-> should not enter cache).
167 PC
.insert(key
, subnet
, *(getFlagsFromDNSHeader(dh
)), dnssecOK
, a
, QType::A
, QClass::IN
, (const char*) response
.data(), responseLen
, false, RCode::ServFail
, boost::optional
<uint32_t>(0));
168 found
= PC
.get(dq
, a
.wirelength(), pwR
.getHeader()->id
, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
, 0, true);
169 BOOST_CHECK_EQUAL(found
, false);
170 BOOST_CHECK(!subnet
);
172 // Insert with failure-TTL non-zero (-> should enter cache).
173 PC
.insert(key
, subnet
, *(getFlagsFromDNSHeader(dh
)), dnssecOK
, a
, QType::A
, QClass::IN
, (const char*) response
.data(), responseLen
, false, RCode::ServFail
, boost::optional
<uint32_t>(300));
174 found
= PC
.get(dq
, a
.wirelength(), pwR
.getHeader()->id
, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
, 0, true);
175 BOOST_CHECK_EQUAL(found
, true);
176 BOOST_CHECK(!subnet
);
178 catch(PDNSException
& e
) {
179 cerr
<<"Had error: "<<e
.reason
<<endl
;
184 BOOST_AUTO_TEST_CASE(test_PacketCacheNoDataTTL
) {
185 const size_t maxEntries
= 150000;
186 DNSDistPacketCache
PC(maxEntries
, /* maxTTL */ 86400, /* minTTL */ 1, /* tempFailureTTL */ 60, /* maxNegativeTTL */ 1);
188 struct timespec queryTime
;
189 gettime(&queryTime
); // does not have to be accurate ("realTime") in tests
192 bool dnssecOK
= false;
194 DNSName
name("nodata");
195 vector
<uint8_t> query
;
196 DNSPacketWriter
pwQ(query
, name
, QType::A
, QClass::IN
, 0);
197 pwQ
.getHeader()->rd
= 1;
199 vector
<uint8_t> response
;
200 DNSPacketWriter
pwR(response
, name
, QType::A
, QClass::IN
, 0);
201 pwR
.getHeader()->rd
= 1;
202 pwR
.getHeader()->ra
= 0;
203 pwR
.getHeader()->qr
= 1;
204 pwR
.getHeader()->rcode
= RCode::NoError
;
205 pwR
.getHeader()->id
= pwQ
.getHeader()->id
;
207 pwR
.startRecord(name
, QType::SOA
, 86400, QClass::IN
, DNSResourceRecord::AUTHORITY
);
209 pwR
.addOpt(4096, 0, 0);
212 uint16_t responseLen
= response
.size();
214 char responseBuf
[4096];
215 uint16_t responseBufSize
= sizeof(responseBuf
);
217 boost::optional
<Netmask
> subnet
;
218 auto dh
= reinterpret_cast<dnsheader
*>(query
.data());
219 DNSQuestion
dq(&name
, QType::A
, QClass::IN
, 0, &remote
, &remote
, dh
, query
.size(), query
.size(), false, &queryTime
);
220 bool found
= PC
.get(dq
, name
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
);
221 BOOST_CHECK_EQUAL(found
, false);
222 BOOST_CHECK(!subnet
);
224 PC
.insert(key
, subnet
, *(getFlagsFromDNSHeader(dh
)), dnssecOK
, name
, QType::A
, QClass::IN
, reinterpret_cast<const char*>(response
.data()), responseLen
, false, RCode::NoError
, boost::none
);
225 found
= PC
.get(dq
, name
.wirelength(), pwR
.getHeader()->id
, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
, 0, true);
226 BOOST_CHECK_EQUAL(found
, true);
227 BOOST_CHECK(!subnet
);
230 /* it should have expired by now */
231 found
= PC
.get(dq
, name
.wirelength(), pwR
.getHeader()->id
, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
, 0, true);
232 BOOST_CHECK_EQUAL(found
, false);
233 BOOST_CHECK(!subnet
);
235 catch(const PDNSException
& e
) {
236 cerr
<<"Had error: "<<e
.reason
<<endl
;
241 BOOST_AUTO_TEST_CASE(test_PacketCacheNXDomainTTL
) {
242 const size_t maxEntries
= 150000;
243 DNSDistPacketCache
PC(maxEntries
, /* maxTTL */ 86400, /* minTTL */ 1, /* tempFailureTTL */ 60, /* maxNegativeTTL */ 1);
245 struct timespec queryTime
;
246 gettime(&queryTime
); // does not have to be accurate ("realTime") in tests
249 bool dnssecOK
= false;
251 DNSName
name("nxdomain");
252 vector
<uint8_t> query
;
253 DNSPacketWriter
pwQ(query
, name
, QType::A
, QClass::IN
, 0);
254 pwQ
.getHeader()->rd
= 1;
256 vector
<uint8_t> response
;
257 DNSPacketWriter
pwR(response
, name
, QType::A
, QClass::IN
, 0);
258 pwR
.getHeader()->rd
= 1;
259 pwR
.getHeader()->ra
= 0;
260 pwR
.getHeader()->qr
= 1;
261 pwR
.getHeader()->rcode
= RCode::NXDomain
;
262 pwR
.getHeader()->id
= pwQ
.getHeader()->id
;
264 pwR
.startRecord(name
, QType::SOA
, 86400, QClass::IN
, DNSResourceRecord::AUTHORITY
);
266 pwR
.addOpt(4096, 0, 0);
269 uint16_t responseLen
= response
.size();
271 char responseBuf
[4096];
272 uint16_t responseBufSize
= sizeof(responseBuf
);
274 boost::optional
<Netmask
> subnet
;
275 auto dh
= reinterpret_cast<dnsheader
*>(query
.data());
276 DNSQuestion
dq(&name
, QType::A
, QClass::IN
, 0, &remote
, &remote
, dh
, query
.size(), query
.size(), false, &queryTime
);
277 bool found
= PC
.get(dq
, name
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
);
278 BOOST_CHECK_EQUAL(found
, false);
279 BOOST_CHECK(!subnet
);
281 PC
.insert(key
, subnet
, *(getFlagsFromDNSHeader(dh
)), dnssecOK
, name
, QType::A
, QClass::IN
, reinterpret_cast<const char*>(response
.data()), responseLen
, false, RCode::NXDomain
, boost::none
);
282 found
= PC
.get(dq
, name
.wirelength(), pwR
.getHeader()->id
, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
, 0, true);
283 BOOST_CHECK_EQUAL(found
, true);
284 BOOST_CHECK(!subnet
);
287 /* it should have expired by now */
288 found
= PC
.get(dq
, name
.wirelength(), pwR
.getHeader()->id
, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
, 0, true);
289 BOOST_CHECK_EQUAL(found
, false);
290 BOOST_CHECK(!subnet
);
292 catch(const PDNSException
& e
) {
293 cerr
<<"Had error: "<<e
.reason
<<endl
;
298 static DNSDistPacketCache
g_PC(500000);
300 static void threadMangler(unsigned int offset
)
302 struct timespec queryTime
;
303 gettime(&queryTime
); // does not have to be accurate ("realTime") in tests
306 bool dnssecOK
= false;
307 for(unsigned int counter
=0; counter
< 100000; ++counter
) {
308 DNSName a
=DNSName("hello ")+DNSName(std::to_string(counter
+offset
));
309 vector
<uint8_t> query
;
310 DNSPacketWriter
pwQ(query
, a
, QType::A
, QClass::IN
, 0);
311 pwQ
.getHeader()->rd
= 1;
313 vector
<uint8_t> response
;
314 DNSPacketWriter
pwR(response
, a
, QType::A
, QClass::IN
, 0);
315 pwR
.getHeader()->rd
= 1;
316 pwR
.getHeader()->ra
= 1;
317 pwR
.getHeader()->qr
= 1;
318 pwR
.getHeader()->id
= pwQ
.getHeader()->id
;
319 pwR
.startRecord(a
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ANSWER
);
320 pwR
.xfr32BitInt(0x01020304);
322 uint16_t responseLen
= response
.size();
324 char responseBuf
[4096];
325 uint16_t responseBufSize
= sizeof(responseBuf
);
327 boost::optional
<Netmask
> subnet
;
328 auto dh
= reinterpret_cast<dnsheader
*>(query
.data());
329 DNSQuestion
dq(&a
, QType::A
, QClass::IN
, 0, &remote
, &remote
, dh
, query
.size(), query
.size(), false, &queryTime
);
330 g_PC
.get(dq
, a
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
);
332 g_PC
.insert(key
, subnet
, *(getFlagsFromDNSHeader(dh
)), dnssecOK
, a
, QType::A
, QClass::IN
, (const char*) response
.data(), responseLen
, false, 0, boost::none
);
335 catch(PDNSException
& e
) {
336 cerr
<<"Had error: "<<e
.reason
<<endl
;
341 AtomicCounter g_missing
;
343 static void threadReader(unsigned int offset
)
345 bool dnssecOK
= false;
346 struct timespec queryTime
;
347 gettime(&queryTime
); // does not have to be accurate ("realTime") in tests
350 vector
<DNSResourceRecord
> entry
;
352 for(unsigned int counter
=0; counter
< 100000; ++counter
) {
353 DNSName a
=DNSName("hello ")+DNSName(std::to_string(counter
+offset
));
354 vector
<uint8_t> query
;
355 DNSPacketWriter
pwQ(query
, a
, QType::A
, QClass::IN
, 0);
356 pwQ
.getHeader()->rd
= 1;
358 char responseBuf
[4096];
359 uint16_t responseBufSize
= sizeof(responseBuf
);
361 boost::optional
<Netmask
> subnet
;
362 DNSQuestion
dq(&a
, QType::A
, QClass::IN
, 0, &remote
, &remote
, (struct dnsheader
*) query
.data(), query
.size(), query
.size(), false, &queryTime
);
363 bool found
= g_PC
.get(dq
, a
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
);
369 catch(PDNSException
& e
) {
370 cerr
<<"Had error in threadReader: "<<e
.reason
<<endl
;
375 BOOST_AUTO_TEST_CASE(test_PacketCacheThreaded
) {
377 std::vector
<std::thread
> threads
;
378 for (int i
= 0; i
< 4; ++i
) {
379 threads
.push_back(std::thread(threadMangler
, i
*1000000UL));
382 for (auto& t
: threads
) {
388 BOOST_CHECK_EQUAL(g_PC
.getSize() + g_PC
.getDeferredInserts() + g_PC
.getInsertCollisions(), 400000U);
389 BOOST_CHECK_SMALL(1.0*g_PC
.getInsertCollisions(), 10000.0);
391 for (int i
= 0; i
< 4; ++i
) {
392 threads
.push_back(std::thread(threadReader
, i
*1000000UL));
395 for (auto& t
: threads
) {
399 BOOST_CHECK((g_PC
.getDeferredInserts() + g_PC
.getDeferredLookups() + g_PC
.getInsertCollisions()) >= g_missing
);
401 catch(PDNSException
& e
) {
402 cerr
<<"Had error: "<<e
.reason
<<endl
;
408 BOOST_AUTO_TEST_CASE(test_PCCollision
) {
409 const size_t maxEntries
= 150000;
410 DNSDistPacketCache
PC(maxEntries
, 86400, 1, 60, 3600, 60, false, 1, true, true);
411 BOOST_CHECK_EQUAL(PC
.getSize(), 0U);
413 DNSName
qname("www.powerdns.com.");
414 uint16_t qtype
= QType::AAAA
;
418 boost::optional
<Netmask
> subnetOut
;
419 bool dnssecOK
= false;
421 /* lookup for a query with an ECS value of 10.0.118.46/32,
422 insert a corresponding response */
424 vector
<uint8_t> query
;
425 DNSPacketWriter
pwQ(query
, qname
, qtype
, QClass::IN
, 0);
426 pwQ
.getHeader()->rd
= 1;
427 pwQ
.getHeader()->id
= qid
;
428 DNSPacketWriter::optvect_t ednsOptions
;
430 opt
.source
= Netmask("10.0.118.46/32");
431 ednsOptions
.push_back(std::make_pair(EDNSOptionCode::ECS
, makeEDNSSubnetOptsString(opt
)));
432 pwQ
.addOpt(512, 0, 0, ednsOptions
);
435 char responseBuf
[4096];
436 uint16_t responseBufSize
= sizeof(responseBuf
);
437 ComboAddress
remote("192.0.2.1");
438 struct timespec queryTime
;
440 DNSQuestion
dq(&qname
, QType::AAAA
, QClass::IN
, 0, &remote
, &remote
, pwQ
.getHeader(), query
.size(), query
.size(), false, &queryTime
);
441 bool found
= PC
.get(dq
, qname
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnetOut
, dnssecOK
);
442 BOOST_CHECK_EQUAL(found
, false);
443 BOOST_REQUIRE(subnetOut
);
444 BOOST_CHECK_EQUAL(subnetOut
->toString(), opt
.source
.toString());
446 vector
<uint8_t> response
;
447 DNSPacketWriter
pwR(response
, qname
, qtype
, QClass::IN
, 0);
448 pwR
.getHeader()->rd
= 1;
449 pwR
.getHeader()->id
= qid
;
450 pwR
.startRecord(qname
, qtype
, 100, QClass::IN
, DNSResourceRecord::ANSWER
);
451 ComboAddress
v6("::1");
452 pwR
.xfrCAWithoutPort(6, v6
);
454 pwR
.addOpt(512, 0, 0, ednsOptions
);
457 PC
.insert(key
, subnetOut
, *(getFlagsFromDNSHeader(pwR
.getHeader())), dnssecOK
, qname
, qtype
, QClass::IN
, reinterpret_cast<const char*>(response
.data()), response
.size(), false, RCode::NoError
, boost::none
);
458 BOOST_CHECK_EQUAL(PC
.getSize(), 1U);
460 found
= PC
.get(dq
, qname
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnetOut
, dnssecOK
);
461 BOOST_CHECK_EQUAL(found
, true);
462 BOOST_REQUIRE(subnetOut
);
463 BOOST_CHECK_EQUAL(subnetOut
->toString(), opt
.source
.toString());
466 /* now lookup for the same query with an ECS value of 10.0.123.193/32
467 we should get the same key (collision) but no match */
469 vector
<uint8_t> query
;
470 DNSPacketWriter
pwQ(query
, qname
, qtype
, QClass::IN
, 0);
471 pwQ
.getHeader()->rd
= 1;
472 pwQ
.getHeader()->id
= qid
;
473 DNSPacketWriter::optvect_t ednsOptions
;
475 opt
.source
= Netmask("10.0.123.193/32");
476 ednsOptions
.push_back(std::make_pair(EDNSOptionCode::ECS
, makeEDNSSubnetOptsString(opt
)));
477 pwQ
.addOpt(512, 0, 0, ednsOptions
);
480 char responseBuf
[4096];
481 uint16_t responseBufSize
= sizeof(responseBuf
);
482 ComboAddress
remote("192.0.2.1");
483 struct timespec queryTime
;
485 DNSQuestion
dq(&qname
, QType::AAAA
, QClass::IN
, 0, &remote
, &remote
, pwQ
.getHeader(), query
.size(), query
.size(), false, &queryTime
);
486 bool found
= PC
.get(dq
, qname
.wirelength(), 0, responseBuf
, &responseBufSize
, &secondKey
, subnetOut
, dnssecOK
);
487 BOOST_CHECK_EQUAL(found
, false);
488 BOOST_CHECK_EQUAL(secondKey
, key
);
489 BOOST_REQUIRE(subnetOut
);
490 BOOST_CHECK_EQUAL(subnetOut
->toString(), opt
.source
.toString());
491 BOOST_CHECK_EQUAL(PC
.getLookupCollisions(), 1U);
495 BOOST_AUTO_TEST_CASE(test_PCDNSSECCollision
) {
496 const size_t maxEntries
= 150000;
497 DNSDistPacketCache
PC(maxEntries
, 86400, 1, 60, 3600, 60, false, 1, true, true);
498 BOOST_CHECK_EQUAL(PC
.getSize(), 0U);
500 DNSName
qname("www.powerdns.com.");
501 uint16_t qtype
= QType::AAAA
;
504 boost::optional
<Netmask
> subnetOut
;
506 /* lookup for a query with DNSSEC OK,
507 insert a corresponding response with DO set,
508 check that it doesn't match without DO, but does with it */
510 vector
<uint8_t> query
;
511 DNSPacketWriter
pwQ(query
, qname
, qtype
, QClass::IN
, 0);
512 pwQ
.getHeader()->rd
= 1;
513 pwQ
.getHeader()->id
= qid
;
514 pwQ
.addOpt(512, 0, EDNS_HEADER_FLAG_DO
);
517 char responseBuf
[4096];
518 uint16_t responseBufSize
= sizeof(responseBuf
);
519 ComboAddress
remote("192.0.2.1");
520 struct timespec queryTime
;
522 DNSQuestion
dq(&qname
, QType::AAAA
, QClass::IN
, 0, &remote
, &remote
, pwQ
.getHeader(), query
.size(), query
.size(), false, &queryTime
);
523 bool found
= PC
.get(dq
, qname
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnetOut
, true);
524 BOOST_CHECK_EQUAL(found
, false);
526 vector
<uint8_t> response
;
527 DNSPacketWriter
pwR(response
, qname
, qtype
, QClass::IN
, 0);
528 pwR
.getHeader()->rd
= 1;
529 pwR
.getHeader()->id
= qid
;
530 pwR
.startRecord(qname
, qtype
, 100, QClass::IN
, DNSResourceRecord::ANSWER
);
531 ComboAddress
v6("::1");
532 pwR
.xfrCAWithoutPort(6, v6
);
534 pwR
.addOpt(512, 0, EDNS_HEADER_FLAG_DO
);
537 PC
.insert(key
, subnetOut
, *(getFlagsFromDNSHeader(pwR
.getHeader())), /* DNSSEC OK is set */ true, qname
, qtype
, QClass::IN
, reinterpret_cast<const char*>(response
.data()), response
.size(), false, RCode::NoError
, boost::none
);
538 BOOST_CHECK_EQUAL(PC
.getSize(), 1U);
540 found
= PC
.get(dq
, qname
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnetOut
, false);
541 BOOST_CHECK_EQUAL(found
, false);
543 found
= PC
.get(dq
, qname
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnetOut
, true);
544 BOOST_CHECK_EQUAL(found
, true);
549 BOOST_AUTO_TEST_SUITE_END()