2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #define BOOST_TEST_DYN_LINK
23 #define BOOST_TEST_NO_MAIN
25 #include <boost/test/unit_test.hpp>
28 #include "dnsdist-ecs.hh"
31 #include "dnsparser.hh"
32 #include "dnswriter.hh"
33 #include "ednsoptions.hh"
34 #include "ednscookies.hh"
35 #include "ednssubnet.hh"
38 BOOST_AUTO_TEST_SUITE(dnsdist_cc
)
43 static const uint16_t ECSSourcePrefixV4
= 24;
44 static const uint16_t ECSSourcePrefixV6
= 56;
46 static void validateQuery(const char * packet
, size_t packetSize
, bool hasEdns
=true)
48 MOADNSParser
mdp(true, packet
, packetSize
);
50 BOOST_CHECK_EQUAL(mdp
.d_qname
.toString(), "www.powerdns.com.");
52 BOOST_CHECK_EQUAL(mdp
.d_header
.qdcount
, 1);
53 BOOST_CHECK_EQUAL(mdp
.d_header
.ancount
, 0);
54 BOOST_CHECK_EQUAL(mdp
.d_header
.nscount
, 0);
55 BOOST_CHECK_EQUAL(mdp
.d_header
.arcount
, (hasEdns
? 1 : 0));
58 static void validateResponse(const char * packet
, size_t packetSize
, bool hasEdns
, uint8_t additionalCount
=0)
60 MOADNSParser
mdp(false, packet
, packetSize
);
62 BOOST_CHECK_EQUAL(mdp
.d_qname
.toString(), "www.powerdns.com.");
64 BOOST_CHECK_EQUAL(mdp
.d_header
.qr
, 1);
65 BOOST_CHECK_EQUAL(mdp
.d_header
.qdcount
, 1);
66 BOOST_CHECK_EQUAL(mdp
.d_header
.ancount
, 1);
67 BOOST_CHECK_EQUAL(mdp
.d_header
.nscount
, 0);
68 BOOST_CHECK_EQUAL(mdp
.d_header
.arcount
, (hasEdns
? 1 : 0) + additionalCount
);
71 BOOST_AUTO_TEST_CASE(addECSWithoutEDNS
)
73 bool ednsAdded
= false;
74 bool ecsAdded
= false;
76 DNSName
name("www.powerdns.com.");
78 vector
<uint8_t> query
;
79 DNSPacketWriter
pw(query
, name
, QType::A
, QClass::IN
, 0);
80 pw
.getHeader()->rd
= 1;
81 uint16_t len
= query
.size();
83 /* large enough packet */
85 memcpy(packet
, query
.data(), query
.size());
87 unsigned int consumed
= 0;
89 DNSName
qname(packet
, len
, sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
90 BOOST_CHECK_EQUAL(qname
, name
);
91 BOOST_CHECK(qtype
== QType::A
);
93 BOOST_CHECK(handleEDNSClientSubnet(packet
, sizeof packet
, consumed
, &len
, &ednsAdded
, &ecsAdded
, remote
, false, remote
.sin4
.sin_family
== AF_INET
? ECSSourcePrefixV4
: ECSSourcePrefixV6
));
94 BOOST_CHECK((size_t) len
> query
.size());
95 BOOST_CHECK_EQUAL(ednsAdded
, true);
96 BOOST_CHECK_EQUAL(ecsAdded
, false);
97 validateQuery(packet
, len
);
99 /* not large enough packet */
104 qname
= DNSName(reinterpret_cast<char*>(query
.data()), len
, sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
105 BOOST_CHECK_EQUAL(qname
, name
);
106 BOOST_CHECK(qtype
== QType::A
);
108 BOOST_CHECK(!handleEDNSClientSubnet(reinterpret_cast<char*>(query
.data()), query
.size(), consumed
, &len
, &ednsAdded
, &ecsAdded
, remote
, false, remote
.sin4
.sin_family
== AF_INET
? ECSSourcePrefixV4
: ECSSourcePrefixV6
));
109 BOOST_CHECK_EQUAL((size_t) len
, query
.size());
110 BOOST_CHECK_EQUAL(ednsAdded
, false);
111 BOOST_CHECK_EQUAL(ecsAdded
, false);
112 validateQuery(reinterpret_cast<char*>(query
.data()), len
, false);
115 BOOST_AUTO_TEST_CASE(addECSWithEDNSNoECS
) {
116 bool ednsAdded
= false;
117 bool ecsAdded
= false;
119 DNSName
name("www.powerdns.com.");
121 vector
<uint8_t> query
;
122 DNSPacketWriter
pw(query
, name
, QType::A
, QClass::IN
, 0);
123 pw
.getHeader()->rd
= 1;
124 pw
.addOpt(512, 0, 0);
126 uint16_t len
= query
.size();
128 /* large enough packet */
130 memcpy(packet
, query
.data(), query
.size());
132 unsigned int consumed
= 0;
134 DNSName
qname(packet
, len
, sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
135 BOOST_CHECK_EQUAL(qname
, name
);
136 BOOST_CHECK(qtype
== QType::A
);
138 BOOST_CHECK(handleEDNSClientSubnet(packet
, sizeof packet
, consumed
, &len
, &ednsAdded
, &ecsAdded
, remote
, false, remote
.sin4
.sin_family
== AF_INET
? ECSSourcePrefixV4
: ECSSourcePrefixV6
));
139 BOOST_CHECK((size_t) len
> query
.size());
140 BOOST_CHECK_EQUAL(ednsAdded
, false);
141 BOOST_CHECK_EQUAL(ecsAdded
, true);
142 validateQuery(packet
, len
);
144 /* not large enough packet */
149 qname
= DNSName(reinterpret_cast<char*>(query
.data()), len
, sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
150 BOOST_CHECK_EQUAL(qname
, name
);
151 BOOST_CHECK(qtype
== QType::A
);
153 BOOST_CHECK(!handleEDNSClientSubnet(reinterpret_cast<char*>(query
.data()), query
.size(), consumed
, &len
, &ednsAdded
, &ecsAdded
, remote
, false, remote
.sin4
.sin_family
== AF_INET
? ECSSourcePrefixV4
: ECSSourcePrefixV6
));
154 BOOST_CHECK_EQUAL((size_t) len
, query
.size());
155 BOOST_CHECK_EQUAL(ednsAdded
, false);
156 BOOST_CHECK_EQUAL(ecsAdded
, false);
157 validateQuery(reinterpret_cast<char*>(query
.data()), len
);
160 BOOST_AUTO_TEST_CASE(replaceECSWithSameSize
) {
161 bool ednsAdded
= false;
162 bool ecsAdded
= false;
163 ComboAddress
remote("192.168.1.25");
164 DNSName
name("www.powerdns.com.");
165 ComboAddress
origRemote("127.0.0.1");
167 vector
<uint8_t> query
;
168 DNSPacketWriter
pw(query
, name
, QType::A
, QClass::IN
, 0);
169 pw
.getHeader()->rd
= 1;
170 EDNSSubnetOpts ecsOpts
;
171 ecsOpts
.source
= Netmask(origRemote
, ECSSourcePrefixV4
);
172 string origECSOption
= makeEDNSSubnetOptsString(ecsOpts
);
173 DNSPacketWriter::optvect_t opts
;
174 opts
.push_back(make_pair(EDNSOptionCode::ECS
, origECSOption
));
175 pw
.addOpt(512, 0, 0, opts
);
177 uint16_t len
= query
.size();
179 /* large enough packet */
181 memcpy(packet
, query
.data(), query
.size());
183 unsigned int consumed
= 0;
185 DNSName
qname(packet
, len
, sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
186 BOOST_CHECK_EQUAL(qname
, name
);
187 BOOST_CHECK(qtype
== QType::A
);
189 BOOST_CHECK(handleEDNSClientSubnet(packet
, sizeof packet
, consumed
, &len
, &ednsAdded
, &ecsAdded
, remote
, true, remote
.sin4
.sin_family
== AF_INET
? ECSSourcePrefixV4
: ECSSourcePrefixV6
));
190 BOOST_CHECK_EQUAL((size_t) len
, query
.size());
191 BOOST_CHECK_EQUAL(ednsAdded
, false);
192 BOOST_CHECK_EQUAL(ecsAdded
, false);
193 validateQuery(packet
, len
);
196 BOOST_AUTO_TEST_CASE(replaceECSWithSmaller
) {
197 bool ednsAdded
= false;
198 bool ecsAdded
= false;
199 ComboAddress
remote("192.168.1.25");
200 DNSName
name("www.powerdns.com.");
201 ComboAddress
origRemote("127.0.0.1");
203 vector
<uint8_t> query
;
204 DNSPacketWriter
pw(query
, name
, QType::A
, QClass::IN
, 0);
205 pw
.getHeader()->rd
= 1;
206 EDNSSubnetOpts ecsOpts
;
207 ecsOpts
.source
= Netmask(origRemote
, 32);
208 string origECSOption
= makeEDNSSubnetOptsString(ecsOpts
);
209 DNSPacketWriter::optvect_t opts
;
210 opts
.push_back(make_pair(EDNSOptionCode::ECS
, origECSOption
));
211 pw
.addOpt(512, 0, 0, opts
);
213 uint16_t len
= query
.size();
215 /* large enough packet */
217 memcpy(packet
, query
.data(), query
.size());
219 unsigned int consumed
= 0;
221 DNSName
qname(packet
, len
, sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
222 BOOST_CHECK_EQUAL(qname
, name
);
223 BOOST_CHECK(qtype
== QType::A
);
225 BOOST_CHECK(handleEDNSClientSubnet(packet
, sizeof packet
, consumed
, &len
, &ednsAdded
, &ecsAdded
, remote
, true, remote
.sin4
.sin_family
== AF_INET
? ECSSourcePrefixV4
: ECSSourcePrefixV6
));
226 BOOST_CHECK((size_t) len
< query
.size());
227 BOOST_CHECK_EQUAL(ednsAdded
, false);
228 BOOST_CHECK_EQUAL(ecsAdded
, false);
229 validateQuery(packet
, len
);
232 BOOST_AUTO_TEST_CASE(replaceECSWithLarger
) {
233 bool ednsAdded
= false;
234 bool ecsAdded
= false;
235 ComboAddress
remote("192.168.1.25");
236 DNSName
name("www.powerdns.com.");
237 ComboAddress
origRemote("127.0.0.1");
239 vector
<uint8_t> query
;
240 DNSPacketWriter
pw(query
, name
, QType::A
, QClass::IN
, 0);
241 pw
.getHeader()->rd
= 1;
242 EDNSSubnetOpts ecsOpts
;
243 ecsOpts
.source
= Netmask(origRemote
, 8);
244 string origECSOption
= makeEDNSSubnetOptsString(ecsOpts
);
245 DNSPacketWriter::optvect_t opts
;
246 opts
.push_back(make_pair(EDNSOptionCode::ECS
, origECSOption
));
247 pw
.addOpt(512, 0, 0, opts
);
249 uint16_t len
= query
.size();
251 /* large enough packet */
253 memcpy(packet
, query
.data(), query
.size());
255 unsigned int consumed
= 0;
257 DNSName
qname(packet
, len
, sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
258 BOOST_CHECK_EQUAL(qname
, name
);
259 BOOST_CHECK(qtype
== QType::A
);
261 BOOST_CHECK(handleEDNSClientSubnet(packet
, sizeof packet
, consumed
, &len
, &ednsAdded
, &ecsAdded
, remote
, true, remote
.sin4
.sin_family
== AF_INET
? ECSSourcePrefixV4
: ECSSourcePrefixV6
));
262 BOOST_CHECK((size_t) len
> query
.size());
263 BOOST_CHECK_EQUAL(ednsAdded
, false);
264 BOOST_CHECK_EQUAL(ecsAdded
, false);
265 validateQuery(packet
, len
);
267 /* not large enough packet */
272 qname
= DNSName(reinterpret_cast<char*>(query
.data()), len
, sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
273 BOOST_CHECK_EQUAL(qname
, name
);
274 BOOST_CHECK(qtype
== QType::A
);
276 BOOST_CHECK(!handleEDNSClientSubnet(reinterpret_cast<char*>(query
.data()), query
.size(), consumed
, &len
, &ednsAdded
, &ecsAdded
, remote
, true, remote
.sin4
.sin_family
== AF_INET
? ECSSourcePrefixV4
: ECSSourcePrefixV6
));
277 BOOST_CHECK_EQUAL((size_t) len
, query
.size());
278 BOOST_CHECK_EQUAL(ednsAdded
, false);
279 BOOST_CHECK_EQUAL(ecsAdded
, false);
280 validateQuery(reinterpret_cast<char*>(query
.data()), len
);
283 BOOST_AUTO_TEST_CASE(removeEDNSWhenFirst
) {
284 DNSName
name("www.powerdns.com.");
286 vector
<uint8_t> response
;
287 DNSPacketWriter
pw(response
, name
, QType::A
, QClass::IN
, 0);
288 pw
.getHeader()->qr
= 1;
289 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ANSWER
, true);
290 pw
.xfr32BitInt(0x01020304);
291 pw
.addOpt(512, 0, 0);
293 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ADDITIONAL
, true);
294 pw
.xfr32BitInt(0x01020304);
297 vector
<uint8_t> newResponse
;
298 int res
= rewriteResponseWithoutEDNS(std::string((const char *) response
.data(), response
.size()), newResponse
);
299 BOOST_CHECK_EQUAL(res
, 0);
301 unsigned int consumed
= 0;
303 DNSName
qname((const char*) newResponse
.data(), newResponse
.size(), sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
304 BOOST_CHECK_EQUAL(qname
, name
);
305 BOOST_CHECK(qtype
== QType::A
);
306 size_t const ednsOptRRSize
= sizeof(struct dnsrecordheader
) + 1 /* root in OPT RR */;
307 BOOST_CHECK_EQUAL(newResponse
.size(), response
.size() - ednsOptRRSize
);
309 validateResponse((const char *) newResponse
.data(), newResponse
.size(), false, 1);
312 BOOST_AUTO_TEST_CASE(removeEDNSWhenIntermediary
) {
313 DNSName
name("www.powerdns.com.");
315 vector
<uint8_t> response
;
316 DNSPacketWriter
pw(response
, name
, QType::A
, QClass::IN
, 0);
317 pw
.getHeader()->qr
= 1;
318 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ANSWER
, true);
319 pw
.xfr32BitInt(0x01020304);
320 pw
.startRecord(DNSName("other.powerdns.com."), QType::A
, 3600, QClass::IN
, DNSResourceRecord::ADDITIONAL
, true);
321 pw
.xfr32BitInt(0x01020304);
323 pw
.addOpt(512, 0, 0);
325 pw
.startRecord(DNSName("yetanother.powerdns.com."), QType::A
, 3600, QClass::IN
, DNSResourceRecord::ADDITIONAL
, true);
326 pw
.xfr32BitInt(0x01020304);
329 vector
<uint8_t> newResponse
;
330 int res
= rewriteResponseWithoutEDNS(std::string((const char *) response
.data(), response
.size()), newResponse
);
331 BOOST_CHECK_EQUAL(res
, 0);
333 unsigned int consumed
= 0;
335 DNSName
qname((const char*) newResponse
.data(), newResponse
.size(), sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
336 BOOST_CHECK_EQUAL(qname
, name
);
337 BOOST_CHECK(qtype
== QType::A
);
338 size_t const ednsOptRRSize
= sizeof(struct dnsrecordheader
) + 1 /* root in OPT RR */;
339 BOOST_CHECK_EQUAL(newResponse
.size(), response
.size() - ednsOptRRSize
);
341 validateResponse((const char *) newResponse
.data(), newResponse
.size(), false, 2);
344 BOOST_AUTO_TEST_CASE(removeEDNSWhenLast
) {
345 DNSName
name("www.powerdns.com.");
347 vector
<uint8_t> response
;
348 DNSPacketWriter
pw(response
, name
, QType::A
, QClass::IN
, 0);
349 pw
.getHeader()->qr
= 1;
350 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ANSWER
, true);
351 pw
.xfr32BitInt(0x01020304);
353 pw
.startRecord(DNSName("other.powerdns.com."), QType::A
, 3600, QClass::IN
, DNSResourceRecord::ADDITIONAL
, true);
354 pw
.xfr32BitInt(0x01020304);
356 pw
.addOpt(512, 0, 0);
359 vector
<uint8_t> newResponse
;
360 int res
= rewriteResponseWithoutEDNS(std::string((const char *) response
.data(), response
.size()), newResponse
);
362 BOOST_CHECK_EQUAL(res
, 0);
364 unsigned int consumed
= 0;
366 DNSName
qname((const char*) newResponse
.data(), newResponse
.size(), sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
367 BOOST_CHECK_EQUAL(qname
, name
);
368 BOOST_CHECK(qtype
== QType::A
);
369 size_t const ednsOptRRSize
= sizeof(struct dnsrecordheader
) + 1 /* root in OPT RR */;
370 BOOST_CHECK_EQUAL(newResponse
.size(), response
.size() - ednsOptRRSize
);
372 validateResponse((const char *) newResponse
.data(), newResponse
.size(), false, 1);
375 BOOST_AUTO_TEST_CASE(removeECSWhenOnlyOption
) {
376 DNSName
name("www.powerdns.com.");
377 ComboAddress
origRemote("127.0.0.1");
379 vector
<uint8_t> response
;
380 DNSPacketWriter
pw(response
, name
, QType::A
, QClass::IN
, 0);
381 pw
.getHeader()->qr
= 1;
382 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ANSWER
, true);
383 pw
.xfr32BitInt(0x01020304);
385 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ADDITIONAL
, true);
386 pw
.xfr32BitInt(0x01020304);
389 EDNSSubnetOpts ecsOpts
;
390 ecsOpts
.source
= Netmask(origRemote
, ECSSourcePrefixV4
);
391 string origECSOptionStr
= makeEDNSSubnetOptsString(ecsOpts
);
392 DNSPacketWriter::optvect_t opts
;
393 opts
.push_back(make_pair(EDNSOptionCode::ECS
, origECSOptionStr
));
394 pw
.addOpt(512, 0, 0, opts
);
401 int res
= locateEDNSOptRR(std::string((char *) response
.data(), response
.size()), &optStart
, &optLen
, &last
);
402 BOOST_CHECK_EQUAL(res
, 0);
403 BOOST_CHECK_EQUAL(last
, true);
405 size_t responseLen
= response
.size();
406 size_t existingOptLen
= optLen
;
407 BOOST_CHECK(existingOptLen
< responseLen
);
408 res
= removeEDNSOptionFromOPT(reinterpret_cast<char *>(response
.data()) + optStart
, &optLen
, EDNSOptionCode::ECS
);
409 BOOST_CHECK_EQUAL(res
, 0);
410 BOOST_CHECK_EQUAL(optLen
, existingOptLen
- (origECSOptionStr
.size() + 4));
411 responseLen
-= (existingOptLen
- optLen
);
413 unsigned int consumed
= 0;
415 DNSName
qname((const char*) response
.data(), responseLen
, sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
416 BOOST_CHECK_EQUAL(qname
, name
);
417 BOOST_CHECK(qtype
== QType::A
);
419 validateResponse((const char *) response
.data(), responseLen
, true, 1);
422 BOOST_AUTO_TEST_CASE(removeECSWhenFirstOption
) {
423 DNSName
name("www.powerdns.com.");
424 ComboAddress
origRemote("127.0.0.1");
426 vector
<uint8_t> response
;
427 DNSPacketWriter
pw(response
, name
, QType::A
, QClass::IN
, 0);
428 pw
.getHeader()->qr
= 1;
429 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ANSWER
, true);
430 pw
.xfr32BitInt(0x01020304);
432 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ADDITIONAL
, true);
433 pw
.xfr32BitInt(0x01020304);
436 EDNSSubnetOpts ecsOpts
;
437 ecsOpts
.source
= Netmask(origRemote
, ECSSourcePrefixV6
);
438 string origECSOptionStr
= makeEDNSSubnetOptsString(ecsOpts
);
439 EDNSCookiesOpt cookiesOpt
;
440 cookiesOpt
.client
= string("deadbeef");
441 cookiesOpt
.server
= string("deadbeef");
442 string cookiesOptionStr
= makeEDNSCookiesOptString(cookiesOpt
);
443 DNSPacketWriter::optvect_t opts
;
444 opts
.push_back(make_pair(EDNSOptionCode::ECS
, origECSOptionStr
));
445 opts
.push_back(make_pair(EDNSOptionCode::COOKIE
, cookiesOptionStr
));
446 pw
.addOpt(512, 0, 0, opts
);
453 int res
= locateEDNSOptRR(std::string((char *) response
.data(), response
.size()), &optStart
, &optLen
, &last
);
454 BOOST_CHECK_EQUAL(res
, 0);
455 BOOST_CHECK_EQUAL(last
, true);
457 size_t responseLen
= response
.size();
458 size_t existingOptLen
= optLen
;
459 BOOST_CHECK(existingOptLen
< responseLen
);
460 res
= removeEDNSOptionFromOPT(reinterpret_cast<char *>(response
.data()) + optStart
, &optLen
, EDNSOptionCode::ECS
);
461 BOOST_CHECK_EQUAL(res
, 0);
462 BOOST_CHECK_EQUAL(optLen
, existingOptLen
- (origECSOptionStr
.size() + 4));
463 responseLen
-= (existingOptLen
- optLen
);
465 unsigned int consumed
= 0;
467 DNSName
qname((const char*) response
.data(), responseLen
, sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
468 BOOST_CHECK_EQUAL(qname
, name
);
469 BOOST_CHECK(qtype
== QType::A
);
471 validateResponse((const char *) response
.data(), responseLen
, true, 1);
474 BOOST_AUTO_TEST_CASE(removeECSWhenIntermediaryOption
) {
475 DNSName
name("www.powerdns.com.");
476 ComboAddress
origRemote("127.0.0.1");
478 vector
<uint8_t> response
;
479 DNSPacketWriter
pw(response
, name
, QType::A
, QClass::IN
, 0);
480 pw
.getHeader()->qr
= 1;
481 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ANSWER
, true);
482 pw
.xfr32BitInt(0x01020304);
484 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ADDITIONAL
, true);
485 pw
.xfr32BitInt(0x01020304);
488 EDNSSubnetOpts ecsOpts
;
489 ecsOpts
.source
= Netmask(origRemote
, ECSSourcePrefixV4
);
490 string origECSOptionStr
= makeEDNSSubnetOptsString(ecsOpts
);
492 EDNSCookiesOpt cookiesOpt
;
493 cookiesOpt
.client
= string("deadbeef");
494 cookiesOpt
.server
= string("deadbeef");
495 string cookiesOptionStr1
= makeEDNSCookiesOptString(cookiesOpt
);
496 string cookiesOptionStr2
= makeEDNSCookiesOptString(cookiesOpt
);
498 DNSPacketWriter::optvect_t opts
;
499 opts
.push_back(make_pair(EDNSOptionCode::COOKIE
, cookiesOptionStr1
));
500 opts
.push_back(make_pair(EDNSOptionCode::ECS
, origECSOptionStr
));
501 opts
.push_back(make_pair(EDNSOptionCode::COOKIE
, cookiesOptionStr2
));
502 pw
.addOpt(512, 0, 0, opts
);
509 int res
= locateEDNSOptRR(std::string((char *) response
.data(), response
.size()), &optStart
, &optLen
, &last
);
510 BOOST_CHECK_EQUAL(res
, 0);
511 BOOST_CHECK_EQUAL(last
, true);
513 size_t responseLen
= response
.size();
514 size_t existingOptLen
= optLen
;
515 BOOST_CHECK(existingOptLen
< responseLen
);
516 res
= removeEDNSOptionFromOPT(reinterpret_cast<char *>(response
.data()) + optStart
, &optLen
, EDNSOptionCode::ECS
);
517 BOOST_CHECK_EQUAL(res
, 0);
518 BOOST_CHECK_EQUAL(optLen
, existingOptLen
- (origECSOptionStr
.size() + 4));
519 responseLen
-= (existingOptLen
- optLen
);
521 unsigned int consumed
= 0;
523 DNSName
qname((const char*) response
.data(), responseLen
, sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
524 BOOST_CHECK_EQUAL(qname
, name
);
525 BOOST_CHECK(qtype
== QType::A
);
527 validateResponse((const char *) response
.data(), responseLen
, true, 1);
530 BOOST_AUTO_TEST_CASE(removeECSWhenLastOption
) {
531 DNSName
name("www.powerdns.com.");
532 ComboAddress
origRemote("127.0.0.1");
534 vector
<uint8_t> response
;
535 DNSPacketWriter
pw(response
, name
, QType::A
, QClass::IN
, 0);
536 pw
.getHeader()->qr
= 1;
537 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ANSWER
, true);
538 pw
.xfr32BitInt(0x01020304);
540 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ADDITIONAL
, true);
541 pw
.xfr32BitInt(0x01020304);
544 EDNSCookiesOpt cookiesOpt
;
545 cookiesOpt
.client
= string("deadbeef");
546 cookiesOpt
.server
= string("deadbeef");
547 string cookiesOptionStr
= makeEDNSCookiesOptString(cookiesOpt
);
548 EDNSSubnetOpts ecsOpts
;
549 ecsOpts
.source
= Netmask(origRemote
, ECSSourcePrefixV4
);
550 string origECSOptionStr
= makeEDNSSubnetOptsString(ecsOpts
);
551 DNSPacketWriter::optvect_t opts
;
552 opts
.push_back(make_pair(EDNSOptionCode::COOKIE
, cookiesOptionStr
));
553 opts
.push_back(make_pair(EDNSOptionCode::ECS
, origECSOptionStr
));
554 pw
.addOpt(512, 0, 0, opts
);
561 int res
= locateEDNSOptRR(std::string((char *) response
.data(), response
.size()), &optStart
, &optLen
, &last
);
562 BOOST_CHECK_EQUAL(res
, 0);
563 BOOST_CHECK_EQUAL(last
, true);
565 size_t responseLen
= response
.size();
566 size_t existingOptLen
= optLen
;
567 BOOST_CHECK(existingOptLen
< responseLen
);
568 res
= removeEDNSOptionFromOPT(reinterpret_cast<char *>(response
.data()) + optStart
, &optLen
, EDNSOptionCode::ECS
);
569 BOOST_CHECK_EQUAL(res
, 0);
570 BOOST_CHECK_EQUAL(optLen
, existingOptLen
- (origECSOptionStr
.size() + 4));
571 responseLen
-= (existingOptLen
- optLen
);
573 unsigned int consumed
= 0;
575 DNSName
qname((const char*) response
.data(), responseLen
, sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
576 BOOST_CHECK_EQUAL(qname
, name
);
577 BOOST_CHECK(qtype
== QType::A
);
579 validateResponse((const char *) response
.data(), responseLen
, true, 1);
582 BOOST_AUTO_TEST_CASE(rewritingWithoutECSWhenOnlyOption
) {
583 DNSName
name("www.powerdns.com.");
584 ComboAddress
origRemote("127.0.0.1");
586 vector
<uint8_t> response
;
587 DNSPacketWriter
pw(response
, name
, QType::A
, QClass::IN
, 0);
588 pw
.getHeader()->qr
= 1;
589 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ANSWER
, true);
590 pw
.xfr32BitInt(0x01020304);
592 EDNSSubnetOpts ecsOpts
;
593 ecsOpts
.source
= Netmask(origRemote
, ECSSourcePrefixV4
);
594 string origECSOptionStr
= makeEDNSSubnetOptsString(ecsOpts
);
595 DNSPacketWriter::optvect_t opts
;
596 opts
.push_back(make_pair(EDNSOptionCode::ECS
, origECSOptionStr
));
597 pw
.addOpt(512, 0, 0, opts
);
600 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ADDITIONAL
, true);
601 pw
.xfr32BitInt(0x01020304);
604 vector
<uint8_t> newResponse
;
605 int res
= rewriteResponseWithoutEDNSOption(std::string((const char *) response
.data(), response
.size()), EDNSOptionCode::ECS
, newResponse
);
606 BOOST_CHECK_EQUAL(res
, 0);
608 BOOST_CHECK_EQUAL(newResponse
.size(), response
.size() - (origECSOptionStr
.size() + 4));
610 unsigned int consumed
= 0;
612 DNSName
qname((const char*) newResponse
.data(), newResponse
.size(), sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
613 BOOST_CHECK_EQUAL(qname
, name
);
614 BOOST_CHECK(qtype
== QType::A
);
616 validateResponse((const char *) newResponse
.data(), newResponse
.size(), true, 1);
619 BOOST_AUTO_TEST_CASE(rewritingWithoutECSWhenFirstOption
) {
620 DNSName
name("www.powerdns.com.");
621 ComboAddress
origRemote("127.0.0.1");
623 vector
<uint8_t> response
;
624 DNSPacketWriter
pw(response
, name
, QType::A
, QClass::IN
, 0);
625 pw
.getHeader()->qr
= 1;
626 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ANSWER
, true);
627 pw
.xfr32BitInt(0x01020304);
629 EDNSSubnetOpts ecsOpts
;
630 ecsOpts
.source
= Netmask(origRemote
, ECSSourcePrefixV4
);
631 string origECSOptionStr
= makeEDNSSubnetOptsString(ecsOpts
);
632 EDNSCookiesOpt cookiesOpt
;
633 cookiesOpt
.client
= string("deadbeef");
634 cookiesOpt
.server
= string("deadbeef");
635 string cookiesOptionStr
= makeEDNSCookiesOptString(cookiesOpt
);
636 DNSPacketWriter::optvect_t opts
;
637 opts
.push_back(make_pair(EDNSOptionCode::ECS
, origECSOptionStr
));
638 opts
.push_back(make_pair(EDNSOptionCode::COOKIE
, cookiesOptionStr
));
639 pw
.addOpt(512, 0, 0, opts
);
642 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ADDITIONAL
, true);
643 pw
.xfr32BitInt(0x01020304);
646 vector
<uint8_t> newResponse
;
647 int res
= rewriteResponseWithoutEDNSOption(std::string((const char *) response
.data(), response
.size()), EDNSOptionCode::ECS
, newResponse
);
648 BOOST_CHECK_EQUAL(res
, 0);
650 BOOST_CHECK_EQUAL(newResponse
.size(), response
.size() - (origECSOptionStr
.size() + 4));
652 unsigned int consumed
= 0;
654 DNSName
qname((const char*) newResponse
.data(), newResponse
.size(), sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
655 BOOST_CHECK_EQUAL(qname
, name
);
656 BOOST_CHECK(qtype
== QType::A
);
658 validateResponse((const char *) newResponse
.data(), newResponse
.size(), true, 1);
661 BOOST_AUTO_TEST_CASE(rewritingWithoutECSWhenIntermediaryOption
) {
662 DNSName
name("www.powerdns.com.");
663 ComboAddress
origRemote("127.0.0.1");
665 vector
<uint8_t> response
;
666 DNSPacketWriter
pw(response
, name
, QType::A
, QClass::IN
, 0);
667 pw
.getHeader()->qr
= 1;
668 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ANSWER
, true);
669 pw
.xfr32BitInt(0x01020304);
671 EDNSSubnetOpts ecsOpts
;
672 ecsOpts
.source
= Netmask(origRemote
, ECSSourcePrefixV4
);
673 string origECSOptionStr
= makeEDNSSubnetOptsString(ecsOpts
);
674 EDNSCookiesOpt cookiesOpt
;
675 cookiesOpt
.client
= string("deadbeef");
676 cookiesOpt
.server
= string("deadbeef");
677 string cookiesOptionStr1
= makeEDNSCookiesOptString(cookiesOpt
);
678 string cookiesOptionStr2
= makeEDNSCookiesOptString(cookiesOpt
);
679 DNSPacketWriter::optvect_t opts
;
680 opts
.push_back(make_pair(EDNSOptionCode::COOKIE
, cookiesOptionStr1
));
681 opts
.push_back(make_pair(EDNSOptionCode::ECS
, origECSOptionStr
));
682 opts
.push_back(make_pair(EDNSOptionCode::COOKIE
, cookiesOptionStr2
));
683 pw
.addOpt(512, 0, 0, opts
);
686 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ADDITIONAL
, true);
687 pw
.xfr32BitInt(0x01020304);
690 vector
<uint8_t> newResponse
;
691 int res
= rewriteResponseWithoutEDNSOption(std::string((const char *) response
.data(), response
.size()), EDNSOptionCode::ECS
, newResponse
);
692 BOOST_CHECK_EQUAL(res
, 0);
694 BOOST_CHECK_EQUAL(newResponse
.size(), response
.size() - (origECSOptionStr
.size() + 4));
696 unsigned int consumed
= 0;
698 DNSName
qname((const char*) newResponse
.data(), newResponse
.size(), sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
699 BOOST_CHECK_EQUAL(qname
, name
);
700 BOOST_CHECK(qtype
== QType::A
);
702 validateResponse((const char *) newResponse
.data(), newResponse
.size(), true, 1);
705 BOOST_AUTO_TEST_CASE(rewritingWithoutECSWhenLastOption
) {
706 DNSName
name("www.powerdns.com.");
707 ComboAddress
origRemote("127.0.0.1");
709 vector
<uint8_t> response
;
710 DNSPacketWriter
pw(response
, name
, QType::A
, QClass::IN
, 0);
711 pw
.getHeader()->qr
= 1;
712 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ANSWER
, true);
713 pw
.xfr32BitInt(0x01020304);
715 EDNSSubnetOpts ecsOpts
;
716 ecsOpts
.source
= Netmask(origRemote
, ECSSourcePrefixV4
);
717 string origECSOptionStr
= makeEDNSSubnetOptsString(ecsOpts
);
718 EDNSCookiesOpt cookiesOpt
;
719 cookiesOpt
.client
= string("deadbeef");
720 cookiesOpt
.server
= string("deadbeef");
721 string cookiesOptionStr
= makeEDNSCookiesOptString(cookiesOpt
);
722 DNSPacketWriter::optvect_t opts
;
723 opts
.push_back(make_pair(EDNSOptionCode::COOKIE
, cookiesOptionStr
));
724 opts
.push_back(make_pair(EDNSOptionCode::ECS
, origECSOptionStr
));
725 pw
.addOpt(512, 0, 0, opts
);
728 pw
.startRecord(name
, QType::A
, 3600, QClass::IN
, DNSResourceRecord::ADDITIONAL
, true);
729 pw
.xfr32BitInt(0x01020304);
732 vector
<uint8_t> newResponse
;
733 int res
= rewriteResponseWithoutEDNSOption(std::string((const char *) response
.data(), response
.size()), EDNSOptionCode::ECS
, newResponse
);
734 BOOST_CHECK_EQUAL(res
, 0);
736 BOOST_CHECK_EQUAL(newResponse
.size(), response
.size() - (origECSOptionStr
.size() + 4));
738 unsigned int consumed
= 0;
740 DNSName
qname((const char*) newResponse
.data(), newResponse
.size(), sizeof(dnsheader
), false, &qtype
, NULL
, &consumed
);
741 BOOST_CHECK_EQUAL(qname
, name
);
742 BOOST_CHECK(qtype
== QType::A
);
744 validateResponse((const char *) newResponse
.data(), newResponse
.size(), true, 1);
747 static DNSQuestion
getDNSQuestion(const DNSName
& qname
, const uint16_t qtype
, const uint16_t qclass
, const ComboAddress
& lc
, const ComboAddress
& rem
, const struct timespec
& realTime
, vector
<uint8_t>& query
, size_t len
)
749 dnsheader
* dh
= reinterpret_cast<dnsheader
*>(query
.data());
751 DNSQuestion
dq(&qname
, qtype
, qclass
, qname
.wirelength(), &lc
, &rem
, dh
, query
.size(), len
, false, &realTime
);
755 static DNSQuestion
turnIntoResponse(const DNSName
& qname
, const uint16_t qtype
, const uint16_t qclass
, const ComboAddress
& lc
, const ComboAddress
& rem
, const struct timespec
& queryRealTime
, vector
<uint8_t>& query
, bool resizeBuffer
=true)
757 size_t length
= query
.size();
762 auto dq
= getDNSQuestion(qname
, qtype
, qclass
, lc
, rem
, queryRealTime
, query
, length
);
764 BOOST_CHECK(addEDNSToQueryTurnedResponse(dq
));
769 static int getZ(const DNSName
& qname
, const uint16_t qtype
, const uint16_t qclass
, vector
<uint8_t>& query
)
771 ComboAddress
lc("127.0.0.1");
772 ComboAddress
rem("127.0.0.1");
773 struct timespec queryRealTime
;
774 gettime(&queryRealTime
, true);
775 size_t length
= query
.size();
776 DNSQuestion dq
= getDNSQuestion(qname
, qtype
, qclass
, lc
, rem
, queryRealTime
, query
, length
);
781 BOOST_AUTO_TEST_CASE(test_getEDNSZ
) {
783 DNSName
qname("www.powerdns.com.");
784 uint16_t qtype
= QType::A
;
785 uint16_t qclass
= QClass::IN
;
786 EDNSSubnetOpts ecsOpts
;
787 ecsOpts
.source
= Netmask(ComboAddress("127.0.0.1"), ECSSourcePrefixV4
);
788 string origECSOptionStr
= makeEDNSSubnetOptsString(ecsOpts
);
789 EDNSCookiesOpt cookiesOpt
;
790 cookiesOpt
.client
= string("deadbeef");
791 cookiesOpt
.server
= string("deadbeef");
792 string cookiesOptionStr
= makeEDNSCookiesOptString(cookiesOpt
);
793 DNSPacketWriter::optvect_t opts
;
794 opts
.push_back(make_pair(EDNSOptionCode::COOKIE
, cookiesOptionStr
));
795 opts
.push_back(make_pair(EDNSOptionCode::ECS
, origECSOptionStr
));
799 vector
<uint8_t> query
;
800 DNSPacketWriter
pw(query
, qname
, qtype
, qclass
, 0);
803 BOOST_CHECK_EQUAL(getZ(qname
, qtype
, qclass
, query
), 0);
804 BOOST_CHECK_EQUAL(getEDNSUDPPayloadSize(reinterpret_cast<const char*>(query
.data()), query
.size()), 0);
809 vector
<uint8_t> query
;
810 DNSPacketWriter
pw(query
, qname
, qtype
, qclass
, 0);
811 pw
.addOpt(512, 0, EDNS_HEADER_FLAG_DO
);
814 query
.resize(query
.size() - (/* RDLEN */ sizeof(uint16_t) + /* last byte of TTL / Z */ 1));
815 BOOST_CHECK_EQUAL(getZ(qname
, qtype
, qclass
, query
), 0);
816 BOOST_CHECK_EQUAL(getEDNSUDPPayloadSize(reinterpret_cast<const char*>(query
.data()), query
.size()), 512);
820 /* valid EDNS, no options, DO not set */
821 vector
<uint8_t> query
;
822 DNSPacketWriter
pw(query
, qname
, qtype
, qclass
, 0);
823 pw
.addOpt(512, 0, 0);
826 BOOST_CHECK_EQUAL(getZ(qname
, qtype
, qclass
, query
), 0);
827 BOOST_CHECK_EQUAL(getEDNSUDPPayloadSize(reinterpret_cast<const char*>(query
.data()), query
.size()), 512);
831 /* valid EDNS, no options, DO set */
832 vector
<uint8_t> query
;
833 DNSPacketWriter
pw(query
, qname
, qtype
, qclass
, 0);
834 pw
.addOpt(512, 0, EDNS_HEADER_FLAG_DO
);
837 BOOST_CHECK_EQUAL(getZ(qname
, qtype
, qclass
, query
), EDNS_HEADER_FLAG_DO
);
838 BOOST_CHECK_EQUAL(getEDNSUDPPayloadSize(reinterpret_cast<const char*>(query
.data()), query
.size()), 512);
842 /* valid EDNS, options, DO not set */
843 vector
<uint8_t> query
;
844 DNSPacketWriter
pw(query
, qname
, qtype
, qclass
, 0);
845 pw
.addOpt(512, 0, 0, opts
);
848 BOOST_CHECK_EQUAL(getZ(qname
, qtype
, qclass
, query
), 0);
849 BOOST_CHECK_EQUAL(getEDNSUDPPayloadSize(reinterpret_cast<const char*>(query
.data()), query
.size()), 512);
853 /* valid EDNS, options, DO set */
854 vector
<uint8_t> query
;
855 DNSPacketWriter
pw(query
, qname
, qtype
, qclass
, 0);
856 pw
.addOpt(512, 0, EDNS_HEADER_FLAG_DO
, opts
);
859 BOOST_CHECK_EQUAL(getZ(qname
, qtype
, qclass
, query
), EDNS_HEADER_FLAG_DO
);
860 BOOST_CHECK_EQUAL(getEDNSUDPPayloadSize(reinterpret_cast<const char*>(query
.data()), query
.size()), 512);
865 BOOST_AUTO_TEST_CASE(test_addEDNSToQueryTurnedResponse
) {
867 DNSName
qname("www.powerdns.com.");
868 uint16_t qtype
= QType::A
;
869 uint16_t qclass
= QClass::IN
;
870 EDNSSubnetOpts ecsOpts
;
871 ecsOpts
.source
= Netmask(ComboAddress("127.0.0.1"), ECSSourcePrefixV4
);
872 string origECSOptionStr
= makeEDNSSubnetOptsString(ecsOpts
);
873 EDNSCookiesOpt cookiesOpt
;
874 cookiesOpt
.client
= string("deadbeef");
875 cookiesOpt
.server
= string("deadbeef");
876 string cookiesOptionStr
= makeEDNSCookiesOptString(cookiesOpt
);
877 DNSPacketWriter::optvect_t opts
;
878 opts
.push_back(make_pair(EDNSOptionCode::COOKIE
, cookiesOptionStr
));
879 opts
.push_back(make_pair(EDNSOptionCode::ECS
, origECSOptionStr
));
880 ComboAddress
lc("127.0.0.1");
881 ComboAddress
rem("127.0.0.1");
882 struct timespec queryRealTime
;
883 gettime(&queryRealTime
, true);
887 vector
<uint8_t> query
;
888 DNSPacketWriter
pw(query
, qname
, qtype
, qclass
, 0);
889 pw
.getHeader()->qr
= 1;
890 pw
.getHeader()->rcode
= RCode::NXDomain
;
893 auto dq
= turnIntoResponse(qname
, qtype
, qclass
, lc
, rem
, queryRealTime
, query
);
894 BOOST_CHECK_EQUAL(getEDNSZ(dq
), 0);
895 BOOST_CHECK_EQUAL(getEDNSUDPPayloadSize(reinterpret_cast<const char*>(dq
.dh
), dq
.len
), 0);
900 vector
<uint8_t> query
;
901 DNSPacketWriter
pw(query
, qname
, qtype
, qclass
, 0);
902 pw
.addOpt(512, 0, EDNS_HEADER_FLAG_DO
);
905 query
.resize(query
.size() - (/* RDLEN */ sizeof(uint16_t) + /* last byte of TTL / Z */ 1));
906 auto dq
= turnIntoResponse(qname
, qtype
, qclass
, lc
, rem
, queryRealTime
, query
);
907 BOOST_CHECK_EQUAL(getEDNSZ(dq
), 0);
908 /* 512, because we don't touch a broken OPT record */
909 BOOST_CHECK_EQUAL(getEDNSUDPPayloadSize(reinterpret_cast<const char*>(dq
.dh
), dq
.len
), 512);
913 /* valid EDNS, no options, DO not set */
914 vector
<uint8_t> query
;
915 DNSPacketWriter
pw(query
, qname
, qtype
, qclass
, 0);
916 pw
.addOpt(512, 0, 0);
919 auto dq
= turnIntoResponse(qname
, qtype
, qclass
, lc
, rem
, queryRealTime
, query
);
920 BOOST_CHECK_EQUAL(getEDNSZ(dq
), 0);
921 BOOST_CHECK_EQUAL(getEDNSUDPPayloadSize(reinterpret_cast<const char*>(dq
.dh
), dq
.len
), g_PayloadSizeSelfGenAnswers
);
925 /* valid EDNS, no options, DO set */
926 vector
<uint8_t> query
;
927 DNSPacketWriter
pw(query
, qname
, qtype
, qclass
, 0);
928 pw
.addOpt(512, 0, EDNS_HEADER_FLAG_DO
);
931 auto dq
= turnIntoResponse(qname
, qtype
, qclass
, lc
, rem
, queryRealTime
, query
);
932 BOOST_CHECK_EQUAL(getEDNSZ(dq
), EDNS_HEADER_FLAG_DO
);
933 BOOST_CHECK_EQUAL(getEDNSUDPPayloadSize(reinterpret_cast<const char*>(dq
.dh
), dq
.len
), g_PayloadSizeSelfGenAnswers
);
937 /* valid EDNS, options, DO not set */
938 vector
<uint8_t> query
;
939 DNSPacketWriter
pw(query
, qname
, qtype
, qclass
, 0);
940 pw
.addOpt(512, 0, 0, opts
);
943 auto dq
= turnIntoResponse(qname
, qtype
, qclass
, lc
, rem
, queryRealTime
, query
);
944 BOOST_CHECK_EQUAL(getEDNSZ(dq
), 0);
945 BOOST_CHECK_EQUAL(getEDNSUDPPayloadSize(reinterpret_cast<const char*>(dq
.dh
), dq
.len
), g_PayloadSizeSelfGenAnswers
);
949 /* valid EDNS, options, DO set */
950 vector
<uint8_t> query
;
951 DNSPacketWriter
pw(query
, qname
, qtype
, qclass
, 0);
952 pw
.addOpt(512, 0, EDNS_HEADER_FLAG_DO
, opts
);
955 auto dq
= turnIntoResponse(qname
, qtype
, qclass
, lc
, rem
, queryRealTime
, query
);
956 BOOST_CHECK_EQUAL(getEDNSZ(dq
), EDNS_HEADER_FLAG_DO
);
957 BOOST_CHECK_EQUAL(getEDNSUDPPayloadSize(reinterpret_cast<const char*>(dq
.dh
), dq
.len
), g_PayloadSizeSelfGenAnswers
);
961 BOOST_AUTO_TEST_SUITE_END();