From: Lennart Poettering Date: Mon, 16 Nov 2020 13:05:52 +0000 (+0100) Subject: resolved: collect incoming fragment size when receiving UDP datagrams X-Git-Tag: v248-rc1~59^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=20a001bdd7a8f52fe96ca56100bdd3b9b16ffba9;p=thirdparty%2Fsystemd.git resolved: collect incoming fragment size when receiving UDP datagrams 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. --- diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h index ee069537c3b..f7c350221c4 100644 --- a/src/resolve/resolved-dns-packet.h +++ b/src/resolve/resolved-dns-packet.h @@ -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; diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 6e02e3f8d50..d4b45f93082 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -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) diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index 416a672bda5..a18998f1c86 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -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) { diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index a8b17143b9f..fc5f8c79d39 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -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; } } }