static void validateQuery(const char * packet, size_t packetSize)
{
MOADNSParser mdp(packet, packetSize);
-
+
BOOST_CHECK_EQUAL(mdp.d_qname.toString(), "www.powerdns.com.");
BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1);
BOOST_CHECK_EQUAL(mdp.d_header.arcount, 1);
}
+static void validateResponse(const char * packet, size_t packetSize, bool hasEdns)
+{
+ MOADNSParser mdp(packet, packetSize);
+
+ BOOST_CHECK_EQUAL(mdp.d_qname.toString(), "www.powerdns.com.");
+
+ BOOST_CHECK_EQUAL(mdp.d_header.qr, 1);
+ BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1);
+ BOOST_CHECK_EQUAL(mdp.d_header.ancount, 1);
+ BOOST_CHECK_EQUAL(mdp.d_header.nscount, 0);
+ BOOST_CHECK_EQUAL(mdp.d_header.arcount, hasEdns ? 1 : 0);
+}
+
BOOST_AUTO_TEST_CASE(addECSWithoutEDNS)
{
string largerPacket;
DNSName name("www.powerdns.com.");
vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::OPT, QClass::IN, 0);
+ DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
int len = query.size();
-
+
/* large enough packet */
char packet[1500];
memcpy(packet, query.data(), query.size());
uint16_t qtype;
DNSName qname(packet, len, sizeof(dnsheader), false, &qtype, NULL, &consumed);
BOOST_CHECK_EQUAL(qname, name);
- BOOST_CHECK(qtype == QType::OPT);
-
+ BOOST_CHECK(qtype == QType::A);
+
handleEDNSClientSubnet(packet, sizeof packet, consumed, &len, largerPacket, &ednsAdded, remote);
BOOST_CHECK((size_t) len > query.size());
BOOST_CHECK_EQUAL(largerPacket.size(), 0);
BOOST_CHECK_EQUAL(ednsAdded, true);
validateQuery(packet, len);
-
+
/* not large enought packet */
consumed = 0;
len = query.size();
qname = DNSName((char*) query.data(), len, sizeof(dnsheader), false, &qtype, NULL, &consumed);
BOOST_CHECK_EQUAL(qname, name);
- BOOST_CHECK(qtype == QType::OPT);
-
+ BOOST_CHECK(qtype == QType::A);
+
handleEDNSClientSubnet((char*) query.data(), query.size(), consumed, &len, largerPacket, &ednsAdded, remote);
BOOST_CHECK_EQUAL((size_t) len, query.size());
BOOST_CHECK(largerPacket.size() > query.size());
string largerPacket;
bool ednsAdded = false;
ComboAddress remote;
- DNSName name("www.powerdns.com");
+ DNSName name("www.powerdns.com.");
vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::OPT, QClass::IN, 0);
+ DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
pw.addOpt(512, 0, 0);
pw.commit();
int len = query.size();
-
+
/* large enough packet */
char packet[1500];
memcpy(packet, query.data(), query.size());
uint16_t qtype;
DNSName qname(packet, len, sizeof(dnsheader), false, &qtype, NULL, &consumed);
BOOST_CHECK_EQUAL(qname, name);
- BOOST_CHECK(qtype == QType::OPT);
-
+ BOOST_CHECK(qtype == QType::A);
+
handleEDNSClientSubnet(packet, sizeof packet, consumed, &len, largerPacket, &ednsAdded, remote);
BOOST_CHECK((size_t) len > query.size());
BOOST_CHECK_EQUAL(largerPacket.size(), 0);
BOOST_CHECK_EQUAL(ednsAdded, false);
validateQuery(packet, len);
-
+
/* not large enought packet */
consumed = 0;
len = query.size();
qname = DNSName((char*) query.data(), len, sizeof(dnsheader), false, &qtype, NULL, &consumed);
BOOST_CHECK_EQUAL(qname, name);
- BOOST_CHECK(qtype == QType::OPT);
-
+ BOOST_CHECK(qtype == QType::A);
+
handleEDNSClientSubnet((char*) query.data(), query.size(), consumed, &len, largerPacket, &ednsAdded, remote);
BOOST_CHECK_EQUAL((size_t) len, query.size());
BOOST_CHECK(largerPacket.size() > query.size());
string largerPacket;
bool ednsAdded = false;
ComboAddress remote("192.168.1.25");
- DNSName name("www.powerdns.com");
+ DNSName name("www.powerdns.com.");
ComboAddress origRemote("127.0.0.1");
vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::OPT, QClass::IN, 0);
+ DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
EDNSSubnetOpts ecsOpts;
ecsOpts.source = Netmask(origRemote, g_ECSSourcePrefixV4);
pw.addOpt(512, 0, 0, opts);
pw.commit();
int len = query.size();
-
+
/* large enough packet */
char packet[1500];
memcpy(packet, query.data(), query.size());
uint16_t qtype;
DNSName qname(packet, len, sizeof(dnsheader), false, &qtype, NULL, &consumed);
BOOST_CHECK_EQUAL(qname, name);
- BOOST_CHECK(qtype == QType::OPT);
+ BOOST_CHECK(qtype == QType::A);
g_ECSOverride = true;
handleEDNSClientSubnet(packet, sizeof packet, consumed, &len, largerPacket, &ednsAdded, remote);
string largerPacket;
bool ednsAdded = false;
ComboAddress remote("192.168.1.25");
- DNSName name("www.powerdns.com");
+ DNSName name("www.powerdns.com.");
ComboAddress origRemote("127.0.0.1");
vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::OPT, QClass::IN, 0);
+ DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
EDNSSubnetOpts ecsOpts;
ecsOpts.source = Netmask(origRemote, 32);
pw.addOpt(512, 0, 0, opts);
pw.commit();
int len = query.size();
-
+
/* large enough packet */
char packet[1500];
memcpy(packet, query.data(), query.size());
uint16_t qtype;
DNSName qname(packet, len, sizeof(dnsheader), false, &qtype, NULL, &consumed);
BOOST_CHECK_EQUAL(qname, name);
- BOOST_CHECK(qtype == QType::OPT);
+ BOOST_CHECK(qtype == QType::A);
g_ECSOverride = true;
handleEDNSClientSubnet(packet, sizeof packet, consumed, &len, largerPacket, &ednsAdded, remote);
string largerPacket;
bool ednsAdded = false;
ComboAddress remote("192.168.1.25");
- DNSName name("www.powerdns.com");
+ DNSName name("www.powerdns.com.");
ComboAddress origRemote("127.0.0.1");
vector<uint8_t> query;
- DNSPacketWriter pw(query, name, QType::OPT, QClass::IN, 0);
+ DNSPacketWriter pw(query, name, QType::A, QClass::IN, 0);
pw.getHeader()->rd = 1;
EDNSSubnetOpts ecsOpts;
ecsOpts.source = Netmask(origRemote, 8);
pw.addOpt(512, 0, 0, opts);
pw.commit();
int len = query.size();
-
+
/* large enough packet */
char packet[1500];
memcpy(packet, query.data(), query.size());
uint16_t qtype;
DNSName qname(packet, len, sizeof(dnsheader), false, &qtype, NULL, &consumed);
BOOST_CHECK_EQUAL(qname, name);
- BOOST_CHECK(qtype == QType::OPT);
+ BOOST_CHECK(qtype == QType::A);
g_ECSOverride = true;
handleEDNSClientSubnet(packet, sizeof packet, consumed, &len, largerPacket, &ednsAdded, remote);
len = query.size();
qname = DNSName((char*) query.data(), len, sizeof(dnsheader), false, &qtype, NULL, &consumed);
BOOST_CHECK_EQUAL(qname, name);
- BOOST_CHECK(qtype == QType::OPT);
-
+ BOOST_CHECK(qtype == QType::A);
+
g_ECSOverride = true;
handleEDNSClientSubnet((char*) query.data(), query.size(), consumed, &len, largerPacket, &ednsAdded, remote);
BOOST_CHECK_EQUAL((size_t) len, query.size());
validateQuery(largerPacket.c_str(), largerPacket.size());
}
+BOOST_AUTO_TEST_CASE(removeEDNS) {
+ DNSName name("www.powerdns.com.");
+
+ vector<uint8_t> response;
+ DNSPacketWriter pw(response, name, QType::A, QClass::IN, 0);
+ pw.getHeader()->qr = 1;
+ pw.startRecord(name, QType::A, 3600, QClass::IN, DNSResourceRecord::ANSWER, true);
+ pw.xfr32BitInt(0x01020304);
+ pw.addOpt(512, 0, 0);
+ pw.commit();
+
+ vector<uint8_t> newResponse;
+ int res = rewriteResponseWithoutEDNS((const char *) response.data(), response.size(), newResponse);
+
+ BOOST_CHECK_EQUAL(res, 0);
+
+ unsigned int consumed = 0;
+ uint16_t qtype;
+ DNSName qname((const char*) newResponse.data(), newResponse.size(), sizeof(dnsheader), false, &qtype, NULL, &consumed);
+ BOOST_CHECK_EQUAL(qname, name);
+ BOOST_CHECK(qtype == QType::A);
+ size_t const ednsOptRRSize = sizeof(struct dnsrecordheader) + 1 /* root in OPT RR */;
+ BOOST_CHECK_EQUAL(newResponse.size(), response.size() - ednsOptRRSize);
+
+ validateResponse((const char *) newResponse.data(), newResponse.size(), false);
+}
+
BOOST_AUTO_TEST_SUITE_END();
self.assertEquals(expectedQuery, receivedQuery)
self.assertEquals(expectedResponse, receivedResponse)
- def testWithEDNSECS(self):
+ def testWithEDNSShorterInitialECS(self):
"""
Send a query with EDNS and a crafted ECS value.
Check that the query received by the responder
has an overwritten ECS value (not the initial one)
and that the response received from dnsdist contains
an EDNS pseudo-RR.
+ The initial ECS value is shorter than the one it will
+ replaced with.
"""
name = 'withednsecs.overriden.ecs.tests.powerdns.com.'
- ecso = clientsubnetoption.ClientSubnetOption('1.2.3.4', 24)
+ ecso = clientsubnetoption.ClientSubnetOption('192.0.2.1', 8)
+ rewrittenEcso = clientsubnetoption.ClientSubnetOption('127.0.0.1', 24)
+ query = dns.message.make_query(name, 'A', 'IN', use_edns=True, payload=4096, options=[ecso])
+ expectedQuery = dns.message.make_query(name, 'A', 'IN', use_edns=True, payload=4096, options=[rewrittenEcso])
+ response = dns.message.make_response(query)
+ rrset = dns.rrset.from_text(name,
+ 3600,
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ '127.0.0.1')
+ response.answer.append(rrset)
+
+ (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
+ self.assertTrue(receivedQuery)
+ self.assertTrue(receivedResponse)
+ receivedQuery.id = expectedQuery.id
+ receivedResponse.id = response.id
+ self.assertEquals(expectedQuery, receivedQuery)
+ self.assertEquals(response, receivedResponse)
+
+ (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
+ self.assertTrue(receivedQuery)
+ self.assertTrue(receivedResponse)
+ receivedQuery.id = expectedQuery.id
+ receivedResponse.id = response.id
+ self.assertEquals(expectedQuery, receivedQuery)
+ self.assertEquals(response, receivedResponse)
+
+ def testWithEDNSLongerInitialECS(self):
+ """
+ Send a query with EDNS and a crafted ECS value.
+ Check that the query received by the responder
+ has an overwritten ECS value (not the initial one)
+ and that the response received from dnsdist contains
+ an EDNS pseudo-RR.
+ The initial ECS value is longer than the one it will
+ replaced with.
+ """
+ name = 'withednsecs.overriden.ecs.tests.powerdns.com.'
+ ecso = clientsubnetoption.ClientSubnetOption('192.0.2.1', 32)
+ rewrittenEcso = clientsubnetoption.ClientSubnetOption('127.0.0.1', 24)
+ query = dns.message.make_query(name, 'A', 'IN', use_edns=True, payload=4096, options=[ecso])
+ expectedQuery = dns.message.make_query(name, 'A', 'IN', use_edns=True, payload=4096, options=[rewrittenEcso])
+ response = dns.message.make_response(query)
+ rrset = dns.rrset.from_text(name,
+ 3600,
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ '127.0.0.1')
+ response.answer.append(rrset)
+
+ (receivedQuery, receivedResponse) = self.sendUDPQuery(query, response)
+ self.assertTrue(receivedQuery)
+ self.assertTrue(receivedResponse)
+ receivedQuery.id = expectedQuery.id
+ receivedResponse.id = response.id
+ self.assertEquals(expectedQuery, receivedQuery)
+ self.assertEquals(response, receivedResponse)
+
+ (receivedQuery, receivedResponse) = self.sendTCPQuery(query, response)
+ self.assertTrue(receivedQuery)
+ self.assertTrue(receivedResponse)
+ receivedQuery.id = expectedQuery.id
+ receivedResponse.id = response.id
+ self.assertEquals(expectedQuery, receivedQuery)
+ self.assertEquals(response, receivedResponse)
+
+ def testWithEDNSSameSizeInitialECS(self):
+ """
+ Send a query with EDNS and a crafted ECS value.
+ Check that the query received by the responder
+ has an overwritten ECS value (not the initial one)
+ and that the response received from dnsdist contains
+ an EDNS pseudo-RR.
+ The initial ECS value is exactly the same size as
+ the one it will replaced with.
+ """
+ name = 'withednsecs.overriden.ecs.tests.powerdns.com.'
+ ecso = clientsubnetoption.ClientSubnetOption('192.0.2.1', 24)
rewrittenEcso = clientsubnetoption.ClientSubnetOption('127.0.0.1', 24)
query = dns.message.make_query(name, 'A', 'IN', use_edns=True, payload=4096, options=[ecso])
expectedQuery = dns.message.make_query(name, 'A', 'IN', use_edns=True, payload=4096, options=[rewrittenEcso])