mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 14:07:59 +00:00
Set minimum MTU (1280) on IPv6 sockets
The IPV6_USE_MIN_MTU socket option directs the IP layer to limit the IPv6 packet size to the minimum required supported MTU from the base IPv6 specification, i.e. 1280 bytes. Many implementations of TCP running over IPv6 neglect to check the IPV6_USE_MIN_MTU value when performing MSS negotiation and when constructing a TCP segment despite MSS being defined to be the MTU less the IP and TCP header sizes (60 bytes for IPv6). This leads to oversized IPv6 packets being sent resulting in unintended Path Maximum Transport Unit Discovery (PMTUD) being performed and to fragmented IPv6 packets being sent. Add and use a function to set socket option to limit the MTU on IPv6 sockets to the minimum MTU (1280) both for UDP and TCP.
This commit is contained in:
@@ -1863,6 +1863,12 @@ isc__nm_socket_tcp_nodelay(uv_os_sock_t fd);
|
||||
* Disables Nagle's algorithm on a TCP socket (sets TCP_NODELAY).
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc__nm_socket_min_mtu(uv_os_sock_t fd, sa_family_t sa_family);
|
||||
/*%<
|
||||
* Use minimum MTU on IPv6 sockets
|
||||
*/
|
||||
|
||||
void
|
||||
isc__nm_set_network_buffers(isc_nm_t *nm, uv_handle_t *handle);
|
||||
/*%>
|
||||
|
@@ -3263,6 +3263,27 @@ isc__nm_socket_tcp_nodelay(uv_os_sock_t fd) {
|
||||
#endif
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
isc__nm_socket_min_mtu(uv_os_sock_t fd, sa_family_t sa_family) {
|
||||
if (sa_family != AF_INET6) {
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
#ifdef IPV6_USE_MIN_MTU
|
||||
if (setsockopt_on(fd, IPPROTO_IPV6, IPV6_USE_MIN_MTU) == -1) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
#elif defined(IPV6_MTU)
|
||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_MTU, &(int){ 1280 },
|
||||
sizeof(int)) == -1) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
#else
|
||||
UNUSED(fd);
|
||||
#endif
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
isc__nm_set_network_buffers(isc_nm_t *nm, uv_handle_t *handle) {
|
||||
int32_t recv_buffer_size = 0;
|
||||
|
@@ -342,6 +342,8 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
|
||||
return;
|
||||
}
|
||||
|
||||
(void)isc__nm_socket_min_mtu(sock->fd, sa_family);
|
||||
|
||||
ievent = isc__nm_get_netievent_tcpconnect(mgr, sock, req);
|
||||
|
||||
if (isc__nm_in_netthread()) {
|
||||
@@ -525,7 +527,7 @@ isc__nm_async_tcplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
REQUIRE(sock->parent != NULL);
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
|
||||
/* TODO: set min mss */
|
||||
(void)isc__nm_socket_min_mtu(sock->fd, sa_family);
|
||||
|
||||
r = uv_tcp_init(&worker->loop, &sock->uv_handle.tcp);
|
||||
UV_RUNTIME_CHECK(uv_tcp_init, r);
|
||||
|
@@ -297,6 +297,8 @@ isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
|
||||
return;
|
||||
}
|
||||
|
||||
(void)isc__nm_socket_min_mtu(sock->fd, sa_family);
|
||||
|
||||
/* 2 minute timeout */
|
||||
result = isc__nm_socket_connectiontimeout(sock->fd, 120 * 1000);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
@@ -489,7 +491,7 @@ isc__nm_async_tcpdnslisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
REQUIRE(sock->parent != NULL);
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
|
||||
/* TODO: set min mss */
|
||||
(void)isc__nm_socket_min_mtu(sock->fd, sa_family);
|
||||
|
||||
r = uv_tcp_init(&worker->loop, &sock->uv_handle.tcp);
|
||||
UV_RUNTIME_CHECK(uv_tcp_init, r);
|
||||
|
@@ -351,6 +351,8 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
|
||||
goto failure;
|
||||
}
|
||||
|
||||
(void)isc__nm_socket_min_mtu(sock->fd, sa_family);
|
||||
|
||||
/* 2 minute timeout */
|
||||
result = isc__nm_socket_connectiontimeout(sock->fd, 120 * 1000);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
@@ -560,7 +562,7 @@ isc__nm_async_tlsdnslisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
REQUIRE(sock->parent != NULL);
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
|
||||
/* TODO: set min mss */
|
||||
(void)isc__nm_socket_min_mtu(sock->fd, sa_family);
|
||||
|
||||
r = uv_tcp_init(&worker->loop, &sock->uv_handle.tcp);
|
||||
UV_RUNTIME_CHECK(uv_tcp_init, r);
|
||||
|
@@ -439,6 +439,8 @@ isc__nm_async_udplisten(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
REQUIRE(sock->parent != NULL);
|
||||
REQUIRE(sock->tid == isc_nm_tid());
|
||||
|
||||
(void)isc__nm_socket_min_mtu(sock->fd, sa_family);
|
||||
|
||||
#if HAVE_DECL_UV_UDP_RECVMMSG
|
||||
uv_init_flags |= UV_UDP_RECVMMSG;
|
||||
#endif
|
||||
@@ -1031,6 +1033,8 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
|
||||
|
||||
(void)isc__nm_socket_disable_pmtud(sock->fd, sa_family);
|
||||
|
||||
(void)isc__nm_socket_min_mtu(sock->fd, sa_family);
|
||||
|
||||
event = isc__nm_get_netievent_udpconnect(mgr, sock, req);
|
||||
|
||||
if (isc__nm_in_netthread()) {
|
||||
|
Reference in New Issue
Block a user