Make sure the unit test listening and connecting ports are different
In rare circumstances, the UDP port for the listening socket and the UDP port for the connecting socket might be the same. Because we use the "reuse" port socket option, this isn't caught when binding the socket, and thus the connected client socket could send a datagram to itself, completely bypassing the server. This doesn't happen under normal operation mode because `named` is listening on a privileged port (53), and even if not, it doesn't usually talk to itself as the tests do. Pick an arbitrary port for listening (9153-9156) that is outside the ephemeral port range for the network manager related unit tests (except the `doh_test).
This commit is contained in:
@@ -95,69 +95,20 @@ bool allow_send_back = false;
|
||||
bool noanswer = false;
|
||||
bool stream_use_TLS = false;
|
||||
bool stream = false;
|
||||
in_port_t stream_port = 0;
|
||||
|
||||
isc_nm_recv_cb_t connect_readcb = NULL;
|
||||
|
||||
int
|
||||
setup_ephemeral_port(isc_sockaddr_t *addr, sa_family_t family) {
|
||||
socklen_t addrlen = sizeof(*addr);
|
||||
uv_os_sock_t fd = -1;
|
||||
int r;
|
||||
|
||||
isc_sockaddr_fromin6(addr, &in6addr_loopback, 0);
|
||||
|
||||
fd = socket(AF_INET6, family, 0);
|
||||
if (fd < 0) {
|
||||
perror("setup_ephemeral_port: socket()");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
r = bind(fd, (const struct sockaddr *)&addr->type.sa,
|
||||
sizeof(addr->type.sin6));
|
||||
if (r != 0) {
|
||||
perror("setup_ephemeral_port: bind()");
|
||||
isc__nm_closesocket(fd);
|
||||
return (r);
|
||||
}
|
||||
|
||||
r = getsockname(fd, (struct sockaddr *)&addr->type.sa, &addrlen);
|
||||
if (r != 0) {
|
||||
perror("setup_ephemeral_port: getsockname()");
|
||||
isc__nm_closesocket(fd);
|
||||
return (r);
|
||||
}
|
||||
|
||||
#if IPV6_RECVERR
|
||||
#define setsockopt_on(socket, level, name) \
|
||||
setsockopt(socket, level, name, &(int){ 1 }, sizeof(int))
|
||||
|
||||
r = setsockopt_on(fd, IPPROTO_IPV6, IPV6_RECVERR);
|
||||
if (r != 0) {
|
||||
perror("setup_ephemeral_port");
|
||||
isc__nm_closesocket(fd);
|
||||
return (r);
|
||||
}
|
||||
#endif
|
||||
|
||||
return (fd);
|
||||
}
|
||||
|
||||
int
|
||||
setup_netmgr_test(void **state) {
|
||||
char *env_workers = getenv("ISC_TASK_WORKERS");
|
||||
uv_os_sock_t tcp_listen_sock = -1;
|
||||
size_t nworkers;
|
||||
|
||||
tcp_connect_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0);
|
||||
|
||||
tcp_listen_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
tcp_listen_sock = setup_ephemeral_port(&tcp_listen_addr, SOCK_STREAM);
|
||||
if (tcp_listen_sock < 0) {
|
||||
return (-1);
|
||||
}
|
||||
isc__nm_closesocket(tcp_listen_sock);
|
||||
tcp_listen_sock = -1;
|
||||
isc_sockaddr_fromin6(&tcp_listen_addr, &in6addr_loopback, stream_port);
|
||||
|
||||
if (env_workers != NULL) {
|
||||
workers = atoi(env_workers);
|
||||
|
||||
@@ -18,6 +18,16 @@
|
||||
|
||||
#include "netmgr/netmgr-int.h"
|
||||
|
||||
/*
|
||||
* Pick unused port outside the ephemeral port range, so we don't clash with
|
||||
* connected sockets.
|
||||
*/
|
||||
#define UDP_TEST_PORT 9153
|
||||
#define TCP_TEST_PORT 9154
|
||||
#define TLS_TEST_PORT 9155
|
||||
#define TCPDNS_TEST_PORT 9156
|
||||
#define TLSDNS_TEST_PORT 9157
|
||||
|
||||
typedef void (*stream_connect_function)(isc_nm_t *nm);
|
||||
typedef void (*connect_func)(isc_nm_t *);
|
||||
|
||||
@@ -119,6 +129,7 @@ extern bool allow_send_back;
|
||||
extern bool noanswer;
|
||||
extern bool stream_use_TLS;
|
||||
extern bool stream;
|
||||
extern in_port_t stream_port;
|
||||
|
||||
extern isc_nm_recv_cb_t connect_readcb;
|
||||
|
||||
@@ -213,9 +224,6 @@ extern isc_nm_recv_cb_t connect_readcb;
|
||||
#define atomic_assert_int_ge(val, exp) assert_true(atomic_load(&val) >= exp)
|
||||
#define atomic_assert_int_gt(val, exp) assert_true(atomic_load(&val) > exp)
|
||||
|
||||
int
|
||||
setup_ephemeral_port(isc_sockaddr_t *addr, sa_family_t family);
|
||||
|
||||
int
|
||||
setup_netmgr_test(void **state);
|
||||
int
|
||||
|
||||
@@ -132,6 +132,7 @@ ISC_TEST_LIST_END
|
||||
|
||||
static int
|
||||
tcp_setup(void **state __attribute__((__unused__))) {
|
||||
stream_port = TCP_TEST_PORT;
|
||||
stream_use_TLS = false;
|
||||
stream = true;
|
||||
|
||||
|
||||
@@ -142,4 +142,12 @@ ISC_TEST_ENTRY_CUSTOM(tcpdns_recv_send, stream_recv_send_setup,
|
||||
stream_recv_send_teardown)
|
||||
|
||||
ISC_TEST_LIST_END
|
||||
ISC_TEST_MAIN
|
||||
|
||||
static int
|
||||
tcpdns_setup(void **state __attribute__((__unused__))) {
|
||||
stream_port = TCPDNS_TEST_PORT;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
ISC_TEST_MAIN_CUSTOM(tcpdns_setup, NULL)
|
||||
|
||||
@@ -131,6 +131,7 @@ ISC_TEST_LIST_END
|
||||
|
||||
static int
|
||||
tls_setup(void **state __attribute__((__unused__))) {
|
||||
stream_port = TLS_TEST_PORT;
|
||||
stream_use_TLS = true;
|
||||
stream = true;
|
||||
|
||||
|
||||
@@ -147,4 +147,12 @@ ISC_TEST_ENTRY_CUSTOM(tlsdns_recv_send, stream_recv_send_setup,
|
||||
/* FIXME: Re-add the noalpn tests */
|
||||
|
||||
ISC_TEST_LIST_END
|
||||
ISC_TEST_MAIN
|
||||
|
||||
static int
|
||||
tlsdns_setup(void **state __attribute__((__unused__))) {
|
||||
stream_port = TCPDNS_TEST_PORT;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
ISC_TEST_MAIN_CUSTOM(tlsdns_setup, NULL)
|
||||
|
||||
@@ -56,8 +56,6 @@ static isc_sockaddr_t udp_connect_addr;
|
||||
|
||||
static int
|
||||
setup_test(void **state) {
|
||||
uv_os_sock_t udp_listen_sock = -1;
|
||||
|
||||
setup_loopmgr(state);
|
||||
setup_netmgr(state);
|
||||
|
||||
@@ -65,11 +63,8 @@ setup_test(void **state) {
|
||||
isc_sockaddr_fromin6(&udp_connect_addr, &in6addr_loopback, 0);
|
||||
|
||||
udp_listen_addr = (isc_sockaddr_t){ .length = 0 };
|
||||
udp_listen_sock = setup_ephemeral_port(&udp_listen_addr, SOCK_DGRAM);
|
||||
if (udp_listen_sock < 0) {
|
||||
return (-1);
|
||||
}
|
||||
isc__nm_closesocket(udp_listen_sock);
|
||||
isc_sockaddr_fromin6(&udp_listen_addr, &in6addr_loopback,
|
||||
UDP_TEST_PORT);
|
||||
|
||||
atomic_store(&sreads, 0);
|
||||
atomic_store(&ssends, 0);
|
||||
|
||||
Reference in New Issue
Block a user