summaryrefslogtreecommitdiff
path: root/src/resolve/resolved-dns-transaction.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-01-08 02:38:00 +0100
committerLennart Poettering <lennart@poettering.net>2016-01-11 19:40:00 +0100
commit7e1851e3c62147794b4b0104ba776453d8945a39 (patch)
treef15bda684e78fa4e77146d45377261b670048e1f /src/resolve/resolved-dns-transaction.c
parenta1a3f73a57da25dbd158ea71607b7d740b101f49 (diff)
resolved: properly handle UDP ICMP errors as lost packets
UDP ICMP errors are reported to us via recvmsg() when we read a reply. Handle this properly, and consider this a lost packet, and retry the connection. This also adds some additional logging for invalid incoming packets.
Diffstat (limited to 'src/resolve/resolved-dns-transaction.c')
-rw-r--r--src/resolve/resolved-dns-transaction.c39
1 files changed, 32 insertions, 7 deletions
diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c
index e6e7aeec63..2af9db5566 100644
--- a/src/resolve/resolved-dns-transaction.c
+++ b/src/resolve/resolved-dns-transaction.c
@@ -779,15 +779,40 @@ static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *use
assert(t->scope);
r = manager_recv(t->scope->manager, fd, DNS_PROTOCOL_DNS, &p);
- if (r <= 0)
- return r;
+ if (ERRNO_IS_DISCONNECT(-r)) {
+ usec_t usec;
- if (dns_packet_validate_reply(p) > 0 &&
- DNS_PACKET_ID(p) == t->id)
- dns_transaction_process_reply(t, p);
- else
- log_debug("Invalid DNS UDP packet, ignoring.");
+ /* UDP connection failure get reported via ICMP and then are possible delivered to us on the next
+ * recvmsg(). Treat this like a lost packet. */
+
+ log_debug_errno(r, "Connection failure for DNS UDP packet, treating as lost packet: %m");
+ assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &usec) >= 0);
+ dns_server_packet_lost(t->server, t->current_features, usec - t->start_usec);
+ dns_transaction_retry(t);
+ return 0;
+ }
+ if (r < 0) {
+ dns_transaction_complete(t, DNS_TRANSACTION_RESOURCES);
+ return 0;
+ }
+
+ r = dns_packet_validate_reply(p);
+ if (r < 0) {
+ log_debug_errno(r, "Received invalid DNS packet as response, ignoring: %m");
+ return 0;
+ }
+ if (r == 0) {
+ log_debug("Received inappropriate DNS packet as response, ignoring: %m");
+ return 0;
+ }
+
+ if (DNS_PACKET_ID(p) != t->id) {
+ log_debug("Received packet with incorrect transaction ID, ignoring: %m");
+ return 0;
+ }
+
+ dns_transaction_process_reply(t, p);
return 0;
}