From: Remi Gacogne Date: Fri, 28 Jun 2019 14:47:25 +0000 (+0200) Subject: rec: Export a protobuf incoming response message for timeouts X-Git-Tag: dnsdist-1.4.0-rc1~70^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=57f8413ef42d5c69e3c4b00cedac6f30d141aa78;p=thirdparty%2Fpdns.git rec: Export a protobuf incoming response message for timeouts --- diff --git a/pdns/dnsmessage.proto b/pdns/dnsmessage.proto index a460b51f3c..8a0fe00828 100644 --- a/pdns/dnsmessage.proto +++ b/pdns/dnsmessage.proto @@ -72,7 +72,7 @@ message PBDNSMessage { optional bytes rdata = 5; optional bool udr = 6; // True if this is the first time this RR has been seen for this question } - optional uint32 rcode = 1; + optional uint32 rcode = 1; // DNS Response code, or 65536 for a network error including a timeout repeated DNSRR rrs = 2; optional string appliedPolicy = 3; // Filtering policy (RPZ or Lua) applied repeated string tags = 4; // Additional tags diff --git a/pdns/lwres.cc b/pdns/lwres.cc index a1fb7400aa..87745d15fe 100644 --- a/pdns/lwres.cc +++ b/pdns/lwres.cc @@ -197,7 +197,12 @@ static void logIncomingResponse(const std::shared_ptrsetQueryTime(queryTime.tv_sec, queryTime.tv_usec); - message->setResponseCode(rcode); + if (rcode == -1) { + message->setNetworkErrorResponseCode(); + } + else { + message->setResponseCode(rcode); + } message->addRRs(records, exportTypes); // cerr <d_usec=dt.udiff(); *now=dt.getTimeval(); - if(ret <= 0) // includes 'timeout' + if(ret <= 0) { // includes 'timeout' +#ifdef HAVE_PROTOBUF + if (outgoingLoggers) { + logIncomingResponse(outgoingLoggers, pbMessage, context ? context->d_initialRequestId : boost::none, uuid, ip, domain, type, qid, doTCP, srcmask, 0, -1, {}, queryTime, exportTypes); + } +#endif return ret; + } buf.resize(len); diff --git a/pdns/protobuf.cc b/pdns/protobuf.cc index fd491ac669..7e51225c81 100644 --- a/pdns/protobuf.cc +++ b/pdns/protobuf.cc @@ -62,6 +62,17 @@ void DNSProtoBufMessage::setResponseCode(uint8_t rcode) #endif /* HAVE_PROTOBUF */ } +void DNSProtoBufMessage::setNetworkErrorResponseCode() +{ +#ifdef HAVE_PROTOBUF + PBDNSMessage_DNSResponse* response = d_message.mutable_response(); + if (response) { + /* special code meaning 'network error', like a timeout */ + response->set_rcode(65536); + } +#endif /* HAVE_PROTOBUF */ +} + void DNSProtoBufMessage::setTime(time_t sec, uint32_t usec) { #ifdef HAVE_PROTOBUF diff --git a/pdns/protobuf.hh b/pdns/protobuf.hh index f87dd5f08c..c3277cc83a 100644 --- a/pdns/protobuf.hh +++ b/pdns/protobuf.hh @@ -62,6 +62,7 @@ public: void updateTime(); void setQueryTime(time_t sec, uint32_t usec); void setResponseCode(uint8_t rcode); + void setNetworkErrorResponseCode(); void addRRsFromPacket(const char* packet, const size_t len, bool includeCNAME=false); void serialize(std::string& data) const; void setRequestor(const std::string& requestor); diff --git a/regression-tests.recursor-dnssec/test_Protobuf.py b/regression-tests.recursor-dnssec/test_Protobuf.py index 7d9f36ee24..14497a53c5 100644 --- a/regression-tests.recursor-dnssec/test_Protobuf.py +++ b/regression-tests.recursor-dnssec/test_Protobuf.py @@ -143,7 +143,7 @@ class TestRecursorProtobuf(RecursorTest): self.assertEquals(len(msg.originalRequestorSubnet), 4) self.assertEquals(socket.inet_ntop(socket.AF_INET, msg.originalRequestorSubnet), '127.0.0.1') - def checkOutgoingProtobufBase(self, msg, protocol, query, initiator): + def checkOutgoingProtobufBase(self, msg, protocol, query, initiator, length=None): self.assertTrue(msg) self.assertTrue(msg.HasField('timeSec')) self.assertTrue(msg.HasField('socketFamily')) @@ -155,8 +155,11 @@ class TestRecursorProtobuf(RecursorTest): self.assertTrue(msg.HasField('id')) self.assertNotEquals(msg.id, query.id) self.assertTrue(msg.HasField('inBytes')) - # compare inBytes with length of query/response - self.assertEquals(msg.inBytes, len(query.to_wire())) + if length is not None: + self.assertEquals(msg.inBytes, length) + else: + # compare inBytes with length of query/response + self.assertEquals(msg.inBytes, len(query.to_wire())) def checkProtobufQuery(self, msg, protocol, query, qclass, qtype, qname, initiator='127.0.0.1'): self.assertEquals(msg.type, dnsmessage_pb2.PBDNSMessage.DNSQueryType) @@ -203,9 +206,9 @@ class TestRecursorProtobuf(RecursorTest): for tag in msg.response.tags: self.assertTrue(tag in tags) - def checkProtobufOutgoingQuery(self, msg, protocol, query, qclass, qtype, qname, initiator='127.0.0.1'): + def checkProtobufOutgoingQuery(self, msg, protocol, query, qclass, qtype, qname, initiator='127.0.0.1', length=None): self.assertEquals(msg.type, dnsmessage_pb2.PBDNSMessage.DNSOutgoingQueryType) - self.checkOutgoingProtobufBase(msg, protocol, query, initiator) + self.checkOutgoingProtobufBase(msg, protocol, query, initiator, length=length) self.assertTrue(msg.HasField('to')) self.assertTrue(msg.HasField('question')) self.assertTrue(msg.question.HasField('qClass')) @@ -215,12 +218,17 @@ class TestRecursorProtobuf(RecursorTest): self.assertTrue(msg.question.HasField('qName')) self.assertEquals(msg.question.qName, qname) - def checkProtobufIncomingResponse(self, msg, protocol, response, initiator='127.0.0.1'): + def checkProtobufIncomingResponse(self, msg, protocol, response, initiator='127.0.0.1', length=None): self.assertEquals(msg.type, dnsmessage_pb2.PBDNSMessage.DNSIncomingResponseType) - self.checkOutgoingProtobufBase(msg, protocol, response, initiator) + self.checkOutgoingProtobufBase(msg, protocol, response, initiator, length=length) self.assertTrue(msg.HasField('response')) + self.assertTrue(msg.response.HasField('rcode')) self.assertTrue(msg.response.HasField('queryTimeSec')) + def checkProtobufIncomingNetworkErrorResponse(self, msg, protocol, response, initiator='127.0.0.1'): + self.checkProtobufIncomingResponse(msg, protocol, response, initiator, length=0) + self.assertEquals(msg.response.rcode, 65536) + @classmethod def setUpClass(cls): @@ -350,9 +358,9 @@ auth-zones=example=configs/%s/example.zone""" % _confdir # check the protobuf messages corresponding to the UDP query and answer msg = self.getFirstProtobufMessage() self.checkProtobufOutgoingQuery(msg, dnsmessage_pb2.PBDNSMessage.UDP, query, dns.rdataclass.IN, dns.rdatatype.A, name) -# # then the response -# msg = self.getFirstProtobufMessage() -# self.checkProtobufIncomingResponse(msg, dnsmessage_pb2.PBDNSMessage.UDP, res) + # then the response + msg = self.getFirstProtobufMessage() + self.checkProtobufIncomingNetworkErrorResponse(msg, dnsmessage_pb2.PBDNSMessage.UDP, res) self.checkNoRemainingMessage() class OutgoingProtobufNoQueriesTest(TestRecursorProtobuf): @@ -376,11 +384,9 @@ auth-zones=example=configs/%s/example.zone""" % _confdir query.flags |= dns.flags.RD res = self.sendUDPQuery(query) -# # check the response -# msg = self.getFirstProtobufMessage() -# self.checkProtobufIncomingResponse(msg, dnsmessage_pb2.PBDNSMessage.UDP, res) - # let's wait a bit for a potential message to arrive - time.sleep(2) + # check the response + msg = self.getFirstProtobufMessage() + self.checkProtobufIncomingNetworkErrorResponse(msg, dnsmessage_pb2.PBDNSMessage.UDP, res) self.checkNoRemainingMessage() class ProtobufMasksTest(TestRecursorProtobuf):