}
}
+// Sets the MTU related flags for IPv6 UDP sockets.
+// It is borrowed from bind-9 lib/isc/unix/socket.c and modified
+// to compile here.
+//
+// The function returns -2 if it fails or the socket file descriptor
+// on success (for convenience, so the result can be just returned).
+int
+mtu(int fd) {
+#ifdef IPV6_USE_MIN_MTU /* RFC 3542, not too common yet*/
+ const int on(1);
+ // use minimum MTU
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_USE_MIN_MTU, &on, sizeof(on)) < 0) {
+ return (-2);
+ }
+#endif
+#ifdef IPV6_MTU
+ // Use minimum MTU on systems that don't have the IPV6_USE_MIN_MTU
+ const int mtu = 1280;
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_MTU, &mtu, sizeof(mtu)) < 0) {
+ return (-2);
+ }
+#endif
+#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT)
+ // Turn off Path MTU discovery on IPv6/UDP sockets.
+ const int action = IPV6_PMTUDISC_DONT;
+ if (setsockopt(fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &action,
+ sizeof(action)) < 0) {
+
+ return (-2);
+ }
+#endif
+ return (fd);
+}
+
} // Anonymous namespace
namespace isc {
if (bind(sock, bind_addr, addr_len) == -1) {
return (-2);
}
+ if (type == SOCK_DGRAM && bind_addr->sa_family == AF_INET6) {
+ // Set some MTU flags on IPv6 UDP sockets.
+ return (mtu(sock));
+ }
return (sock);
}
// The other argument is the socket descriptor number.
// IPv4 check
-void addressFamilySpecificCheck(const sockaddr_in*, const int) {
+void addressFamilySpecificCheck(const sockaddr_in*, const int, const int) {
}
// IPv6 check
-void addressFamilySpecificCheck(const sockaddr_in6*, const int socknum) {
+void addressFamilySpecificCheck(const sockaddr_in6*, const int socknum,
+ const int socket_type)
+{
int options;
socklen_t len = sizeof(options);
- EXPECT_EQ(0, getsockopt(socknum, IPPROTO_IPV6, IPV6_V6ONLY, &options, &len));
+ EXPECT_EQ(0, getsockopt(socknum, IPPROTO_IPV6, IPV6_V6ONLY, &options,
+ &len));
EXPECT_NE(0, options);
+ if (socket_type == SOCK_DGRAM) {
+ // Some more checks for UDP - MTU
+#ifdef IPV6_USE_MIN_MTU /* RFC 3542, not too common yet*/
+ // use minimum MTU
+ EXPECT_EQ(getsockopt(socknum, IPPROTO_IPV6, IPV6_USE_MIN_MTU, &options,
+ &len)) << strerror(errno);
+ EXPECT_NE(0, options);
+#endif
+#ifdef IPV6_MTU
+ // Use minimum MTU on systems that don't have the IPV6_USE_MIN_MTU
+ EXPECT_EQ(0, getsockopt(socknum, IPPROTO_IPV6, IPV6_MTU, &options,
+ &len)) << strerror(errno);
+ EXPECT_EQ(1280, options);
+#endif
+#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT)
+ // Turned off Path MTU discovery on IPv6/UDP sockets?
+ EXPECT_EQ(0, getsockopt(socknum, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
+ &options, &len)) << strerror(errno);
+ EXPECT_EQ(IPV6_PMTUDISC_DONT, options);
+#endif
+ }
}
EXPECT_NE(0, options);
// ...and the address-family specific tests.
- addressFamilySpecificCheck(&addr, socket);
+ addressFamilySpecificCheck(&addr, socket, socket_type);
// Tidy up and exit.
EXPECT_EQ(0, close(socket));