From 20a001bdd7a8f52fe96ca56100bdd3b9b16ffba9 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 16 Nov 2020 14:05:52 +0100 Subject: [PATCH] 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. --- src/resolve/resolved-dns-packet.h | 2 +- src/resolve/resolved-dns-scope.c | 5 +++++ src/resolve/resolved-dns-stub.c | 4 ++++ src/resolve/resolved-manager.c | 8 ++++++++ 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h index ee069537c3..f7c350221c 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 6e02e3f8d5..d4b45f9308 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 416a672bda..a18998f1c8 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 a8b17143b9..fc5f8c79d3 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; } } }