From: Remi Gacogne Date: Thu, 12 Jan 2023 15:21:59 +0000 (+0100) Subject: dnsdist: Add the ability to change the qname and owner names in DNS packets X-Git-Tag: dnsdist-1.8.0-rc1~67^2~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7c092c7303e5ad4bc434649338165fc84af190f5;p=thirdparty%2Fpdns.git dnsdist: Add the ability to change the qname and owner names in DNS packets --- diff --git a/pdns/dnsdistdist/dnsdist-dnsparser.cc b/pdns/dnsdistdist/dnsdist-dnsparser.cc index 00800b3f7c..fce410c00e 100644 --- a/pdns/dnsdistdist/dnsdist-dnsparser.cc +++ b/pdns/dnsdistdist/dnsdist-dnsparser.cc @@ -63,4 +63,131 @@ DNSPacketOverlay::DNSPacketOverlay(const std::string_view& packet) 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(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 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 nameOnlyTypes{QType::NS, QType::PTR, QType::CNAME, QType::DNAME}; + const std::unordered_set 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; +} + } diff --git a/pdns/dnsdistdist/dnsdist-dnsparser.hh b/pdns/dnsdistdist/dnsdist-dnsparser.hh index e6a4c009de..91de7acf78 100644 --- a/pdns/dnsdistdist/dnsdist-dnsparser.hh +++ b/pdns/dnsdistdist/dnsdist-dnsparser.hh @@ -47,4 +47,11 @@ public: uint16_t d_qclass; dnsheader d_header; }; + +/* Rewrite, if they are exactly equal to 'from', the qname and owner name of any record + * to 'to'. Since that might break DNS name pointers, the whole payload is rewritten, + * and the operation may fail if there is at least one unsupported record in the payload, + * because it could contain pointers that would not be rewritten. + */ +bool changeNameInDNSPacket(PacketBuffer& initialPacket, const DNSName& from, const DNSName& to); } diff --git a/pdns/dnsdistdist/test-dnsdist-dnsparser.cc b/pdns/dnsdistdist/test-dnsdist-dnsparser.cc index 6bca068f67..ed7ec5a999 100644 --- a/pdns/dnsdistdist/test-dnsdist-dnsparser.cc +++ b/pdns/dnsdistdist/test-dnsdist-dnsparser.cc @@ -30,6 +30,356 @@ 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 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(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 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 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(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 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(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(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(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(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 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(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(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(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(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 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(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(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(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(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(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 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(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 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(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(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 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(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(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.");