}
}
- /* Only set this on IPv4 UDP sockets.
- Don't set it for DNSCrypt binds. DNSCrypt pads queries for privacy
- purposes, so we do receive large, sometimes fragmented datagrams. */
- if (!tcp && !clientState.dnscryptCtx) {
+ const bool isQUIC = clientState.doqFrontend != nullptr || clientState.doh3Frontend != nullptr;
+ if (isQUIC) {
+ /* disable fragmentation and force PMTU discovery for QUIC-enabled sockets */
+ try {
+ setSocketForcePMTU(socket, addr.sin4.sin_family);
+ }
+ catch (const std::exception& e) {
+ warnlog("Failed to set IP_MTU_DISCOVER on QUIC server socket for local address '%s': %s", addr.toStringWithPort(), e.what());
+ }
+ }
+ else if (!tcp && !clientState.dnscryptCtx) {
+ /* Only set this on IPv4 UDP sockets.
+ Don't set it for DNSCrypt binds. DNSCrypt pads queries for privacy
+ purposes, so we do receive large, sometimes fragmented datagrams. */
try {
setSocketIgnorePMTU(socket, addr.sin4.sin_family);
}
}
}
+void setSocketForcePMTU([[maybe_unused]] int sockfd, [[maybe_unused]] int family)
+{
+ if (family == AF_INET) {
+#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
+ /* IP_PMTUDISC_DO enables Path MTU discovery and prevents fragmentation */
+ SSetsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DO);
+#elif defined(IP_DONTFRAG)
+ /* at least this prevents fragmentation */
+ SSetsockopt(sockfd, IPPROTO_IP, IP_DONTFRAG, 1);
+#endif /* defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) */
+ }
+ else {
+#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
+ /* IPV6_PMTUDISC_DO enables Path MTU discovery and prevents fragmentation */
+ SSetsockopt(sockfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, IPV6_PMTUDISC_DO);
+#elif defined(IPV6_DONTFRAG)
+ /* at least this prevents fragmentation */
+ SSetsockopt(sockfd, IPPROTO_IPV6, IPV6_DONTFRAG, 1);
+#endif /* defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) */
+ }
+}
bool setReusePort(int sockfd)
{
int SListen(int sockfd, int limit);
int SSetsockopt(int sockfd, int level, int opname, int value);
void setSocketIgnorePMTU(int sockfd, int family);
+void setSocketForcePMTU(int sockfd, int family);
bool setReusePort(int sockfd);
#if defined(IP_PKTINFO)