diff options
author | Lennart Poettering <lennart@poettering.net> | 2016-01-08 02:38:00 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2016-01-11 19:40:00 +0100 |
commit | 7e1851e3c62147794b4b0104ba776453d8945a39 (patch) | |
tree | f15bda684e78fa4e77146d45377261b670048e1f /src/resolve | |
parent | a1a3f73a57da25dbd158ea71607b7d740b101f49 (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')
-rw-r--r-- | src/resolve/resolved-dns-transaction.c | 39 |
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; } |