throw std::runtime_error("Unable to parse DNS packet");
}
}
+
+bool changeNameInDNSPacket(PacketBuffer& initialPacket, const DNSName& from, const DNSName& to)
+{
+ if (initialPacket.size() < sizeof(dnsheader)) {
+ return false;
+ }
+
+ PacketReader pr(pdns_string_view(reinterpret_cast<const char*>(initialPacket.data()), initialPacket.size()));
+
+ dnsheader dh;
+ memcpy(&dh, initialPacket.data(), sizeof(dh));
+ size_t idx = 0;
+ DNSName rrname;
+ uint16_t qdcount = ntohs(dh.qdcount);
+ uint16_t ancount = ntohs(dh.ancount);
+ uint16_t nscount = ntohs(dh.nscount);
+ uint16_t arcount = ntohs(dh.arcount);
+ uint16_t rrtype;
+ uint16_t rrclass;
+ string blob;
+
+ size_t recordsCount = ancount + nscount + arcount;
+ struct dnsrecordheader ah;
+
+ rrname = pr.getName();
+ if (rrname == from) {
+ rrname = to;
+ }
+
+ rrtype = pr.get16BitInt();
+ rrclass = pr.get16BitInt();
+
+ PacketBuffer newContent;
+ newContent.reserve(initialPacket.size());
+ GenericDNSPacketWriter<PacketBuffer> pw(newContent, rrname, rrtype, rrclass, dh.opcode);
+ /* we want to copy the flags and ID but not the counts since we recreate the records below */
+ pw.getHeader()->id = dh.id;
+ pw.getHeader()->qr = dh.qr;
+ pw.getHeader()->aa = dh.aa;
+ pw.getHeader()->tc = dh.tc;
+ pw.getHeader()->rd = dh.rd;
+ pw.getHeader()->ra = dh.ra;
+ pw.getHeader()->ad = dh.ad;
+ pw.getHeader()->cd = dh.cd;
+ pw.getHeader()->rcode = dh.rcode;
+
+ /* consume remaining qd if any, but do not copy it */
+ if (qdcount > 1) {
+ for (idx = 1; idx < qdcount; idx++) {
+ rrname = pr.getName();
+ rrtype = pr.get16BitInt();
+ rrclass = pr.get16BitInt();
+ (void)rrtype;
+ (void)rrclass;
+ }
+ }
+
+ const std::unordered_set<QType> nameOnlyTypes{QType::NS, QType::PTR, QType::CNAME, QType::DNAME};
+ const std::unordered_set<QType> noNameTypes{QType::A, QType::AAAA, QType::DHCID, QType::TXT, QType::OPT, QType::HINFO, QType::DNSKEY, QType::CDNSKEY, QType::DS, QType::CDS, QType::DLV, QType::SSHFP, QType::KEY, QType::CERT, QType::TLSA, QType::SMIMEA, QType::OPENPGPKEY, QType::NSEC, QType::NSEC3, QType::CSYNC, QType::NSEC3PARAM, QType::LOC, QType::NID, QType::L32, QType::L64, QType::EUI48, QType::EUI64, QType::URI, QType::CAA};
+
+ /* copy AN, NS and AR */
+ for (idx = 0; idx < recordsCount; idx++) {
+ rrname = pr.getName();
+ if (rrname == from) {
+ rrname = to;
+ }
+ pr.getDnsrecordheader(ah);
+
+ auto place = idx < ancount ? DNSResourceRecord::ANSWER : (idx < (ancount + nscount) ? DNSResourceRecord::AUTHORITY : DNSResourceRecord::ADDITIONAL);
+ pw.startRecord(rrname, ah.d_type, ah.d_ttl, ah.d_class, place, true);
+ if (nameOnlyTypes.count(ah.d_type)) {
+ rrname = pr.getName();
+ pw.xfrName(rrname);
+ }
+ else if (noNameTypes.count(ah.d_type)) {
+ pr.xfrBlob(blob);
+ pw.xfrBlob(blob);
+ }
+ else if (ah.d_type == QType::RRSIG) {
+ /* good luck */
+ pr.xfrBlob(blob);
+ pw.xfrBlob(blob);
+ }
+ else if (ah.d_type == QType::MX) {
+ auto prio = pr.get16BitInt();
+ rrname = pr.getName();
+ pw.xfr16BitInt(prio);
+ pw.xfrName(rrname);
+ }
+ else if (ah.d_type == QType::SOA) {
+ auto mname = pr.getName();
+ pw.xfrName(mname);
+ auto rname = pr.getName();
+ pw.xfrName(rname);
+ /* serial */
+ pw.xfr32BitInt(pr.get32BitInt());
+ /* refresh */
+ pw.xfr32BitInt(pr.get32BitInt());
+ /* retry */
+ pw.xfr32BitInt(pr.get32BitInt());
+ /* expire */
+ pw.xfr32BitInt(pr.get32BitInt());
+ /* minimal */
+ pw.xfr32BitInt(pr.get32BitInt());
+ }
+ else if (ah.d_type == QType::SRV) {
+ /* preference */
+ pw.xfr16BitInt(pr.get16BitInt());
+ /* weight */
+ pw.xfr16BitInt(pr.get16BitInt());
+ /* port */
+ pw.xfr16BitInt(pr.get16BitInt());
+ auto target = pr.getName();
+ pw.xfrName(target);
+ }
+ else {
+ /* sorry, unsafe type */
+ return false;
+ }
+ }
+
+ pw.commit();
+ initialPacket = std::move(newContent);
+
+ return true;
+}
+
}
BOOST_AUTO_TEST_SUITE(test_dnsdist_dnsparser)
+BOOST_AUTO_TEST_CASE(test_Query)
+{
+ const DNSName target("powerdns.com.");
+ const DNSName newTarget("dnsdist.org.");
+ const DNSName notTheTarget("not-powerdns.com.");
+
+ {
+ /* query for the target */
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, target, QType::A, QClass::IN, 0);
+ pw.getHeader()->rd = 1;
+ pw.getHeader()->id = htons(42);
+ pw.commit();
+
+ BOOST_CHECK(dnsdist::changeNameInDNSPacket(query, target, newTarget));
+
+ MOADNSParser mdp(false, reinterpret_cast<const char*>(query.data()), query.size());
+ BOOST_CHECK_EQUAL(mdp.d_qname, newTarget);
+ BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1U);
+ }
+
+ {
+ /* query smaller than a DNS header */
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, target, QType::A, QClass::IN, 0);
+ pw.getHeader()->rd = 1;
+ pw.getHeader()->id = htons(42);
+ pw.commit();
+
+ query.resize(sizeof(dnsheader) - 1);
+ BOOST_CHECK(!dnsdist::changeNameInDNSPacket(query, target, newTarget));
+ }
+
+ {
+ /* query for a different name than the target */
+ PacketBuffer query;
+ GenericDNSPacketWriter<PacketBuffer> pw(query, notTheTarget, QType::A, QClass::IN, 0);
+ pw.getHeader()->rd = 1;
+ pw.getHeader()->id = htons(42);
+ pw.commit();
+
+ BOOST_CHECK(dnsdist::changeNameInDNSPacket(query, target, newTarget));
+
+ MOADNSParser mdp(false, reinterpret_cast<const char*>(query.data()), query.size());
+ BOOST_CHECK_EQUAL(mdp.d_qname, notTheTarget);
+ BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1U);
+ }
+}
+
+BOOST_AUTO_TEST_CASE(test_Response)
+{
+ const DNSName target("powerdns.com.");
+ const DNSName newTarget("dnsdist.org.");
+ const DNSName notTheTarget("not-powerdns.com.");
+
+ {
+ /* response for the target, A and AAAA */
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pwR(response, target, QType::A, QClass::IN, 0);
+ pwR.getHeader()->qr = 1;
+ pwR.getHeader()->rd = 1;
+ pwR.getHeader()->ra = 1;
+ pwR.getHeader()->id = htons(42);
+ pwR.startRecord(target, QType::A, 7200, QClass::IN, DNSResourceRecord::ANSWER);
+ ComboAddress v4("192.0.2.1");
+ pwR.xfrCAWithoutPort(4, v4);
+ pwR.commit();
+ pwR.startRecord(target, QType::AAAA, 7200, QClass::IN, DNSResourceRecord::ADDITIONAL);
+ ComboAddress v6("2001:db8::1");
+ pwR.xfrCAWithoutPort(6, v6);
+ pwR.commit();
+ pwR.addOpt(4096, 0, 0);
+ pwR.commit();
+
+ BOOST_CHECK(dnsdist::changeNameInDNSPacket(response, target, newTarget));
+
+ MOADNSParser mdp(false, reinterpret_cast<const char*>(response.data()), response.size());
+ BOOST_CHECK_EQUAL(mdp.d_qname, newTarget);
+ BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1U);
+ BOOST_CHECK_EQUAL(mdp.d_header.ancount, 1U);
+ BOOST_CHECK_EQUAL(mdp.d_header.nscount, 0U);
+ BOOST_CHECK_EQUAL(mdp.d_header.arcount, 2U);
+
+ BOOST_REQUIRE_EQUAL(mdp.d_answers.size(), 3U);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_type, static_cast<uint16_t>(QType::A));
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_class, QClass::IN);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_name, newTarget);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(1).first.d_type, static_cast<uint16_t>(QType::AAAA));
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(1).first.d_class, QClass::IN);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(1).first.d_name, newTarget);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(2).first.d_type, static_cast<uint16_t>(QType::OPT));
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(2).first.d_name, g_rootdnsname);
+ }
+
+ {
+ /* response with A for the target, AAAA for another name */
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pwR(response, target, QType::A, QClass::IN, 0);
+ pwR.getHeader()->qr = 1;
+ pwR.getHeader()->rd = 1;
+ pwR.getHeader()->ra = 1;
+ pwR.getHeader()->id = htons(42);
+ pwR.startRecord(target, QType::A, 7200, QClass::IN, DNSResourceRecord::ANSWER);
+ ComboAddress v4("192.0.2.1");
+ pwR.xfrCAWithoutPort(4, v4);
+ pwR.commit();
+ pwR.startRecord(notTheTarget, QType::AAAA, 7200, QClass::IN, DNSResourceRecord::ADDITIONAL);
+ ComboAddress v6("2001:db8::1");
+ pwR.xfrCAWithoutPort(6, v6);
+ pwR.commit();
+ pwR.addOpt(4096, 0, 0);
+ pwR.commit();
+
+ BOOST_CHECK(dnsdist::changeNameInDNSPacket(response, target, newTarget));
+
+ MOADNSParser mdp(false, reinterpret_cast<const char*>(response.data()), response.size());
+ BOOST_CHECK_EQUAL(mdp.d_qname, newTarget);
+ BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1U);
+ BOOST_CHECK_EQUAL(mdp.d_header.ancount, 1U);
+ BOOST_CHECK_EQUAL(mdp.d_header.nscount, 0U);
+ BOOST_CHECK_EQUAL(mdp.d_header.arcount, 2U);
+
+ BOOST_REQUIRE_EQUAL(mdp.d_answers.size(), 3U);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_type, static_cast<uint16_t>(QType::A));
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_class, QClass::IN);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_name, newTarget);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(1).first.d_type, static_cast<uint16_t>(QType::AAAA));
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(1).first.d_class, QClass::IN);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(1).first.d_name, notTheTarget);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(2).first.d_type, static_cast<uint16_t>(QType::OPT));
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(2).first.d_name, g_rootdnsname);
+ }
+
+ {
+ /* response with CNAME for the target, A for another name */
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pwR(response, target, QType::A, QClass::IN, 0);
+ pwR.getHeader()->qr = 1;
+ pwR.getHeader()->rd = 1;
+ pwR.getHeader()->ra = 1;
+ pwR.getHeader()->id = htons(42);
+ pwR.startRecord(target, QType::CNAME, 7200, QClass::IN, DNSResourceRecord::ANSWER);
+ pwR.xfrName(notTheTarget);
+ pwR.commit();
+ pwR.startRecord(notTheTarget, QType::A, 7200, QClass::IN, DNSResourceRecord::ANSWER);
+ ComboAddress v4("192.0.2.1");
+ pwR.xfrCAWithoutPort(4, v4);
+ pwR.commit();
+ pwR.addOpt(4096, 0, 0);
+ pwR.commit();
+
+ BOOST_CHECK(dnsdist::changeNameInDNSPacket(response, target, newTarget));
+
+ MOADNSParser mdp(false, reinterpret_cast<const char*>(response.data()), response.size());
+ BOOST_CHECK_EQUAL(mdp.d_qname, newTarget);
+ BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1U);
+ BOOST_CHECK_EQUAL(mdp.d_header.ancount, 2U);
+ BOOST_CHECK_EQUAL(mdp.d_header.nscount, 0U);
+ BOOST_CHECK_EQUAL(mdp.d_header.arcount, 1U);
+
+ BOOST_REQUIRE_EQUAL(mdp.d_answers.size(), 3U);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_type, static_cast<uint16_t>(QType::CNAME));
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_class, QClass::IN);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_name, newTarget);
+ auto content = std::dynamic_pointer_cast<UnknownRecordContent>(mdp.d_answers.at(0).first.d_content);
+ BOOST_REQUIRE(content != nullptr);
+ BOOST_CHECK_EQUAL(content->getRawContent().size(), notTheTarget.getStorage().size());
+
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(1).first.d_type, static_cast<uint16_t>(QType::A));
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(1).first.d_class, QClass::IN);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(1).first.d_name, notTheTarget);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(2).first.d_type, static_cast<uint16_t>(QType::OPT));
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(2).first.d_name, g_rootdnsname);
+ }
+
+ {
+ /* response with a lot of records for the target, all supported */
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pwR(response, target, QType::ANY, QClass::IN, 0);
+ pwR.getHeader()->qr = 1;
+ pwR.getHeader()->rd = 1;
+ pwR.getHeader()->ra = 1;
+ pwR.getHeader()->id = htons(42);
+ pwR.startRecord(target, QType::A, 7200, QClass::IN, DNSResourceRecord::ANSWER);
+ ComboAddress v4("192.0.2.1");
+ pwR.xfrCAWithoutPort(4, v4);
+ pwR.commit();
+ pwR.startRecord(target, QType::AAAA, 7200, QClass::IN, DNSResourceRecord::ANSWER);
+ ComboAddress v6("2001:db8::1");
+ pwR.xfrCAWithoutPort(6, v6);
+ pwR.commit();
+ pwR.startRecord(target, QType::NS, 7200, QClass::IN, DNSResourceRecord::ANSWER);
+ pwR.xfrName(DNSName("pdns-public-ns1.powerdns.com."));
+ pwR.commit();
+ pwR.startRecord(target, QType::MX, 7200, QClass::IN, DNSResourceRecord::ANSWER);
+ pwR.xfr16BitInt(75);
+ pwR.xfrName(DNSName("download1.powerdns.com."));
+ pwR.commit();
+ pwR.startRecord(target, QType::TXT, 7200, QClass::IN, DNSResourceRecord::ANSWER);
+ pwR.xfrText("\"random text\"");
+ pwR.commit();
+ pwR.startRecord(target, QType::RRSIG, 7200, QClass::IN, DNSResourceRecord::ANSWER);
+ pwR.xfrType(QType::TXT);
+ pwR.xfr8BitInt(13);
+ pwR.xfr8BitInt(2);
+ pwR.xfr32BitInt(42);
+ pwR.xfrTime(42);
+ pwR.xfrTime(42);
+ pwR.xfr16BitInt(42);
+ pwR.xfrName(DNSName("powerdns.com."));
+ pwR.xfrBlob(std::string());
+ pwR.commit();
+ pwR.addOpt(4096, 0, 0);
+ pwR.commit();
+
+ BOOST_CHECK(dnsdist::changeNameInDNSPacket(response, target, newTarget));
+
+ MOADNSParser mdp(false, reinterpret_cast<const char*>(response.data()), response.size());
+ BOOST_CHECK_EQUAL(mdp.d_qname, newTarget);
+ BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1U);
+ BOOST_CHECK_EQUAL(mdp.d_header.ancount, 6U);
+ BOOST_CHECK_EQUAL(mdp.d_header.nscount, 0U);
+ BOOST_CHECK_EQUAL(mdp.d_header.arcount, 1U);
+
+ BOOST_REQUIRE_EQUAL(mdp.d_answers.size(), 7U);
+ for (const auto& answer : mdp.d_answers) {
+ if (answer.first.d_type == QType::OPT) {
+ continue;
+ }
+ BOOST_CHECK_EQUAL(answer.first.d_class, QClass::IN);
+ BOOST_CHECK_EQUAL(answer.first.d_name, newTarget);
+ }
+ }
+
+ {
+ /* response with a lot of records for the target, all supported */
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pwR(response, target, QType::ANY, QClass::IN, 0);
+ pwR.getHeader()->qr = 1;
+ pwR.getHeader()->rd = 1;
+ pwR.getHeader()->ra = 1;
+ pwR.getHeader()->id = htons(42);
+ pwR.startRecord(target, QType::A, 7200, QClass::IN, DNSResourceRecord::ANSWER);
+ ComboAddress v4("192.0.2.1");
+ pwR.xfrCAWithoutPort(4, v4);
+ pwR.commit();
+ pwR.startRecord(target, QType::AAAA, 7200, QClass::IN, DNSResourceRecord::ANSWER);
+ ComboAddress v6("2001:db8::1");
+ pwR.xfrCAWithoutPort(6, v6);
+ pwR.commit();
+ pwR.startRecord(target, QType::NS, 7200, QClass::IN, DNSResourceRecord::ANSWER);
+ pwR.xfrName(DNSName("pdns-public-ns1.powerdns.com."));
+ pwR.commit();
+ pwR.startRecord(target, QType::SOA, 7200, QClass::IN, DNSResourceRecord::ANSWER);
+ pwR.xfrName(DNSName("pdns-public-ns1.powerdns.com."));
+ pwR.xfrName(DNSName("admin.powerdns.com."));
+ pwR.xfr32BitInt(1);
+ pwR.xfr32BitInt(2);
+ pwR.xfr32BitInt(3);
+ pwR.xfr32BitInt(4);
+ pwR.xfr32BitInt(5);
+ pwR.commit();
+ pwR.startRecord(target, QType::MX, 7200, QClass::IN, DNSResourceRecord::ANSWER);
+ pwR.xfr16BitInt(75);
+ pwR.xfrName(DNSName("download1.powerdns.com."));
+ pwR.commit();
+ pwR.startRecord(target, QType::TXT, 7200, QClass::IN, DNSResourceRecord::ANSWER);
+ pwR.xfrText("\"random text\"");
+ pwR.commit();
+ pwR.startRecord(target, QType::SRV, 7200, QClass::IN, DNSResourceRecord::ANSWER);
+ pwR.xfr16BitInt(1);
+ pwR.xfr16BitInt(2);
+ pwR.xfr16BitInt(65535);
+ pwR.xfrName(DNSName("target.powerdns.com."));
+ pwR.commit();
+ pwR.addOpt(4096, 0, 0);
+ pwR.commit();
+
+ {
+ // before
+ MOADNSParser mdp(false, reinterpret_cast<const char*>(response.data()), response.size());
+ BOOST_CHECK_EQUAL(mdp.d_qname, target);
+ BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1U);
+ BOOST_CHECK_EQUAL(mdp.d_header.ancount, 7U);
+ BOOST_CHECK_EQUAL(mdp.d_header.nscount, 0U);
+ BOOST_CHECK_EQUAL(mdp.d_header.arcount, 1U);
+
+ BOOST_REQUIRE_EQUAL(mdp.d_answers.size(), 8U);
+ for (const auto& answer : mdp.d_answers) {
+ if (answer.first.d_type == QType::OPT) {
+ continue;
+ }
+ BOOST_CHECK_EQUAL(answer.first.d_class, QClass::IN);
+ BOOST_CHECK_EQUAL(answer.first.d_name, target);
+ }
+ }
+
+ // rebasing
+ BOOST_CHECK(dnsdist::changeNameInDNSPacket(response, target, newTarget));
+
+ {
+ // after
+ MOADNSParser mdp(false, reinterpret_cast<const char*>(response.data()), response.size());
+ BOOST_CHECK_EQUAL(mdp.d_qname, newTarget);
+ BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1U);
+ BOOST_CHECK_EQUAL(mdp.d_header.ancount, 7U);
+ BOOST_CHECK_EQUAL(mdp.d_header.nscount, 0U);
+ BOOST_CHECK_EQUAL(mdp.d_header.arcount, 1U);
+
+ BOOST_REQUIRE_EQUAL(mdp.d_answers.size(), 8U);
+ for (const auto& answer : mdp.d_answers) {
+ if (answer.first.d_type == QType::OPT) {
+ continue;
+ }
+ BOOST_CHECK_EQUAL(answer.first.d_class, QClass::IN);
+ BOOST_CHECK_EQUAL(answer.first.d_name, newTarget);
+ }
+ }
+ }
+
+ {
+ /* response with an ALIAS record, which is not supported */
+ PacketBuffer response;
+ GenericDNSPacketWriter<PacketBuffer> pwR(response, target, QType::A, QClass::IN, 0);
+ pwR.getHeader()->qr = 1;
+ pwR.getHeader()->rd = 1;
+ pwR.getHeader()->ra = 1;
+ pwR.getHeader()->id = htons(42);
+ pwR.startRecord(target, QType::ALIAS, 7200, QClass::IN, DNSResourceRecord::ANSWER);
+ pwR.xfrName(notTheTarget);
+ pwR.commit();
+ pwR.addOpt(4096, 0, 0);
+ pwR.commit();
+
+ BOOST_CHECK(!dnsdist::changeNameInDNSPacket(response, target, newTarget));
+
+ MOADNSParser mdp(false, reinterpret_cast<const char*>(response.data()), response.size());
+ BOOST_CHECK_EQUAL(mdp.d_qname, target);
+ BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1U);
+ BOOST_CHECK_EQUAL(mdp.d_header.ancount, 1U);
+ BOOST_CHECK_EQUAL(mdp.d_header.nscount, 0U);
+ BOOST_CHECK_EQUAL(mdp.d_header.arcount, 1U);
+
+ BOOST_REQUIRE_EQUAL(mdp.d_answers.size(), 2U);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_type, static_cast<uint16_t>(QType::ALIAS));
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_class, QClass::IN);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_name, target);
+ }
+}
+
BOOST_AUTO_TEST_CASE(test_Overlay)
{
const DNSName target("powerdns.com.");