/* 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 (!cs->tcp && cs->local.isIPv4() && !cs->dnscryptCtx) {
+ if (!cs->tcp && !cs->dnscryptCtx) {
try {
- setSocketIgnorePMTU(cs->udpFD);
+ setSocketIgnorePMTU(cs->udpFD, cs->local.sin4.sin_family);
}
catch(const std::exception& e) {
warnlog("Failed to set IP_MTU_DISCOVER on UDP server socket for local address '%s': %s", cs->local.toStringWithPort(), e.what());
return ret;
}
-void setSocketIgnorePMTU(int sockfd)
+void setSocketIgnorePMTU(int sockfd, int family)
{
+ if (family == AF_INET) {
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
#ifdef IP_PMTUDISC_OMIT
/* Linux 3.15+ has IP_PMTUDISC_OMIT, which discards PMTU information to prevent
poisoning, but still allows fragmentation if the packet size exceeds the
outgoing interface MTU, which is good.
*/
- try {
- SSetsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_OMIT);
- return;
- }
- catch(const std::exception& e) {
- /* failed, let's try IP_PMTUDISC_DONT instead */
- }
+ try {
+ SSetsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_OMIT);
+ return;
+ }
+ catch(const std::exception& e) {
+ /* failed, let's try IP_PMTUDISC_DONT instead */
+ }
#endif /* IP_PMTUDISC_OMIT */
/* IP_PMTUDISC_DONT disables Path MTU discovery */
- SSetsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT);
+ SSetsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT);
#endif /* defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) */
+ }
+ else {
+ #if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT)
+#ifdef IPV6_PMTUDISC_OMIT
+ /* Linux 3.15+ has IPV6_PMTUDISC_OMIT, which discards PMTU information to prevent
+ poisoning, but still allows fragmentation if the packet size exceeds the
+ outgoing interface MTU, which is good.
+ */
+ try {
+ SSetsockopt(sockfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, IPV6_PMTUDISC_OMIT);
+ return;
+ }
+ catch(const std::exception& e) {
+ /* failed, let's try IP_PMTUDISC_DONT instead */
+ }
+#endif /* IPV6_PMTUDISC_OMIT */
+
+ /* IPV6_PMTUDISC_DONT disables Path MTU discovery */
+ SSetsockopt(sockfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, IPV6_PMTUDISC_DONT);
+#endif /* defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT) */
+ }
}
+
bool setReusePort(int sockfd)
{
#if defined(SO_REUSEPORT_LB)
int SAccept(int sockfd, ComboAddress& remote);
int SListen(int sockfd, int limit);
int SSetsockopt(int sockfd, int level, int opname, int value);
-void setSocketIgnorePMTU(int sockfd);
+void setSocketIgnorePMTU(int sockfd, int family);
bool setReusePort(int sockfd);
#if defined(IP_PKTINFO)
if (!setSocketTimestamps(s))
g_log<<Logger::Warning<<"Unable to enable timestamp reporting for socket "<<locala.toStringWithPort()<<endl;
- if (locala.isIPv4()) {
- try {
- setSocketIgnorePMTU(s);
- }
- catch(const std::exception& e) {
- g_log<<Logger::Warning<<"Failed to set IP_MTU_DISCOVER on UDP server socket: "<<e.what()<<endl;
- }
+ try {
+ setSocketIgnorePMTU(s, locala.sin4.sin_family);
+ }
+ catch(const std::exception& e) {
+ g_log<<Logger::Warning<<"Failed to set IP_MTU_DISCOVER on UDP server socket: "<<e.what()<<endl;
}
if (d_can_reuseport) {