2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 05:57:52 +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:
Ondřej Surý 2021-10-05 22:30:55 +02:00 committed by Ondřej Surý
parent b40d1e8467
commit 5d34a14f22
6 changed files with 40 additions and 3 deletions

View File

@ -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);
/*%>

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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()) {