]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: collect incoming fragment size when receiving UDP datagrams
authorLennart Poettering <lennart@poettering.net>
Mon, 16 Nov 2020 13:05:52 +0000 (14:05 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 18 Feb 2021 14:42:18 +0000 (15:42 +0100)
We can later use this to adapt our announced EDNS buffer size in order
to avoid fragmentation to make the best of large datagrams while still
avoiding he security weaknesses of it.

src/resolve/resolved-dns-packet.h
src/resolve/resolved-dns-scope.c
src/resolve/resolved-dns-stub.c
src/resolve/resolved-manager.c

index ee069537c3ba7eee6d2a9810e16f4831f5122823..f7c350221c43fa1ad0195ec1413655d05ac2c3fa 100644 (file)
@@ -55,7 +55,7 @@ struct DnsPacketHeader {
 struct DnsPacket {
         unsigned n_ref;
         DnsProtocol protocol;
-        size_t size, allocated, rindex, max_size;
+        size_t size, allocated, rindex, max_size, fragsize;
         void *_data; /* don't access directly, use DNS_PACKET_DATA()! */
         Hashmap *names; /* For name compression */
         size_t opt_start, opt_size;
index 6e02e3f8d505821d46b459df876e3000ce40cc97..d4b45f93082896e9276c86b9de7a49303ab579f2 100644 (file)
@@ -415,6 +415,11 @@ static int dns_scope_socket(
                 r = socket_disable_pmtud(fd, sa.sa.sa_family);
                 if (r < 0)
                         log_debug_errno(r, "Failed to disable UDP PMTUD, ignoring: %m");
+
+                /* Learn about fragmentation taking place */
+                r = socket_set_recvfragsize(fd, sa.sa.sa_family, true);
+                if (r < 0)
+                        log_debug_errno(r, "Failed to enable fragment size reception, ignoring: %m");
         }
 
         if (ret_socket_address)
index 416a672bda5d3200b20c0a1a754ee01ba12a1283..a18998f1c868f44666c61d354369600f6666a2d9 100644 (file)
@@ -1121,6 +1121,10 @@ static int manager_dns_stub_fd_extra(Manager *m, DnsStubListenerExtra *l, int ty
                 r = socket_disable_pmtud(fd, l->family);
                 if (r < 0)
                         log_debug_errno(r, "Failed to disable UDP PMTUD, ignoring: %m");
+
+                r = socket_set_recvfragsize(fd, l->family, true);
+                if (r < 0)
+                        log_debug_errno(r, "Failed to enable fragment size reception, ignoring: %m");
         }
 
         if (bind(fd, &sa.sa, SOCKADDR_LEN(sa)) < 0) {
index a8b17143b9f61b417b8285b167e06cfc6cdb25f5..fc5f8c79d39db9fb1202f6d2f11ddb6c74c821f3 100644 (file)
@@ -19,6 +19,7 @@
 #include "idn-util.h"
 #include "io-util.h"
 #include "missing_network.h"
+#include "missing_socket.h"
 #include "netlink-util.h"
 #include "ordered-set.h"
 #include "parse-util.h"
@@ -881,6 +882,9 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
                                 p->ttl = *(int *) CMSG_DATA(cmsg);
                                 break;
 
+                        case IPV6_RECVFRAGSIZE:
+                                p->fragsize = *(int *) CMSG_DATA(cmsg);
+                                break;
                         }
                 } else if (cmsg->cmsg_level == IPPROTO_IP) {
                         assert(p->family == AF_INET);
@@ -900,6 +904,10 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
                         case IP_TTL:
                                 p->ttl = *(int *) CMSG_DATA(cmsg);
                                 break;
+
+                        case IP_RECVFRAGSIZE:
+                                p->fragsize = *(int *) CMSG_DATA(cmsg);
+                                break;
                         }
                 }
         }