It might help prevent Path MTU poisoning attacks.
#endif
}
+ if (!cs->tcp) {
+ if (cs->local.isIPv4()) {
+ try {
+ setSocketIgnorePMTU(cs->udpFD);
+ }
+ 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());
+ }
+ }
+ }
+
const std::string& itf = cs->interface;
if (!itf.empty()) {
#ifdef SO_BINDTODEVICE
return ret;
}
+void setSocketIgnorePMTU(int sockfd)
+{
+#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 */
+ }
+#endif /* IP_PMTUDISC_OMIT */
+
+ /* IP_PMTUDISC_DONT disables Path MTU discovery */
+ SSetsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT);
+}
bool HarvestTimestamp(struct msghdr* msgh, struct timeval* tv)
{
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);
#if defined(IP_PKTINFO)
#define GEN_IP_PKTINFO IP_PKTINFO
if (!setSocketTimestamps(s))
g_log<<Logger::Warning<<"Unable to enable timestamp reporting for socket"<<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;
+ }
+ }
+
#ifdef SO_REUSEPORT
if( d_can_reuseport )
if( setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) )
throw PDNSException("SO_REUSEPORT: "+stringerror());
}
#endif
- socklen_t socklen=sin.getSocklen();
+
+ if (sin.isIPv4()) {
+ try {
+ setSocketIgnorePMTU(fd);
+ }
+ catch(const std::exception& e) {
+ g_log<<Logger::Warning<<"Failed to set IP_MTU_DISCOVER on UDP server socket: "<<e.what()<<endl;
+ }
+ }
+
+ socklen_t socklen=sin.getSocklen();
if (::bind(fd, (struct sockaddr *)&sin, socklen)<0)
throw PDNSException("Resolver binding to server socket on port "+ std::to_string(st.port) +" for "+ st.host+": "+stringerror());