]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/test-dnsdistpacketcache_cc.cc
Merge pull request #6923 from Habbie/ds-in-unsigned-zone
[thirdparty/pdns.git] / pdns / test-dnsdistpacketcache_cc.cc
CommitLineData
886e2cf2
RG
1#define BOOST_TEST_DYN_LINK
2#define BOOST_TEST_NO_MAIN
3
4#include <boost/test/unit_test.hpp>
5
78e3ac9e 6#include "ednscookies.hh"
8dcdbdb1 7#include "ednsoptions.hh"
78e3ac9e 8#include "ednssubnet.hh"
1ea747c0 9#include "dnsdist.hh"
886e2cf2 10#include "iputils.hh"
886e2cf2 11#include "dnswriter.hh"
1ea747c0 12#include "dnsdist-cache.hh"
5ffb2f83 13#include "gettime.hh"
886e2cf2
RG
14
15BOOST_AUTO_TEST_SUITE(dnsdistpacketcache_cc)
16
17BOOST_AUTO_TEST_CASE(test_PacketCacheSimple) {
18 const size_t maxEntries = 150000;
19 DNSDistPacketCache PC(maxEntries, 86400, 1);
20 BOOST_CHECK_EQUAL(PC.getSize(), 0);
5ffb2f83
CH
21 struct timespec queryTime;
22 gettime(&queryTime); // does not have to be accurate ("realTime") in tests
886e2cf2
RG
23
24 size_t counter=0;
25 size_t skipped=0;
1ea747c0 26 ComboAddress remote;
886e2cf2
RG
27 try {
28 for(counter = 0; counter < 100000; ++counter) {
490dc586 29 DNSName a=DNSName(std::to_string(counter))+DNSName(" hello");
886e2cf2
RG
30 BOOST_CHECK_EQUAL(DNSName(a.toString()), a);
31
32 vector<uint8_t> query;
33 DNSPacketWriter pwQ(query, a, QType::A, QClass::IN, 0);
34 pwQ.getHeader()->rd = 1;
35
36 vector<uint8_t> response;
37 DNSPacketWriter pwR(response, a, QType::A, QClass::IN, 0);
38 pwR.getHeader()->rd = 1;
39 pwR.getHeader()->ra = 1;
40 pwR.getHeader()->qr = 1;
41 pwR.getHeader()->id = pwQ.getHeader()->id;
42 pwR.startRecord(a, QType::A, 100, QClass::IN, DNSResourceRecord::ANSWER);
43 pwR.xfr32BitInt(0x01020304);
44 pwR.commit();
45 uint16_t responseLen = response.size();
46
47 char responseBuf[4096];
48 uint16_t responseBufSize = sizeof(responseBuf);
49 uint32_t key = 0;
78e3ac9e 50 boost::optional<Netmask> subnet;
8dcdbdb1 51 auto dh = reinterpret_cast<dnsheader*>(query.data());
e7c732b8 52 DNSQuestion dq(&a, QType::A, QClass::IN, 0, &remote, &remote, dh, query.size(), query.size(), false, &queryTime);
78e3ac9e 53 bool found = PC.get(dq, a.wirelength(), 0, responseBuf, &responseBufSize, &key, subnet);
886e2cf2 54 BOOST_CHECK_EQUAL(found, false);
78e3ac9e 55 BOOST_CHECK(!subnet);
886e2cf2 56
78e3ac9e 57 PC.insert(key, subnet, *(getFlagsFromDNSHeader(dh)), a, QType::A, QClass::IN, (const char*) response.data(), responseLen, false, 0, boost::none);
886e2cf2 58
78e3ac9e 59 found = PC.get(dq, a.wirelength(), pwR.getHeader()->id, responseBuf, &responseBufSize, &key, subnet, 0, true);
886e2cf2
RG
60 if (found == true) {
61 BOOST_CHECK_EQUAL(responseBufSize, responseLen);
62 int match = memcmp(responseBuf, response.data(), responseLen);
63 BOOST_CHECK_EQUAL(match, 0);
78e3ac9e 64 BOOST_CHECK(!subnet);
886e2cf2
RG
65 }
66 else {
67 skipped++;
68 }
69 }
70
71 BOOST_CHECK_EQUAL(skipped, PC.getInsertCollisions());
72 BOOST_CHECK_EQUAL(PC.getSize(), counter - skipped);
73
74 size_t deleted=0;
75 size_t delcounter=0;
76 for(delcounter=0; delcounter < counter/1000; ++delcounter) {
490dc586 77 DNSName a=DNSName(std::to_string(delcounter))+DNSName(" hello");
886e2cf2
RG
78 vector<uint8_t> query;
79 DNSPacketWriter pwQ(query, a, QType::A, QClass::IN, 0);
80 pwQ.getHeader()->rd = 1;
81 char responseBuf[4096];
82 uint16_t responseBufSize = sizeof(responseBuf);
83 uint32_t key = 0;
78e3ac9e 84 boost::optional<Netmask> subnet;
e7c732b8 85 DNSQuestion dq(&a, QType::A, QClass::IN, 0, &remote, &remote, (struct dnsheader*) query.data(), query.size(), query.size(), false, &queryTime);
78e3ac9e 86 bool found = PC.get(dq, a.wirelength(), 0, responseBuf, &responseBufSize, &key, subnet);
886e2cf2 87 if (found == true) {
4275aaba 88 PC.expungeByName(a);
886e2cf2
RG
89 deleted++;
90 }
91 }
92 BOOST_CHECK_EQUAL(PC.getSize(), counter - skipped - deleted);
93
490dc586 94
886e2cf2
RG
95 size_t matches=0;
96 vector<DNSResourceRecord> entry;
97 size_t expected=counter-skipped-deleted;
98 for(; delcounter < counter; ++delcounter) {
490dc586 99 DNSName a(DNSName(std::to_string(delcounter))+DNSName(" hello"));
886e2cf2
RG
100 vector<uint8_t> query;
101 DNSPacketWriter pwQ(query, a, QType::A, QClass::IN, 0);
102 pwQ.getHeader()->rd = 1;
103 uint16_t len = query.size();
104 uint32_t key = 0;
78e3ac9e 105 boost::optional<Netmask> subnet;
886e2cf2
RG
106 char response[4096];
107 uint16_t responseSize = sizeof(response);
e7c732b8 108 DNSQuestion dq(&a, QType::A, QClass::IN, 0, &remote, &remote, (struct dnsheader*) query.data(), len, query.size(), false, &queryTime);
78e3ac9e 109 if(PC.get(dq, a.wirelength(), pwQ.getHeader()->id, response, &responseSize, &key, subnet)) {
490dc586 110 matches++;
886e2cf2
RG
111 }
112 }
113 BOOST_CHECK_EQUAL(matches, expected);
490dc586
RG
114
115 PC.expungeByName(DNSName(" hello"), QType::ANY, true);
116 BOOST_CHECK_EQUAL(PC.getSize(), 0);
886e2cf2
RG
117 }
118 catch(PDNSException& e) {
119 cerr<<"Had error: "<<e.reason<<endl;
120 throw;
121 }
122}
123
acb8f5d5
CH
124BOOST_AUTO_TEST_CASE(test_PacketCacheServFailTTL) {
125 const size_t maxEntries = 150000;
126 DNSDistPacketCache PC(maxEntries, 86400, 1);
5ffb2f83
CH
127 struct timespec queryTime;
128 gettime(&queryTime); // does not have to be accurate ("realTime") in tests
acb8f5d5
CH
129
130 ComboAddress remote;
131 try {
132 DNSName a = DNSName("servfail");
133 BOOST_CHECK_EQUAL(DNSName(a.toString()), a);
134
135 vector<uint8_t> query;
136 DNSPacketWriter pwQ(query, a, QType::A, QClass::IN, 0);
137 pwQ.getHeader()->rd = 1;
138
139 vector<uint8_t> response;
140 DNSPacketWriter pwR(response, a, QType::A, QClass::IN, 0);
141 pwR.getHeader()->rd = 1;
142 pwR.getHeader()->ra = 0;
143 pwR.getHeader()->qr = 1;
144 pwR.getHeader()->rcode = RCode::ServFail;
145 pwR.getHeader()->id = pwQ.getHeader()->id;
146 pwR.commit();
147 uint16_t responseLen = response.size();
148
149 char responseBuf[4096];
150 uint16_t responseBufSize = sizeof(responseBuf);
151 uint32_t key = 0;
78e3ac9e 152 boost::optional<Netmask> subnet;
8dcdbdb1 153 auto dh = reinterpret_cast<dnsheader*>(query.data());
e7c732b8 154 DNSQuestion dq(&a, QType::A, QClass::IN, 0, &remote, &remote, dh, query.size(), query.size(), false, &queryTime);
78e3ac9e 155 bool found = PC.get(dq, a.wirelength(), 0, responseBuf, &responseBufSize, &key, subnet);
acb8f5d5 156 BOOST_CHECK_EQUAL(found, false);
78e3ac9e 157 BOOST_CHECK(!subnet);
acb8f5d5
CH
158
159 // Insert with failure-TTL of 0 (-> should not enter cache).
78e3ac9e
RG
160 PC.insert(key, subnet, *(getFlagsFromDNSHeader(dh)), a, QType::A, QClass::IN, (const char*) response.data(), responseLen, false, RCode::ServFail, boost::optional<uint32_t>(0));
161 found = PC.get(dq, a.wirelength(), pwR.getHeader()->id, responseBuf, &responseBufSize, &key, subnet, 0, true);
acb8f5d5 162 BOOST_CHECK_EQUAL(found, false);
78e3ac9e 163 BOOST_CHECK(!subnet);
acb8f5d5 164
56459632 165 // Insert with failure-TTL non-zero (-> should enter cache).
78e3ac9e
RG
166 PC.insert(key, subnet, *(getFlagsFromDNSHeader(dh)), a, QType::A, QClass::IN, (const char*) response.data(), responseLen, false, RCode::ServFail, boost::optional<uint32_t>(300));
167 found = PC.get(dq, a.wirelength(), pwR.getHeader()->id, responseBuf, &responseBufSize, &key, subnet, 0, true);
acb8f5d5 168 BOOST_CHECK_EQUAL(found, true);
78e3ac9e 169 BOOST_CHECK(!subnet);
acb8f5d5
CH
170 }
171 catch(PDNSException& e) {
172 cerr<<"Had error: "<<e.reason<<endl;
173 throw;
174 }
175}
176
47698274
RG
177BOOST_AUTO_TEST_CASE(test_PacketCacheNoDataTTL) {
178 const size_t maxEntries = 150000;
179 DNSDistPacketCache PC(maxEntries, /* maxTTL */ 86400, /* minTTL */ 1, /* tempFailureTTL */ 60, /* maxNegativeTTL */ 1);
180
181 struct timespec queryTime;
182 gettime(&queryTime); // does not have to be accurate ("realTime") in tests
183
184 ComboAddress remote;
185 try {
186 DNSName name("nodata");
187 vector<uint8_t> query;
188 DNSPacketWriter pwQ(query, name, QType::A, QClass::IN, 0);
189 pwQ.getHeader()->rd = 1;
190
191 vector<uint8_t> response;
192 DNSPacketWriter pwR(response, name, QType::A, QClass::IN, 0);
193 pwR.getHeader()->rd = 1;
194 pwR.getHeader()->ra = 0;
195 pwR.getHeader()->qr = 1;
196 pwR.getHeader()->rcode = RCode::NoError;
197 pwR.getHeader()->id = pwQ.getHeader()->id;
198 pwR.commit();
199 pwR.startRecord(name, QType::SOA, 86400, QClass::IN, DNSResourceRecord::AUTHORITY);
200 pwR.commit();
201 pwR.addOpt(4096, 0, 0);
202 pwR.commit();
203
204 uint16_t responseLen = response.size();
205
206 char responseBuf[4096];
207 uint16_t responseBufSize = sizeof(responseBuf);
208 uint32_t key = 0;
78e3ac9e 209 boost::optional<Netmask> subnet;
8dcdbdb1 210 auto dh = reinterpret_cast<dnsheader*>(query.data());
e7c732b8 211 DNSQuestion dq(&name, QType::A, QClass::IN, 0, &remote, &remote, dh, query.size(), query.size(), false, &queryTime);
78e3ac9e 212 bool found = PC.get(dq, name.wirelength(), 0, responseBuf, &responseBufSize, &key, subnet);
47698274 213 BOOST_CHECK_EQUAL(found, false);
78e3ac9e 214 BOOST_CHECK(!subnet);
47698274 215
78e3ac9e
RG
216 PC.insert(key, subnet, *(getFlagsFromDNSHeader(dh)), name, QType::A, QClass::IN, reinterpret_cast<const char*>(response.data()), responseLen, false, RCode::NoError, boost::none);
217 found = PC.get(dq, name.wirelength(), pwR.getHeader()->id, responseBuf, &responseBufSize, &key, subnet, 0, true);
47698274 218 BOOST_CHECK_EQUAL(found, true);
78e3ac9e
RG
219 BOOST_CHECK(!subnet);
220
47698274
RG
221 sleep(2);
222 /* it should have expired by now */
78e3ac9e 223 found = PC.get(dq, name.wirelength(), pwR.getHeader()->id, responseBuf, &responseBufSize, &key, subnet, 0, true);
47698274 224 BOOST_CHECK_EQUAL(found, false);
78e3ac9e 225 BOOST_CHECK(!subnet);
47698274
RG
226 }
227 catch(const PDNSException& e) {
228 cerr<<"Had error: "<<e.reason<<endl;
229 throw;
230 }
231}
232
233BOOST_AUTO_TEST_CASE(test_PacketCacheNXDomainTTL) {
234 const size_t maxEntries = 150000;
235 DNSDistPacketCache PC(maxEntries, /* maxTTL */ 86400, /* minTTL */ 1, /* tempFailureTTL */ 60, /* maxNegativeTTL */ 1);
236
237 struct timespec queryTime;
238 gettime(&queryTime); // does not have to be accurate ("realTime") in tests
239
240 ComboAddress remote;
241 try {
242 DNSName name("nxdomain");
243 vector<uint8_t> query;
244 DNSPacketWriter pwQ(query, name, QType::A, QClass::IN, 0);
245 pwQ.getHeader()->rd = 1;
246
247 vector<uint8_t> response;
248 DNSPacketWriter pwR(response, name, QType::A, QClass::IN, 0);
249 pwR.getHeader()->rd = 1;
250 pwR.getHeader()->ra = 0;
251 pwR.getHeader()->qr = 1;
252 pwR.getHeader()->rcode = RCode::NXDomain;
253 pwR.getHeader()->id = pwQ.getHeader()->id;
254 pwR.commit();
255 pwR.startRecord(name, QType::SOA, 86400, QClass::IN, DNSResourceRecord::AUTHORITY);
256 pwR.commit();
257 pwR.addOpt(4096, 0, 0);
258 pwR.commit();
259
260 uint16_t responseLen = response.size();
261
262 char responseBuf[4096];
263 uint16_t responseBufSize = sizeof(responseBuf);
264 uint32_t key = 0;
78e3ac9e 265 boost::optional<Netmask> subnet;
8dcdbdb1 266 auto dh = reinterpret_cast<dnsheader*>(query.data());
e7c732b8 267 DNSQuestion dq(&name, QType::A, QClass::IN, 0, &remote, &remote, dh, query.size(), query.size(), false, &queryTime);
78e3ac9e 268 bool found = PC.get(dq, name.wirelength(), 0, responseBuf, &responseBufSize, &key, subnet);
47698274 269 BOOST_CHECK_EQUAL(found, false);
78e3ac9e 270 BOOST_CHECK(!subnet);
47698274 271
78e3ac9e
RG
272 PC.insert(key, subnet, *(getFlagsFromDNSHeader(dh)), name, QType::A, QClass::IN, reinterpret_cast<const char*>(response.data()), responseLen, false, RCode::NXDomain, boost::none);
273 found = PC.get(dq, name.wirelength(), pwR.getHeader()->id, responseBuf, &responseBufSize, &key, subnet, 0, true);
47698274 274 BOOST_CHECK_EQUAL(found, true);
78e3ac9e
RG
275 BOOST_CHECK(!subnet);
276
47698274
RG
277 sleep(2);
278 /* it should have expired by now */
78e3ac9e 279 found = PC.get(dq, name.wirelength(), pwR.getHeader()->id, responseBuf, &responseBufSize, &key, subnet, 0, true);
47698274 280 BOOST_CHECK_EQUAL(found, false);
78e3ac9e 281 BOOST_CHECK(!subnet);
47698274
RG
282 }
283 catch(const PDNSException& e) {
284 cerr<<"Had error: "<<e.reason<<endl;
285 throw;
286 }
287}
288
886e2cf2
RG
289static DNSDistPacketCache PC(500000);
290
af619119 291static void *threadMangler(void* off)
886e2cf2 292{
5ffb2f83
CH
293 struct timespec queryTime;
294 gettime(&queryTime); // does not have to be accurate ("realTime") in tests
886e2cf2 295 try {
1ea747c0 296 ComboAddress remote;
af619119 297 unsigned int offset=(unsigned int)(unsigned long)off;
886e2cf2
RG
298 for(unsigned int counter=0; counter < 100000; ++counter) {
299 DNSName a=DNSName("hello ")+DNSName(std::to_string(counter+offset));
300 vector<uint8_t> query;
301 DNSPacketWriter pwQ(query, a, QType::A, QClass::IN, 0);
302 pwQ.getHeader()->rd = 1;
303
304 vector<uint8_t> response;
305 DNSPacketWriter pwR(response, a, QType::A, QClass::IN, 0);
306 pwR.getHeader()->rd = 1;
307 pwR.getHeader()->ra = 1;
308 pwR.getHeader()->qr = 1;
309 pwR.getHeader()->id = pwQ.getHeader()->id;
310 pwR.startRecord(a, QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER);
311 pwR.xfr32BitInt(0x01020304);
312 pwR.commit();
313 uint16_t responseLen = response.size();
314
315 char responseBuf[4096];
316 uint16_t responseBufSize = sizeof(responseBuf);
317 uint32_t key = 0;
78e3ac9e 318 boost::optional<Netmask> subnet;
8dcdbdb1 319 auto dh = reinterpret_cast<dnsheader*>(query.data());
e7c732b8 320 DNSQuestion dq(&a, QType::A, QClass::IN, 0, &remote, &remote, dh, query.size(), query.size(), false, &queryTime);
78e3ac9e 321 PC.get(dq, a.wirelength(), 0, responseBuf, &responseBufSize, &key, subnet);
886e2cf2 322
78e3ac9e 323 PC.insert(key, subnet, *(getFlagsFromDNSHeader(dh)), a, QType::A, QClass::IN, (const char*) response.data(), responseLen, false, 0, boost::none);
886e2cf2
RG
324 }
325 }
326 catch(PDNSException& e) {
327 cerr<<"Had error: "<<e.reason<<endl;
328 throw;
329 }
330 return 0;
331}
332
333AtomicCounter g_missing;
334
af619119 335static void *threadReader(void* off)
886e2cf2 336{
5ffb2f83
CH
337 struct timespec queryTime;
338 gettime(&queryTime); // does not have to be accurate ("realTime") in tests
886e2cf2
RG
339 try
340 {
af619119 341 unsigned int offset=(unsigned int)(unsigned long)off;
886e2cf2 342 vector<DNSResourceRecord> entry;
1ea747c0 343 ComboAddress remote;
886e2cf2
RG
344 for(unsigned int counter=0; counter < 100000; ++counter) {
345 DNSName a=DNSName("hello ")+DNSName(std::to_string(counter+offset));
346 vector<uint8_t> query;
347 DNSPacketWriter pwQ(query, a, QType::A, QClass::IN, 0);
348 pwQ.getHeader()->rd = 1;
349
350 char responseBuf[4096];
351 uint16_t responseBufSize = sizeof(responseBuf);
352 uint32_t key = 0;
78e3ac9e 353 boost::optional<Netmask> subnet;
e7c732b8 354 DNSQuestion dq(&a, QType::A, QClass::IN, 0, &remote, &remote, (struct dnsheader*) query.data(), query.size(), query.size(), false, &queryTime);
78e3ac9e 355 bool found = PC.get(dq, a.wirelength(), 0, responseBuf, &responseBufSize, &key, subnet);
886e2cf2
RG
356 if (!found) {
357 g_missing++;
358 }
359 }
360 }
361 catch(PDNSException& e) {
362 cerr<<"Had error in threadReader: "<<e.reason<<endl;
363 throw;
364 }
365 return 0;
366}
367
368BOOST_AUTO_TEST_CASE(test_PacketCacheThreaded) {
369 try {
370 pthread_t tid[4];
371 for(int i=0; i < 4; ++i)
372 pthread_create(&tid[i], 0, threadMangler, (void*)(i*1000000UL));
373 void* res;
374 for(int i=0; i < 4 ; ++i)
375 pthread_join(tid[i], &res);
376
377 BOOST_CHECK_EQUAL(PC.getSize() + PC.getDeferredInserts() + PC.getInsertCollisions(), 400000);
378 BOOST_CHECK_SMALL(1.0*PC.getInsertCollisions(), 10000.0);
379
380 for(int i=0; i < 4; ++i)
381 pthread_create(&tid[i], 0, threadReader, (void*)(i*1000000UL));
382 for(int i=0; i < 4 ; ++i)
383 pthread_join(tid[i], &res);
384
385 BOOST_CHECK((PC.getDeferredInserts() + PC.getDeferredLookups() + PC.getInsertCollisions()) >= g_missing);
386 }
387 catch(PDNSException& e) {
388 cerr<<"Had error: "<<e.reason<<endl;
389 throw;
390 }
391
392}
393
78e3ac9e
RG
394BOOST_AUTO_TEST_CASE(test_PCCollision) {
395 const size_t maxEntries = 150000;
396 DNSDistPacketCache PC(maxEntries, 86400, 1, 60, 3600, 60, false, 1, true, true);
397 BOOST_CHECK_EQUAL(PC.getSize(), 0);
398
399 DNSName qname("www.powerdns.com.");
400 uint16_t qtype = QType::AAAA;
401 uint16_t qid = 0x42;
402 uint32_t key;
403 uint32_t secondKey;
404 boost::optional<Netmask> subnetOut;
405
406 /* lookup for a query with an ECS value of 10.0.118.46/32,
407 insert a corresponding response */
408 {
409 vector<uint8_t> query;
410 DNSPacketWriter pwQ(query, qname, qtype, QClass::IN, 0);
411 pwQ.getHeader()->rd = 1;
412 pwQ.getHeader()->id = qid;
413 DNSPacketWriter::optvect_t ednsOptions;
414 EDNSSubnetOpts opt;
415 opt.source = Netmask("10.0.118.46/32");
416 ednsOptions.push_back(std::make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(opt)));
417 pwQ.addOpt(512, 0, 0, ednsOptions);
418 pwQ.commit();
419
420 char responseBuf[4096];
421 uint16_t responseBufSize = sizeof(responseBuf);
422 ComboAddress remote("192.0.2.1");
423 struct timespec queryTime;
424 gettime(&queryTime);
e7c732b8 425 DNSQuestion dq(&qname, QType::AAAA, QClass::IN, 0, &remote, &remote, pwQ.getHeader(), query.size(), query.size(), false, &queryTime);
78e3ac9e
RG
426 bool found = PC.get(dq, qname.wirelength(), 0, responseBuf, &responseBufSize, &key, subnetOut);
427 BOOST_CHECK_EQUAL(found, false);
428 BOOST_REQUIRE(subnetOut);
429 BOOST_CHECK_EQUAL(subnetOut->toString(), opt.source.toString());
430
431 vector<uint8_t> response;
432 DNSPacketWriter pwR(response, qname, qtype, QClass::IN, 0);
433 pwR.getHeader()->rd = 1;
434 pwR.getHeader()->id = qid;
435 pwR.startRecord(qname, qtype, 100, QClass::IN, DNSResourceRecord::ANSWER);
436 ComboAddress v6("::1");
437 pwR.xfrCAWithoutPort(6, v6);
438 pwR.commit();
439 pwR.addOpt(512, 0, 0, ednsOptions);
440 pwR.commit();
441
442 PC.insert(key, subnetOut, *(getFlagsFromDNSHeader(pwR.getHeader())), qname, qtype, QClass::IN, reinterpret_cast<const char*>(response.data()), response.size(), false, RCode::NoError, boost::none);
443 BOOST_CHECK_EQUAL(PC.getSize(), 1);
444
445 found = PC.get(dq, qname.wirelength(), 0, responseBuf, &responseBufSize, &key, subnetOut);
446 BOOST_CHECK_EQUAL(found, true);
447 BOOST_REQUIRE(subnetOut);
448 BOOST_CHECK_EQUAL(subnetOut->toString(), opt.source.toString());
449 }
450
451 /* now lookup for the same query with an ECS value of 10.0.123.193/32
452 we should get the same key (collision) but no match */
453 {
454 vector<uint8_t> query;
455 DNSPacketWriter pwQ(query, qname, qtype, QClass::IN, 0);
456 pwQ.getHeader()->rd = 1;
457 pwQ.getHeader()->id = qid;
458 DNSPacketWriter::optvect_t ednsOptions;
459 EDNSSubnetOpts opt;
460 opt.source = Netmask("10.0.123.193/32");
461 ednsOptions.push_back(std::make_pair(EDNSOptionCode::ECS, makeEDNSSubnetOptsString(opt)));
462 pwQ.addOpt(512, 0, 0, ednsOptions);
463 pwQ.commit();
464
465 char responseBuf[4096];
466 uint16_t responseBufSize = sizeof(responseBuf);
467 ComboAddress remote("192.0.2.1");
468 struct timespec queryTime;
469 gettime(&queryTime);
e7c732b8 470 DNSQuestion dq(&qname, QType::AAAA, QClass::IN, 0, &remote, &remote, pwQ.getHeader(), query.size(), query.size(), false, &queryTime);
78e3ac9e
RG
471 bool found = PC.get(dq, qname.wirelength(), 0, responseBuf, &responseBufSize, &secondKey, subnetOut);
472 BOOST_CHECK_EQUAL(found, false);
473 BOOST_CHECK_EQUAL(secondKey, key);
474 BOOST_REQUIRE(subnetOut);
475 BOOST_CHECK_EQUAL(subnetOut->toString(), opt.source.toString());
476 BOOST_CHECK_EQUAL(PC.getLookupCollisions(), 1);
477 }
478}
479
886e2cf2 480BOOST_AUTO_TEST_SUITE_END()