1 #ifndef BOOST_TEST_DYN_LINK
2 #define BOOST_TEST_DYN_LINK
5 #define BOOST_TEST_NO_MAIN
11 #include <boost/test/unit_test.hpp>
13 #include "dnsparser.hh"
15 BOOST_AUTO_TEST_SUITE(test_dnsparser_cc
)
17 BOOST_AUTO_TEST_CASE(test_editDNSPacketTTL
) {
19 auto generatePacket
= [](uint32_t ttl
) {
20 DNSName
name("powerdns.com.");
21 ComboAddress
v4("1.2.3.4");
22 ComboAddress
v6("2001:db8::1");
24 vector
<uint8_t> packet
;
25 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
26 pwR
.getHeader()->qr
= 1;
28 /* record we want to see altered */
29 pwR
.startRecord(name
, QType::A
, ttl
, QClass::IN
, DNSResourceRecord::ANSWER
);
30 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
33 /* same record but different TTL (yeah, don't do that but it's just a test) */
34 pwR
.startRecord(name
, QType::A
, 100, QClass::IN
, DNSResourceRecord::ANSWER
);
35 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
39 pwR
.startRecord(name
, QType::AAAA
, 42, QClass::IN
, DNSResourceRecord::ANSWER
);
40 pwR
.xfrIP6(std::string(reinterpret_cast<const char*>(v6
.sin6
.sin6_addr
.s6_addr
), 16));
44 pwR
.startRecord(name
, QType::A
, 42, QClass::CHAOS
, DNSResourceRecord::ANSWER
);
47 /* different section */
48 pwR
.startRecord(name
, QType::A
, 42, QClass::IN
, DNSResourceRecord::AUTHORITY
);
49 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
55 auto firstPacket
= generatePacket(42);
56 auto expectedAlteredPacket
= generatePacket(84);
59 editDNSPacketTTL(reinterpret_cast<char*>(firstPacket
.data()), firstPacket
.size(), [&called
](uint8_t section
, uint16_t class_
, uint16_t type
, uint32_t ttl
) {
63 /* only updates the TTL of IN/A, in answer, with an existing ttl of 42 */
64 if (section
== 1 && class_
== QClass::IN
&& type
== QType::A
&& ttl
== 42) {
70 /* check that we have been for all records */
71 BOOST_CHECK_EQUAL(called
, 5U);
73 BOOST_REQUIRE_EQUAL(firstPacket
.size(), expectedAlteredPacket
.size());
74 for (size_t idx
= 0; idx
< firstPacket
.size(); idx
++) {
75 BOOST_CHECK_EQUAL(firstPacket
.at(idx
), expectedAlteredPacket
.at(idx
));
77 BOOST_CHECK(firstPacket
== expectedAlteredPacket
);
79 /* now call it with a truncated packet, missing the last TTL and rdata,
80 we should only be called 4 times but everything else should be fine. */
82 editDNSPacketTTL(reinterpret_cast<char*>(firstPacket
.data()), firstPacket
.size() - sizeof(uint32_t) - /* rdata length */ sizeof (uint16_t) - /* IPv4 payload in rdata */ 4, [&called
](uint8_t section
, uint16_t class_
, uint16_t type
, uint32_t ttl
) {
86 /* only updates the TTL of IN/A, in answer, with an existing ttl of 42 */
87 if (section
== 1 && class_
== QClass::IN
&& type
== QType::A
&& ttl
== 42) {
93 /* check that we have been for all records */
94 BOOST_CHECK_EQUAL(called
, 4U);
95 BOOST_CHECK(firstPacket
== expectedAlteredPacket
);
98 BOOST_AUTO_TEST_CASE(test_ageDNSPacket
) {
100 auto generatePacket
= [](uint32_t ttl
) {
101 DNSName
name("powerdns.com.");
102 ComboAddress
v4("1.2.3.4");
103 ComboAddress
v6("2001:db8::1");
105 vector
<uint8_t> packet
;
106 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
107 pwR
.getHeader()->qr
= 1;
109 /* record we want to see altered */
110 pwR
.startRecord(name
, QType::A
, ttl
, QClass::IN
, DNSResourceRecord::ANSWER
);
111 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
114 pwR
.addOpt(4096, 0, 0);
120 auto firstPacket
= generatePacket(3600);
121 auto expectedAlteredPacket
= generatePacket(1800);
123 dnsheader_aligned
dh_aligned(firstPacket
.data());
124 ageDNSPacket(reinterpret_cast<char*>(firstPacket
.data()), firstPacket
.size(), 1800, dh_aligned
);
126 BOOST_REQUIRE_EQUAL(firstPacket
.size(), expectedAlteredPacket
.size());
127 for (size_t idx
= 0; idx
< firstPacket
.size(); idx
++) {
128 BOOST_CHECK_EQUAL(firstPacket
.at(idx
), expectedAlteredPacket
.at(idx
));
130 BOOST_CHECK(firstPacket
== expectedAlteredPacket
);
132 /* now call it with a truncated packet, missing the last TTL and rdata,
133 the packet should not be altered. */
134 ageDNSPacket(reinterpret_cast<char*>(firstPacket
.data()), firstPacket
.size() - sizeof(uint32_t) - /* rdata length */ sizeof (uint16_t) - /* IPv4 payload in rdata */ 4 - /* size of OPT record */ 11, 900, dh_aligned
);
136 BOOST_CHECK(firstPacket
== expectedAlteredPacket
);
138 /* now remove more than the remaining TTL. We expect ageDNSPacket
139 to cap this at zero and not cause an unsigned underflow into
140 the 2^32-1 neighbourhood */
141 ageDNSPacket(reinterpret_cast<char*>(firstPacket
.data()), firstPacket
.size(), 1801, dh_aligned
);
145 expectedAlteredPacket
= generatePacket(ttl
);
146 BOOST_REQUIRE_EQUAL(firstPacket
.size(), expectedAlteredPacket
.size());
147 for (size_t idx
= 0; idx
< firstPacket
.size(); idx
++) {
148 BOOST_CHECK_EQUAL(firstPacket
.at(idx
), expectedAlteredPacket
.at(idx
));
150 BOOST_CHECK(firstPacket
== expectedAlteredPacket
);
153 BOOST_AUTO_TEST_CASE(test_getDNSPacketMinTTL
) {
155 const DNSName
name("powerdns.com.");
156 const ComboAddress
v4("1.2.3.4");
157 const ComboAddress
v6("2001:db8::1");
161 vector
<uint8_t> packet
;
162 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
163 pwR
.getHeader()->qr
= 1;
166 auto result
= getDNSPacketMinTTL(reinterpret_cast<char*>(packet
.data()), packet
.size(), nullptr);
167 BOOST_CHECK_EQUAL(result
, std::numeric_limits
<uint32_t>::max());
171 /* only one record, not an OPT one */
173 vector
<uint8_t> packet
;
174 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
175 pwR
.getHeader()->qr
= 1;
178 pwR
.startRecord(name
, QType::A
, ttl
, QClass::IN
, DNSResourceRecord::ANSWER
);
179 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
182 auto result
= getDNSPacketMinTTL(reinterpret_cast<char*>(packet
.data()), packet
.size(), nullptr);
183 BOOST_CHECK_EQUAL(result
, ttl
);
187 /* only one record, an OPT one */
188 vector
<uint8_t> packet
;
189 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
190 pwR
.getHeader()->qr
= 1;
193 pwR
.addOpt(4096, 0, 0);
196 auto result
= getDNSPacketMinTTL(reinterpret_cast<char*>(packet
.data()), packet
.size(), nullptr);
197 BOOST_CHECK_EQUAL(result
, std::numeric_limits
<uint32_t>::max());
201 /* records with different TTLs, should return the lower */
202 vector
<uint8_t> packet
;
203 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
204 pwR
.getHeader()->qr
= 1;
207 pwR
.startRecord(name
, QType::A
, 257, QClass::IN
, DNSResourceRecord::ANSWER
);
208 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
211 pwR
.startRecord(name
, QType::A
, 255, QClass::IN
, DNSResourceRecord::AUTHORITY
);
212 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
215 pwR
.startRecord(name
, QType::A
, 256, QClass::IN
, DNSResourceRecord::ADDITIONAL
);
216 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
219 auto result
= getDNSPacketMinTTL(reinterpret_cast<char*>(packet
.data()), packet
.size(), nullptr);
220 BOOST_CHECK_EQUAL(result
, 255U);
224 /* SOA record in answer, seenAuthSOA should not be set */
225 vector
<uint8_t> packet
;
226 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
227 pwR
.getHeader()->qr
= 1;
230 pwR
.startRecord(name
, QType::SOA
, 257, QClass::IN
, DNSResourceRecord::ANSWER
);
233 pwR
.startRecord(name
, QType::A
, 255, QClass::IN
, DNSResourceRecord::AUTHORITY
);
234 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
237 pwR
.startRecord(name
, QType::A
, 256, QClass::IN
, DNSResourceRecord::ADDITIONAL
);
238 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
241 bool seenAuthSOA
= false;
242 auto result
= getDNSPacketMinTTL(reinterpret_cast<char*>(packet
.data()), packet
.size(), &seenAuthSOA
);
243 BOOST_CHECK_EQUAL(result
, 255U);
244 BOOST_CHECK_EQUAL(seenAuthSOA
, false);
248 /* one SOA record in auth, seenAuthSOA should be set */
249 vector
<uint8_t> packet
;
250 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
251 pwR
.getHeader()->qr
= 1;
254 pwR
.startRecord(name
, QType::A
, 255, QClass::IN
, DNSResourceRecord::ANSWER
);
255 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
258 pwR
.startRecord(name
, QType::SOA
, 257, QClass::IN
, DNSResourceRecord::AUTHORITY
);
261 pwR
.startRecord(name
, QType::A
, 256, QClass::IN
, DNSResourceRecord::ADDITIONAL
);
262 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
265 bool seenAuthSOA
= false;
266 auto result
= getDNSPacketMinTTL(reinterpret_cast<char*>(packet
.data()), packet
.size(), &seenAuthSOA
);
267 BOOST_CHECK_EQUAL(result
, 255U);
268 BOOST_CHECK_EQUAL(seenAuthSOA
, true);
272 /* one SOA record of the wrong qclass in auth, seenAuthSOA should not be set */
273 vector
<uint8_t> packet
;
274 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
275 pwR
.getHeader()->qr
= 1;
278 pwR
.startRecord(name
, QType::A
, 257, QClass::IN
, DNSResourceRecord::ANSWER
);
279 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
282 pwR
.startRecord(name
, QType::SOA
, 255, QClass::CHAOS
, DNSResourceRecord::AUTHORITY
);
285 pwR
.startRecord(name
, QType::A
, 256, QClass::IN
, DNSResourceRecord::ADDITIONAL
);
286 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
289 bool seenAuthSOA
= false;
290 auto result
= getDNSPacketMinTTL(reinterpret_cast<char*>(packet
.data()), packet
.size(), &seenAuthSOA
);
291 BOOST_CHECK_EQUAL(result
, 255U);
292 BOOST_CHECK_EQUAL(seenAuthSOA
, false);
296 /* one A record in auth, seenAuthSOA should not be set */
297 vector
<uint8_t> packet
;
298 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
299 pwR
.getHeader()->qr
= 1;
302 pwR
.startRecord(name
, QType::A
, 257, QClass::IN
, DNSResourceRecord::AUTHORITY
);
303 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
306 bool seenAuthSOA
= false;
307 auto result
= getDNSPacketMinTTL(reinterpret_cast<char*>(packet
.data()), packet
.size(), &seenAuthSOA
);
308 BOOST_CHECK_EQUAL(result
, 257U);
309 BOOST_CHECK_EQUAL(seenAuthSOA
, false);
313 /* one SOA record in additional, seenAuthSOA should not be set */
314 vector
<uint8_t> packet
;
315 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
316 pwR
.getHeader()->qr
= 1;
319 pwR
.startRecord(name
, QType::SOA
, 255, QClass::IN
, DNSResourceRecord::ADDITIONAL
);
322 bool seenAuthSOA
= false;
323 auto result
= getDNSPacketMinTTL(reinterpret_cast<char*>(packet
.data()), packet
.size(), &seenAuthSOA
);
324 BOOST_CHECK_EQUAL(result
, 255U);
325 BOOST_CHECK_EQUAL(seenAuthSOA
, false);
329 /* truncated packet, no exception should be raised */
330 /* one SOA record in auth, seenAuthSOA should be set */
331 vector
<uint8_t> packet
;
332 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
333 pwR
.getHeader()->qr
= 1;
336 pwR
.startRecord(name
, QType::A
, 255, QClass::IN
, DNSResourceRecord::ANSWER
);
337 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
340 pwR
.startRecord(name
, QType::SOA
, 257, QClass::IN
, DNSResourceRecord::AUTHORITY
);
343 pwR
.startRecord(name
, QType::A
, 254, QClass::IN
, DNSResourceRecord::ADDITIONAL
);
344 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
347 bool seenAuthSOA
= false;
348 auto result
= getDNSPacketMinTTL(reinterpret_cast<char*>(packet
.data()), packet
.size() - sizeof(uint32_t) - /* rdata length */ sizeof (uint16_t) - /* IPv4 payload in rdata */ 4, &seenAuthSOA
);
349 BOOST_CHECK_EQUAL(result
, 255U);
350 BOOST_CHECK_EQUAL(seenAuthSOA
, true);
354 BOOST_AUTO_TEST_CASE(test_getDNSPacketLength
) {
356 const DNSName
name("powerdns.com.");
357 const ComboAddress
v4("1.2.3.4");
358 const ComboAddress
v6("2001:db8::1");
362 vector
<uint8_t> packet
;
363 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
364 pwR
.getHeader()->qr
= 1;
367 auto result
= getDNSPacketLength(reinterpret_cast<char*>(packet
.data()), packet
.size());
368 BOOST_CHECK_EQUAL(result
, packet
.size());
372 /* several records */
373 vector
<uint8_t> packet
;
374 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
375 pwR
.getHeader()->qr
= 1;
378 pwR
.startRecord(name
, QType::A
, 255, QClass::IN
, DNSResourceRecord::ANSWER
);
379 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
382 pwR
.startRecord(name
, QType::SOA
, 257, QClass::IN
, DNSResourceRecord::AUTHORITY
);
385 pwR
.startRecord(name
, QType::A
, 256, QClass::IN
, DNSResourceRecord::ADDITIONAL
);
386 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
389 pwR
.addOpt(4096, 0, 0);
392 auto result
= getDNSPacketLength(reinterpret_cast<char*>(packet
.data()), packet
.size());
393 BOOST_CHECK_EQUAL(result
, packet
.size());
398 vector
<uint8_t> packet
;
399 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
400 pwR
.getHeader()->qr
= 1;
403 pwR
.startRecord(name
, QType::A
, 255, QClass::IN
, DNSResourceRecord::ANSWER
);
404 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
407 pwR
.startRecord(name
, QType::SOA
, 257, QClass::IN
, DNSResourceRecord::AUTHORITY
);
410 pwR
.startRecord(name
, QType::A
, 256, QClass::IN
, DNSResourceRecord::ADDITIONAL
);
411 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
414 pwR
.addOpt(4096, 0, 0);
417 auto realSize
= packet
.size();
418 packet
.resize(realSize
+ 512);
419 auto result
= getDNSPacketLength(reinterpret_cast<char*>(packet
.data()), packet
.size());
420 BOOST_CHECK_EQUAL(result
, realSize
);
424 /* truncated packet, should return the full size */
425 vector
<uint8_t> packet
;
426 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
427 pwR
.getHeader()->qr
= 1;
430 pwR
.startRecord(name
, QType::A
, 255, QClass::IN
, DNSResourceRecord::ANSWER
);
431 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
434 pwR
.startRecord(name
, QType::SOA
, 257, QClass::IN
, DNSResourceRecord::AUTHORITY
);
437 pwR
.startRecord(name
, QType::A
, 256, QClass::IN
, DNSResourceRecord::ADDITIONAL
);
438 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
441 pwR
.addOpt(4096, 0, 0);
444 size_t fakeSize
= packet
.size()-1;
445 auto result
= getDNSPacketLength(reinterpret_cast<char*>(packet
.data()), fakeSize
);
446 BOOST_CHECK_EQUAL(result
, fakeSize
);
451 BOOST_AUTO_TEST_CASE(test_getRecordsOfTypeCount
) {
452 const DNSName
name("powerdns.com.");
453 const ComboAddress
v4("1.2.3.4");
454 const ComboAddress
v6("2001:db8::1");
457 vector
<uint8_t> packet
;
458 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
459 pwR
.getHeader()->qr
= 1;
462 pwR
.startRecord(name
, QType::A
, 255, QClass::IN
, DNSResourceRecord::ANSWER
);
463 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
466 pwR
.startRecord(name
, QType::SOA
, 257, QClass::IN
, DNSResourceRecord::AUTHORITY
);
469 pwR
.startRecord(name
, QType::A
, 256, QClass::IN
, DNSResourceRecord::ADDITIONAL
);
470 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
473 pwR
.addOpt(4096, 0, 0);
476 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 0, QType::A
), 1);
477 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 0, QType::SOA
), 0);
478 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 1, QType::A
), 1);
479 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 1, QType::SOA
), 0);
480 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 2, QType::A
), 0);
481 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 2, QType::SOA
), 1);
482 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 3, QType::A
), 1);
483 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 3, QType::SOA
), 0);
485 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 4, QType::SOA
), 0);
490 BOOST_AUTO_TEST_CASE(test_clearDNSPacketRecordTypes
) {
492 auto generatePacket
= []() {
493 const DNSName
name("powerdns.com.");
494 const ComboAddress
v4("1.2.3.4");
495 const ComboAddress
v6("2001:db8::1");
497 vector
<uint8_t> packet
;
498 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
499 pwR
.getHeader()->qr
= 1;
502 pwR
.startRecord(name
, QType::A
, 255, QClass::IN
, DNSResourceRecord::ANSWER
);
503 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
507 pwR
.startRecord(name
, QType::AAAA
, 42, QClass::IN
, DNSResourceRecord::ANSWER
);
508 pwR
.xfrIP6(std::string(reinterpret_cast<const char*>(v6
.sin6
.sin6_addr
.s6_addr
), 16));
511 pwR
.startRecord(name
, QType::A
, 256, QClass::IN
, DNSResourceRecord::ADDITIONAL
);
512 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
515 pwR
.addOpt(4096, 0, 0);
520 auto packet
= generatePacket();
522 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 1, QType::A
), 1);
523 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 1, QType::AAAA
), 1);
524 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 3, QType::A
), 1);
526 std::unordered_set
<QType
> toremove
{QType::AAAA
};
527 clearDNSPacketRecordTypes(packet
, toremove
);
529 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 1, QType::A
), 1);
530 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 1, QType::AAAA
), 0);
531 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 3, QType::A
), 1);
533 toremove
= {QType::A
};
534 clearDNSPacketRecordTypes(packet
, toremove
);
536 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 1, QType::A
), 0);
537 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 1, QType::AAAA
), 0);
538 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 3, QType::A
), 0);
540 packet
= generatePacket();
542 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 1, QType::A
), 1);
543 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 1, QType::AAAA
), 1);
544 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 3, QType::A
), 1);
546 toremove
= {QType::A
, QType::AAAA
};
547 clearDNSPacketRecordTypes(packet
, toremove
);
549 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 1, QType::A
), 0);
550 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 1, QType::AAAA
), 0);
551 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 3, QType::A
), 0);
556 BOOST_AUTO_TEST_CASE(test_clearDNSPacketUnsafeRecordTypes
) {
558 auto generatePacket
= []() {
559 const DNSName
name("powerdns.com.");
560 const DNSName
mxname("mx.powerdns.com.");
561 const ComboAddress
v4("1.2.3.4");
562 const ComboAddress
v6("2001:db8::1");
564 vector
<uint8_t> packet
;
565 DNSPacketWriter
pwR(packet
, name
, QType::A
, QClass::IN
, 0);
566 pwR
.getHeader()->qr
= 1;
569 pwR
.startRecord(name
, QType::A
, 255, QClass::IN
, DNSResourceRecord::ANSWER
);
570 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
574 pwR
.startRecord(name
, QType::AAAA
, 42, QClass::IN
, DNSResourceRecord::ANSWER
);
575 pwR
.xfrIP6(std::string(reinterpret_cast<const char*>(v6
.sin6
.sin6_addr
.s6_addr
), 16));
578 pwR
.startRecord(name
, QType::A
, 256, QClass::IN
, DNSResourceRecord::ADDITIONAL
);
579 pwR
.xfrIP(v4
.sin4
.sin_addr
.s_addr
);
582 pwR
.startRecord(name
, QType::MX
, 256, QClass::IN
, DNSResourceRecord::ADDITIONAL
);
583 pwR
.xfrName(mxname
, false);
586 pwR
.addOpt(4096, 0, 0);
591 auto packet
= generatePacket();
593 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 1, QType::A
), 1);
594 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 1, QType::AAAA
), 1);
595 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 3, QType::A
), 1);
596 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 3, QType::MX
), 1);
598 std::unordered_set
<QType
> toremove
{QType::AAAA
};
599 clearDNSPacketRecordTypes(packet
, toremove
);
601 // nothing should have been removed as an "unsafe" MX RR is in the packet
602 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 1, QType::A
), 1);
603 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 1, QType::AAAA
), 1);
604 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 3, QType::A
), 1);
605 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 3, QType::MX
), 1);
607 toremove
= {QType::MX
, QType::AAAA
};
608 clearDNSPacketRecordTypes(packet
, toremove
);
610 // MX is unsafe, but we asked to remove it
611 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 1, QType::A
), 1);
612 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 1, QType::AAAA
), 0);
613 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 3, QType::A
), 1);
614 BOOST_CHECK_EQUAL(getRecordsOfTypeCount(reinterpret_cast<char*>(packet
.data()), packet
.size(), 3, QType::MX
), 0);
619 BOOST_AUTO_TEST_SUITE_END()