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(), 0);
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
, 100, 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
);
93 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
)) {
114 BOOST_CHECK_EQUAL(matches
, expected
);
116 PC
.expungeByName(DNSName(" hello"), QType::ANY
, true);
117 BOOST_CHECK_EQUAL(PC
.getSize(), 0);
119 catch(PDNSException
& e
) {
120 cerr
<<"Had error: "<<e
.reason
<<endl
;
125 BOOST_AUTO_TEST_CASE(test_PacketCacheServFailTTL
) {
126 const size_t maxEntries
= 150000;
127 DNSDistPacketCache
PC(maxEntries
, 86400, 1);
128 struct timespec queryTime
;
129 gettime(&queryTime
); // does not have to be accurate ("realTime") in tests
132 bool dnssecOK
= false;
134 DNSName a
= DNSName("servfail");
135 BOOST_CHECK_EQUAL(DNSName(a
.toString()), a
);
137 vector
<uint8_t> query
;
138 DNSPacketWriter
pwQ(query
, a
, QType::A
, QClass::IN
, 0);
139 pwQ
.getHeader()->rd
= 1;
141 vector
<uint8_t> response
;
142 DNSPacketWriter
pwR(response
, a
, QType::A
, QClass::IN
, 0);
143 pwR
.getHeader()->rd
= 1;
144 pwR
.getHeader()->ra
= 0;
145 pwR
.getHeader()->qr
= 1;
146 pwR
.getHeader()->rcode
= RCode::ServFail
;
147 pwR
.getHeader()->id
= pwQ
.getHeader()->id
;
149 uint16_t responseLen
= response
.size();
151 char responseBuf
[4096];
152 uint16_t responseBufSize
= sizeof(responseBuf
);
154 boost::optional
<Netmask
> subnet
;
155 auto dh
= reinterpret_cast<dnsheader
*>(query
.data());
156 DNSQuestion
dq(&a
, QType::A
, QClass::IN
, 0, &remote
, &remote
, dh
, query
.size(), query
.size(), false, &queryTime
);
157 bool found
= PC
.get(dq
, a
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
);
158 BOOST_CHECK_EQUAL(found
, false);
159 BOOST_CHECK(!subnet
);
161 // Insert with failure-TTL of 0 (-> should not enter cache).
162 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));
163 found
= PC
.get(dq
, a
.wirelength(), pwR
.getHeader()->id
, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
, 0, true);
164 BOOST_CHECK_EQUAL(found
, false);
165 BOOST_CHECK(!subnet
);
167 // Insert with failure-TTL non-zero (-> should enter cache).
168 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));
169 found
= PC
.get(dq
, a
.wirelength(), pwR
.getHeader()->id
, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
, 0, true);
170 BOOST_CHECK_EQUAL(found
, true);
171 BOOST_CHECK(!subnet
);
173 catch(PDNSException
& e
) {
174 cerr
<<"Had error: "<<e
.reason
<<endl
;
179 BOOST_AUTO_TEST_CASE(test_PacketCacheNoDataTTL
) {
180 const size_t maxEntries
= 150000;
181 DNSDistPacketCache
PC(maxEntries
, /* maxTTL */ 86400, /* minTTL */ 1, /* tempFailureTTL */ 60, /* maxNegativeTTL */ 1);
183 struct timespec queryTime
;
184 gettime(&queryTime
); // does not have to be accurate ("realTime") in tests
187 bool dnssecOK
= false;
189 DNSName
name("nodata");
190 vector
<uint8_t> query
;
191 DNSPacketWriter
pwQ(query
, name
, QType::A
, QClass::IN
, 0);
192 pwQ
.getHeader()->rd
= 1;
194 vector
<uint8_t> response
;
195 DNSPacketWriter
pwR(response
, name
, QType::A
, QClass::IN
, 0);
196 pwR
.getHeader()->rd
= 1;
197 pwR
.getHeader()->ra
= 0;
198 pwR
.getHeader()->qr
= 1;
199 pwR
.getHeader()->rcode
= RCode::NoError
;
200 pwR
.getHeader()->id
= pwQ
.getHeader()->id
;
202 pwR
.startRecord(name
, QType::SOA
, 86400, QClass::IN
, DNSResourceRecord::AUTHORITY
);
204 pwR
.addOpt(4096, 0, 0);
207 uint16_t responseLen
= response
.size();
209 char responseBuf
[4096];
210 uint16_t responseBufSize
= sizeof(responseBuf
);
212 boost::optional
<Netmask
> subnet
;
213 auto dh
= reinterpret_cast<dnsheader
*>(query
.data());
214 DNSQuestion
dq(&name
, QType::A
, QClass::IN
, 0, &remote
, &remote
, dh
, query
.size(), query
.size(), false, &queryTime
);
215 bool found
= PC
.get(dq
, name
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
);
216 BOOST_CHECK_EQUAL(found
, false);
217 BOOST_CHECK(!subnet
);
219 PC
.insert(key
, subnet
, *(getFlagsFromDNSHeader(dh
)), dnssecOK
, name
, QType::A
, QClass::IN
, reinterpret_cast<const char*>(response
.data()), responseLen
, false, RCode::NoError
, boost::none
);
220 found
= PC
.get(dq
, name
.wirelength(), pwR
.getHeader()->id
, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
, 0, true);
221 BOOST_CHECK_EQUAL(found
, true);
222 BOOST_CHECK(!subnet
);
225 /* it should have expired by now */
226 found
= PC
.get(dq
, name
.wirelength(), pwR
.getHeader()->id
, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
, 0, true);
227 BOOST_CHECK_EQUAL(found
, false);
228 BOOST_CHECK(!subnet
);
230 catch(const PDNSException
& e
) {
231 cerr
<<"Had error: "<<e
.reason
<<endl
;
236 BOOST_AUTO_TEST_CASE(test_PacketCacheNXDomainTTL
) {
237 const size_t maxEntries
= 150000;
238 DNSDistPacketCache
PC(maxEntries
, /* maxTTL */ 86400, /* minTTL */ 1, /* tempFailureTTL */ 60, /* maxNegativeTTL */ 1);
240 struct timespec queryTime
;
241 gettime(&queryTime
); // does not have to be accurate ("realTime") in tests
244 bool dnssecOK
= false;
246 DNSName
name("nxdomain");
247 vector
<uint8_t> query
;
248 DNSPacketWriter
pwQ(query
, name
, QType::A
, QClass::IN
, 0);
249 pwQ
.getHeader()->rd
= 1;
251 vector
<uint8_t> response
;
252 DNSPacketWriter
pwR(response
, name
, QType::A
, QClass::IN
, 0);
253 pwR
.getHeader()->rd
= 1;
254 pwR
.getHeader()->ra
= 0;
255 pwR
.getHeader()->qr
= 1;
256 pwR
.getHeader()->rcode
= RCode::NXDomain
;
257 pwR
.getHeader()->id
= pwQ
.getHeader()->id
;
259 pwR
.startRecord(name
, QType::SOA
, 86400, QClass::IN
, DNSResourceRecord::AUTHORITY
);
261 pwR
.addOpt(4096, 0, 0);
264 uint16_t responseLen
= response
.size();
266 char responseBuf
[4096];
267 uint16_t responseBufSize
= sizeof(responseBuf
);
269 boost::optional
<Netmask
> subnet
;
270 auto dh
= reinterpret_cast<dnsheader
*>(query
.data());
271 DNSQuestion
dq(&name
, QType::A
, QClass::IN
, 0, &remote
, &remote
, dh
, query
.size(), query
.size(), false, &queryTime
);
272 bool found
= PC
.get(dq
, name
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
);
273 BOOST_CHECK_EQUAL(found
, false);
274 BOOST_CHECK(!subnet
);
276 PC
.insert(key
, subnet
, *(getFlagsFromDNSHeader(dh
)), dnssecOK
, name
, QType::A
, QClass::IN
, reinterpret_cast<const char*>(response
.data()), responseLen
, false, RCode::NXDomain
, boost::none
);
277 found
= PC
.get(dq
, name
.wirelength(), pwR
.getHeader()->id
, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
, 0, true);
278 BOOST_CHECK_EQUAL(found
, true);
279 BOOST_CHECK(!subnet
);
282 /* it should have expired by now */
283 found
= PC
.get(dq
, name
.wirelength(), pwR
.getHeader()->id
, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
, 0, true);
284 BOOST_CHECK_EQUAL(found
, false);
285 BOOST_CHECK(!subnet
);
287 catch(const PDNSException
& e
) {
288 cerr
<<"Had error: "<<e
.reason
<<endl
;
293 static DNSDistPacketCache
PC(500000);
295 static void *threadMangler(void* off
)
297 struct timespec queryTime
;
298 gettime(&queryTime
); // does not have to be accurate ("realTime") in tests
301 bool dnssecOK
= false;
302 unsigned int offset
=(unsigned int)(unsigned long)off
;
303 for(unsigned int counter
=0; counter
< 100000; ++counter
) {
304 DNSName a
=DNSName("hello ")+DNSName(std::to_string(counter
+offset
));
305 vector
<uint8_t> query
;
306 DNSPacketWriter
pwQ(query
, a
, QType::A
, QClass::IN
, 0);
307 pwQ
.getHeader()->rd
= 1;
309 vector
<uint8_t> response
;
310 DNSPacketWriter
pwR(response
, a
, QType::A
, QClass::IN
, 0);
311 pwR
.getHeader()->rd
= 1;
312 pwR
.getHeader()->ra
= 1;
313 pwR
.getHeader()->qr
= 1;
314 pwR
.getHeader()->id
= pwQ
.getHeader()->id
;
315 pwR
.startRecord(a
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ANSWER
);
316 pwR
.xfr32BitInt(0x01020304);
318 uint16_t responseLen
= response
.size();
320 char responseBuf
[4096];
321 uint16_t responseBufSize
= sizeof(responseBuf
);
323 boost::optional
<Netmask
> subnet
;
324 auto dh
= reinterpret_cast<dnsheader
*>(query
.data());
325 DNSQuestion
dq(&a
, QType::A
, QClass::IN
, 0, &remote
, &remote
, dh
, query
.size(), query
.size(), false, &queryTime
);
326 PC
.get(dq
, a
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
);
328 PC
.insert(key
, subnet
, *(getFlagsFromDNSHeader(dh
)), dnssecOK
, a
, QType::A
, QClass::IN
, (const char*) response
.data(), responseLen
, false, 0, boost::none
);
331 catch(PDNSException
& e
) {
332 cerr
<<"Had error: "<<e
.reason
<<endl
;
338 AtomicCounter g_missing
;
340 static void *threadReader(void* off
)
342 bool dnssecOK
= false;
343 struct timespec queryTime
;
344 gettime(&queryTime
); // does not have to be accurate ("realTime") in tests
347 unsigned int offset
=(unsigned int)(unsigned long)off
;
348 vector
<DNSResourceRecord
> entry
;
350 for(unsigned int counter
=0; counter
< 100000; ++counter
) {
351 DNSName a
=DNSName("hello ")+DNSName(std::to_string(counter
+offset
));
352 vector
<uint8_t> query
;
353 DNSPacketWriter
pwQ(query
, a
, QType::A
, QClass::IN
, 0);
354 pwQ
.getHeader()->rd
= 1;
356 char responseBuf
[4096];
357 uint16_t responseBufSize
= sizeof(responseBuf
);
359 boost::optional
<Netmask
> subnet
;
360 DNSQuestion
dq(&a
, QType::A
, QClass::IN
, 0, &remote
, &remote
, (struct dnsheader
*) query
.data(), query
.size(), query
.size(), false, &queryTime
);
361 bool found
= PC
.get(dq
, a
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnet
, dnssecOK
);
367 catch(PDNSException
& e
) {
368 cerr
<<"Had error in threadReader: "<<e
.reason
<<endl
;
374 BOOST_AUTO_TEST_CASE(test_PacketCacheThreaded
) {
377 for(int i
=0; i
< 4; ++i
)
378 pthread_create(&tid
[i
], 0, threadMangler
, (void*)(i
*1000000UL));
380 for(int i
=0; i
< 4 ; ++i
)
381 pthread_join(tid
[i
], &res
);
383 BOOST_CHECK_EQUAL(PC
.getSize() + PC
.getDeferredInserts() + PC
.getInsertCollisions(), 400000);
384 BOOST_CHECK_SMALL(1.0*PC
.getInsertCollisions(), 10000.0);
386 for(int i
=0; i
< 4; ++i
)
387 pthread_create(&tid
[i
], 0, threadReader
, (void*)(i
*1000000UL));
388 for(int i
=0; i
< 4 ; ++i
)
389 pthread_join(tid
[i
], &res
);
391 BOOST_CHECK((PC
.getDeferredInserts() + PC
.getDeferredLookups() + PC
.getInsertCollisions()) >= g_missing
);
393 catch(PDNSException
& e
) {
394 cerr
<<"Had error: "<<e
.reason
<<endl
;
400 BOOST_AUTO_TEST_CASE(test_PCCollision
) {
401 const size_t maxEntries
= 150000;
402 DNSDistPacketCache
PC(maxEntries
, 86400, 1, 60, 3600, 60, false, 1, true, true);
403 BOOST_CHECK_EQUAL(PC
.getSize(), 0);
405 DNSName
qname("www.powerdns.com.");
406 uint16_t qtype
= QType::AAAA
;
410 boost::optional
<Netmask
> subnetOut
;
411 bool dnssecOK
= false;
413 /* lookup for a query with an ECS value of 10.0.118.46/32,
414 insert a corresponding response */
416 vector
<uint8_t> query
;
417 DNSPacketWriter
pwQ(query
, qname
, qtype
, QClass::IN
, 0);
418 pwQ
.getHeader()->rd
= 1;
419 pwQ
.getHeader()->id
= qid
;
420 DNSPacketWriter::optvect_t ednsOptions
;
422 opt
.source
= Netmask("10.0.118.46/32");
423 ednsOptions
.push_back(std::make_pair(EDNSOptionCode::ECS
, makeEDNSSubnetOptsString(opt
)));
424 pwQ
.addOpt(512, 0, 0, ednsOptions
);
427 char responseBuf
[4096];
428 uint16_t responseBufSize
= sizeof(responseBuf
);
429 ComboAddress
remote("192.0.2.1");
430 struct timespec queryTime
;
432 DNSQuestion
dq(&qname
, QType::AAAA
, QClass::IN
, 0, &remote
, &remote
, pwQ
.getHeader(), query
.size(), query
.size(), false, &queryTime
);
433 bool found
= PC
.get(dq
, qname
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnetOut
, dnssecOK
);
434 BOOST_CHECK_EQUAL(found
, false);
435 BOOST_REQUIRE(subnetOut
);
436 BOOST_CHECK_EQUAL(subnetOut
->toString(), opt
.source
.toString());
438 vector
<uint8_t> response
;
439 DNSPacketWriter
pwR(response
, qname
, qtype
, QClass::IN
, 0);
440 pwR
.getHeader()->rd
= 1;
441 pwR
.getHeader()->id
= qid
;
442 pwR
.startRecord(qname
, qtype
, 100, QClass::IN
, DNSResourceRecord::ANSWER
);
443 ComboAddress
v6("::1");
444 pwR
.xfrCAWithoutPort(6, v6
);
446 pwR
.addOpt(512, 0, 0, ednsOptions
);
449 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
);
450 BOOST_CHECK_EQUAL(PC
.getSize(), 1);
452 found
= PC
.get(dq
, qname
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnetOut
, dnssecOK
);
453 BOOST_CHECK_EQUAL(found
, true);
454 BOOST_REQUIRE(subnetOut
);
455 BOOST_CHECK_EQUAL(subnetOut
->toString(), opt
.source
.toString());
458 /* now lookup for the same query with an ECS value of 10.0.123.193/32
459 we should get the same key (collision) but no match */
461 vector
<uint8_t> query
;
462 DNSPacketWriter
pwQ(query
, qname
, qtype
, QClass::IN
, 0);
463 pwQ
.getHeader()->rd
= 1;
464 pwQ
.getHeader()->id
= qid
;
465 DNSPacketWriter::optvect_t ednsOptions
;
467 opt
.source
= Netmask("10.0.123.193/32");
468 ednsOptions
.push_back(std::make_pair(EDNSOptionCode::ECS
, makeEDNSSubnetOptsString(opt
)));
469 pwQ
.addOpt(512, 0, 0, ednsOptions
);
472 char responseBuf
[4096];
473 uint16_t responseBufSize
= sizeof(responseBuf
);
474 ComboAddress
remote("192.0.2.1");
475 struct timespec queryTime
;
477 DNSQuestion
dq(&qname
, QType::AAAA
, QClass::IN
, 0, &remote
, &remote
, pwQ
.getHeader(), query
.size(), query
.size(), false, &queryTime
);
478 bool found
= PC
.get(dq
, qname
.wirelength(), 0, responseBuf
, &responseBufSize
, &secondKey
, subnetOut
, dnssecOK
);
479 BOOST_CHECK_EQUAL(found
, false);
480 BOOST_CHECK_EQUAL(secondKey
, key
);
481 BOOST_REQUIRE(subnetOut
);
482 BOOST_CHECK_EQUAL(subnetOut
->toString(), opt
.source
.toString());
483 BOOST_CHECK_EQUAL(PC
.getLookupCollisions(), 1);
487 BOOST_AUTO_TEST_CASE(test_PCDNSSECCollision
) {
488 const size_t maxEntries
= 150000;
489 DNSDistPacketCache
PC(maxEntries
, 86400, 1, 60, 3600, 60, false, 1, true, true);
490 BOOST_CHECK_EQUAL(PC
.getSize(), 0);
492 DNSName
qname("www.powerdns.com.");
493 uint16_t qtype
= QType::AAAA
;
496 boost::optional
<Netmask
> subnetOut
;
498 /* lookup for a query with DNSSEC OK,
499 insert a corresponding response with DO set,
500 check that it doesn't match without DO, but does with it */
502 vector
<uint8_t> query
;
503 DNSPacketWriter
pwQ(query
, qname
, qtype
, QClass::IN
, 0);
504 pwQ
.getHeader()->rd
= 1;
505 pwQ
.getHeader()->id
= qid
;
506 pwQ
.addOpt(512, 0, EDNS_HEADER_FLAG_DO
);
509 char responseBuf
[4096];
510 uint16_t responseBufSize
= sizeof(responseBuf
);
511 ComboAddress
remote("192.0.2.1");
512 struct timespec queryTime
;
514 DNSQuestion
dq(&qname
, QType::AAAA
, QClass::IN
, 0, &remote
, &remote
, pwQ
.getHeader(), query
.size(), query
.size(), false, &queryTime
);
515 bool found
= PC
.get(dq
, qname
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnetOut
, true);
516 BOOST_CHECK_EQUAL(found
, false);
518 vector
<uint8_t> response
;
519 DNSPacketWriter
pwR(response
, qname
, qtype
, QClass::IN
, 0);
520 pwR
.getHeader()->rd
= 1;
521 pwR
.getHeader()->id
= qid
;
522 pwR
.startRecord(qname
, qtype
, 100, QClass::IN
, DNSResourceRecord::ANSWER
);
523 ComboAddress
v6("::1");
524 pwR
.xfrCAWithoutPort(6, v6
);
526 pwR
.addOpt(512, 0, EDNS_HEADER_FLAG_DO
);
529 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
);
530 BOOST_CHECK_EQUAL(PC
.getSize(), 1);
532 found
= PC
.get(dq
, qname
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnetOut
, false);
533 BOOST_CHECK_EQUAL(found
, false);
535 found
= PC
.get(dq
, qname
.wirelength(), 0, responseBuf
, &responseBufSize
, &key
, subnetOut
, true);
536 BOOST_CHECK_EQUAL(found
, true);
541 BOOST_AUTO_TEST_SUITE_END()