]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: properly handle UDP ICMP errors as lost packets
authorLennart Poettering <lennart@poettering.net>
Fri, 8 Jan 2016 01:38:00 +0000 (02:38 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 11 Jan 2016 18:40:00 +0000 (19:40 +0100)
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.

src/resolve/resolved-dns-transaction.c

index e6e7aeec63513af93951967da694cd80cc5af448..2af9db5566e918ac17b76d5cf388d154b74289f4 100644 (file)
@@ -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;
 }