mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-02 07:35:26 +00:00
Don't enable SO_REUSEADDR on outgoing UDP sockets
Currently, the outgoing UDP sockets have enabled SO_REUSEADDR (SO_REUSEPORT on BSDs) which allows multiple UDP sockets to bind to the same address+port. There's one caveat though - only a single (the last one) socket is going to receive all the incoming traffic. This in turn could lead to incoming DNS message matching to invalid dns_dispatch and getting dropped. Disable setting the SO_REUSEADDR on the outgoing UDP sockets. This needs to be done explicitly because `uv_udp_open()` silently enables the option on the socket.
This commit is contained in:
@@ -1321,7 +1321,7 @@ isc__nm_closesocket(uv_os_sock_t sock);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
isc__nm_socket_reuse(uv_os_sock_t fd);
|
isc__nm_socket_reuse(uv_os_sock_t fd, int val);
|
||||||
/*%<
|
/*%<
|
||||||
* Set the SO_REUSEADDR or SO_REUSEPORT (or equivalent) socket option on the fd
|
* Set the SO_REUSEADDR or SO_REUSEPORT (or equivalent) socket option on the fd
|
||||||
*/
|
*/
|
||||||
|
@@ -159,7 +159,7 @@ isc__nm_closesocket(uv_os_sock_t sock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
isc__nm_socket_reuse(uv_os_sock_t fd) {
|
isc__nm_socket_reuse(uv_os_sock_t fd, int val) {
|
||||||
/*
|
/*
|
||||||
* Generally, the SO_REUSEADDR socket option allows reuse of
|
* Generally, the SO_REUSEADDR socket option allows reuse of
|
||||||
* local addresses.
|
* local addresses.
|
||||||
@@ -173,12 +173,12 @@ isc__nm_socket_reuse(uv_os_sock_t fd) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(SO_REUSEPORT) && !defined(__linux__)
|
#if defined(SO_REUSEPORT) && !defined(__linux__)
|
||||||
if (setsockopt_on(fd, SOL_SOCKET, SO_REUSEPORT) == -1) {
|
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)) == -1) {
|
||||||
return (ISC_R_FAILURE);
|
return (ISC_R_FAILURE);
|
||||||
}
|
}
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
#elif defined(SO_REUSEADDR)
|
#elif defined(SO_REUSEADDR)
|
||||||
if (setsockopt_on(fd, SOL_SOCKET, SO_REUSEADDR) == -1) {
|
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) == -1) {
|
||||||
return (ISC_R_FAILURE);
|
return (ISC_R_FAILURE);
|
||||||
}
|
}
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
|
@@ -289,7 +289,7 @@ isc__nm_tcp_lb_socket(isc_nm_t *mgr, sa_family_t sa_family) {
|
|||||||
|
|
||||||
/* FIXME: set mss */
|
/* FIXME: set mss */
|
||||||
|
|
||||||
result = isc__nm_socket_reuse(sock);
|
result = isc__nm_socket_reuse(sock, 1);
|
||||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
|
||||||
if (mgr->load_balance_sockets) {
|
if (mgr->load_balance_sockets) {
|
||||||
|
@@ -78,7 +78,7 @@ isc__nm_udp_lb_socket(isc_nm_t *mgr, sa_family_t sa_family) {
|
|||||||
(void)isc__nm_socket_disable_pmtud(sock, sa_family);
|
(void)isc__nm_socket_disable_pmtud(sock, sa_family);
|
||||||
(void)isc__nm_socket_v6only(sock, sa_family);
|
(void)isc__nm_socket_v6only(sock, sa_family);
|
||||||
|
|
||||||
result = isc__nm_socket_reuse(sock);
|
result = isc__nm_socket_reuse(sock, 1);
|
||||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
|
||||||
if (mgr->load_balance_sockets) {
|
if (mgr->load_balance_sockets) {
|
||||||
@@ -752,9 +752,10 @@ fail:
|
|||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
udp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
|
udp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
|
||||||
int uv_bind_flags = UV_UDP_REUSEADDR;
|
int uv_bind_flags = 0;
|
||||||
int r;
|
int r;
|
||||||
isc__networker_t *worker = sock->worker;
|
isc__networker_t *worker = sock->worker;
|
||||||
|
isc_result_t result;
|
||||||
|
|
||||||
r = uv_udp_init(&worker->loop->loop, &sock->uv_handle.udp);
|
r = uv_udp_init(&worker->loop->loop, &sock->uv_handle.udp);
|
||||||
UV_RUNTIME_CHECK(uv_udp_init, r);
|
UV_RUNTIME_CHECK(uv_udp_init, r);
|
||||||
@@ -771,6 +772,12 @@ udp_connect_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req) {
|
|||||||
}
|
}
|
||||||
isc__nm_incstats(sock, STATID_OPEN);
|
isc__nm_incstats(sock, STATID_OPEN);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* uv_udp_open() enables REUSE_ADDR, we need to disable it again.
|
||||||
|
*/
|
||||||
|
result = isc__nm_socket_reuse(sock->fd, 0);
|
||||||
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
|
||||||
if (sock->iface.type.sa.sa_family == AF_INET6) {
|
if (sock->iface.type.sa.sa_family == AF_INET6) {
|
||||||
uv_bind_flags |= UV_UDP_IPV6ONLY;
|
uv_bind_flags |= UV_UDP_IPV6ONLY;
|
||||||
}
|
}
|
||||||
@@ -846,9 +853,6 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
|
|||||||
sock->client = true;
|
sock->client = true;
|
||||||
|
|
||||||
sock->fd = fd;
|
sock->fd = fd;
|
||||||
result = isc__nm_socket_reuse(sock->fd);
|
|
||||||
RUNTIME_CHECK(result == ISC_R_SUCCESS ||
|
|
||||||
result == ISC_R_NOTIMPLEMENTED);
|
|
||||||
|
|
||||||
(void)isc__nm_socket_disable_pmtud(sock->fd, sa_family);
|
(void)isc__nm_socket_disable_pmtud(sock->fd, sa_family);
|
||||||
|
|
||||||
|
@@ -247,7 +247,7 @@ setup_ephemeral_port(isc_sockaddr_t *addr, sa_family_t family) {
|
|||||||
return (r);
|
return (r);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = isc__nm_socket_reuse(fd);
|
result = isc__nm_socket_reuse(fd, 1);
|
||||||
if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
|
if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"setup_ephemeral_port: isc__nm_socket_reuse(): %s",
|
"setup_ephemeral_port: isc__nm_socket_reuse(): %s",
|
||||||
|
Reference in New Issue
Block a user