if (g_domainConfigs.find(mdp.d_qname) == g_domainConfigs.end()) {
info_msg.push_back("Domain name '" + mdp.d_qname.toLogString() + "' is not configured for distribution");
}
-
- const auto zoneInfo = getCurrentZoneInfo(mdp.d_qname);
- if (zoneInfo == nullptr) {
- info_msg.push_back("Domain has not been transferred yet");
+ else {
+ const auto zoneInfo = getCurrentZoneInfo(mdp.d_qname);
+ if (zoneInfo == nullptr) {
+ info_msg.push_back("Domain has not been transferred yet");
+ }
}
}
if (!info_msg.empty()) {
- g_log<<Logger::Warning<<logPrefix<<"Ignoring "<<mdp.d_qname<<"|"<<QType(mdp.d_qtype).getName()<<" query from "<<saddr.toStringWithPort();
+ g_log<<Logger::Warning<<logPrefix<<"Refusing "<<mdp.d_qname<<"|"<<QType(mdp.d_qtype).getName()<<" query from "<<saddr.toStringWithPort();
g_log<<Logger::Warning<<": ";
bool first = true;
for (const auto& s : info_msg) {
}
/*
- * Returns a vector<uint8_t> that represents the full response to a SOA
+ * Returns a vector<uint8_t> that represents the full positive response to a SOA
* query. QNAME is read from mdp.
*/
static bool makeSOAPacket(const MOADNSParser& mdp, vector<uint8_t>& packet) {
return true;
}
+/*
+ * Returns a vector<uint8_t> that represents the full REFUSED response to a
+ * query. QNAME and type are read from mdp.
+ */
+static bool makeRefusedPacket(const MOADNSParser& mdp, vector<uint8_t>& packet) {
+ DNSPacketWriter pw(packet, mdp.d_qname, mdp.d_qtype);
+ pw.getHeader()->id = mdp.d_header.id;
+ pw.getHeader()->rd = mdp.d_header.rd;
+ pw.getHeader()->qr = 1;
+ pw.getHeader()->rcode = RCode::Refused;
+
+ return true;
+}
+
static vector<uint8_t> getSOAPacket(const MOADNSParser& mdp, const shared_ptr<SOARecordContent>& soa) {
vector<uint8_t> packet;
DNSPacketWriter pw(packet, mdp.d_qname, mdp.d_qtype);
}
MOADNSParser mdp(true, string(buf, res));
- if (!checkQuery(mdp, saddr)) {
- return;
+ vector<uint8_t> packet;
+ if (checkQuery(mdp, saddr)) {
+ /* RFC 1995 Section 2
+ * Transport of a query may be by either UDP or TCP. If an IXFR query
+ * is via UDP, the IXFR server may attempt to reply using UDP if the
+ * entire response can be contained in a single DNS packet. If the UDP
+ * reply does not fit, the query is responded to with a single SOA
+ * record of the server's current version to inform the client that a
+ * TCP query should be initiated.
+ *
+ * Let's not complicate this with IXFR over UDP (and looking if we need to truncate etc).
+ * Just send the current SOA and let the client try over TCP
+ */
+ makeSOAPacket(mdp, packet);
+ } else {
+ makeRefusedPacket(mdp, packet);
}
- /* RFC 1995 Section 2
- * Transport of a query may be by either UDP or TCP. If an IXFR query
- * is via UDP, the IXFR server may attempt to reply using UDP if the
- * entire response can be contained in a single DNS packet. If the UDP
- * reply does not fit, the query is responded to with a single SOA
- * record of the server's current version to inform the client that a
- * TCP query should be initiated.
- *
- * Let's not complicate this with IXFR over UDP (and looking if we need to truncate etc).
- * Just send the current SOA and let the client try over TCP
- */
- vector<uint8_t> packet;
- makeSOAPacket(mdp, packet);
if(sendto(fd, &packet[0], packet.size(), 0, (struct sockaddr*) &saddr, fromlen) < 0) {
auto savedErrno = errno;
g_log<<Logger::Warning<<"Could not send reply for "<<mdp.d_qname<<"|"<<QType(mdp.d_qtype).getName()<<" to "<<saddr.toStringWithPort()<<": "<<strerror(savedErrno)<<endl;
global xfrServerPort
_xfrDone = 0
- _config_domains = { 'example': '127.0.0.1:' + str(xfrServerPort) }
+ _config_domains = { 'example': '127.0.0.1:' + str(xfrServerPort),
+ 'example2': '127.0.0.1:1' } # bogus port is intentional
@classmethod
def setUpClass(cls):
# answers[1].sort(key=lambda rrset: (rrset.name, rrset.rdtype))
self.assertEqual(answers, expected)
- def testXFR(self):
+ def test_a_XFR(self):
self.waitUntilCorrectSerialIsLoaded(1)
self.checkFullZone(1)
self.waitUntilCorrectSerialIsLoaded(2)
self.checkFullZone(2)
- self.checkIXFR(1,2)
\ No newline at end of file
+ self.checkIXFR(1,2)
+
+ # _b_ because we expect post-XFR testing state
+ def test_b_UDP_SOA_existing(self):
+ query = dns.message.make_query('example.', 'SOA')
+ expected = dns.message.make_response(query)
+ expected.answer.append(xfrServer._getSOAForSerial(2))
+
+ response = self.sendUDPQuery(query)
+ self.assertEquals(expected, response)
+
+ def test_b_UDP_SOA_not_loaded(self):
+ query = dns.message.make_query('example2.', 'SOA')
+ expected = dns.message.make_response(query)
+ expected.set_rcode(dns.rcode.REFUSED)
+
+ response = self.sendUDPQuery(query)
+ self.assertEquals(expected, response)
+
+ def test_b_UDP_SOA_not_configured(self):
+ query = dns.message.make_query('example3.', 'SOA')
+ expected = dns.message.make_response(query)
+ expected.set_rcode(dns.rcode.REFUSED)
+
+ response = self.sendUDPQuery(query)
+ self.assertEquals(expected, response)