PROXY over UDP unit tests

This commit adds a unit test suite for the new PROXY over UDP
transport. Most of the code is reused from the UDP unit test suite, as
the new transport aims to be fully compatible with UDP on the API
level.
This commit is contained in:
Artem Boldariev 2023-10-13 15:31:32 +03:00
parent 148cfb17d5
commit b6cdebcf5c
4 changed files with 362 additions and 6 deletions

View file

@ -36,6 +36,7 @@ check_PROGRAMS = \
parse_test \
proxyheader_test \
proxystream_test \
proxyudp_test \
quota_test \
radix_test \
random_test \
@ -125,6 +126,20 @@ proxystream_test_SOURCES = \
netmgr_common.c \
stream_shutdown.c
proxyudp_test_CPPFLAGS = \
$(AM_CPPFLAGS) \
$(OPENSSL_CFLAGS)
proxyudp_test_LDADD = \
$(LDADD) \
$(OPENSSL_LIBS)
proxyudp_test_SOURCES = \
proxyudp_test.c \
netmgr_common.h \
netmgr_common.c \
uv_wrap.h
random_test_LDADD = \
$(LDADD) \
-lm

View file

@ -107,10 +107,11 @@ bool noanswer = false;
bool stream_use_TLS = false;
bool stream_use_PROXY = false;
bool stream_PROXY_over_TLS = false;
bool udp_use_PROXY = false;
bool stream = false;
in_port_t stream_port = 0;
bool udp_use_PROXY = false;
isc_nm_recv_cb_t connect_readcb = NULL;
isc_nm_proxyheader_info_t proxy_info_data;
@ -443,6 +444,11 @@ listen_read_cb(isc_nmhandle_t *handle, isc_result_t eresult,
switch (eresult) {
case ISC_R_SUCCESS:
if (udp_use_PROXY || stream_use_PROXY) {
assert_true(isc_nm_is_proxy_handle(handle));
proxy_verify_endpoints(handle);
}
memmove(&magic, region->base, sizeof(magic));
assert_true(magic == send_magic);
@ -520,6 +526,7 @@ stream_accept_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) {
if (stream_use_PROXY) {
assert_true(isc_nm_is_proxy_handle(handle));
proxy_verify_endpoints(handle);
}
isc_refcount_increment0(&active_sreads);
@ -908,6 +915,25 @@ stream_timeout_recovery_setup(void **state ISC_ATTR_UNUSED) {
return (r);
}
void
proxy_verify_endpoints(isc_nmhandle_t *handle) {
isc_sockaddr_t local, peer;
peer = isc_nmhandle_peeraddr(handle);
local = isc_nmhandle_localaddr(handle);
if (isc_nm_is_proxy_unspec(handle)) {
isc_sockaddr_t real_local, real_peer;
real_peer = isc_nmhandle_real_peeraddr(handle);
real_local = isc_nmhandle_real_localaddr(handle);
assert_true(isc_sockaddr_equal(&peer, &real_peer));
assert_true(isc_sockaddr_equal(&local, &real_local));
} else if (proxy_info == NULL) {
assert_true(isc_sockaddr_equal(&peer, &proxy_src));
assert_true(isc_sockaddr_equal(&local, &proxy_dst));
}
}
int
proxystream_timeout_recovery_setup(void **state) {
stream_use_PROXY = true;
@ -1199,7 +1225,8 @@ setup_udp_test(void **state) {
udp_listen_addr = (isc_sockaddr_t){ .length = 0 };
isc_sockaddr_fromin6(&udp_listen_addr, &in6addr_loopback,
UDP_TEST_PORT);
udp_use_PROXY ? PROXYUDP_TEST_PORT
: UDP_TEST_PORT);
atomic_store(&sreads, 0);
atomic_store(&ssends, 0);
@ -1253,8 +1280,14 @@ teardown_udp_test(void **state) {
static void
udp_connect(isc_nm_cb_t cb, void *cbarg, unsigned int timeout) {
isc_nm_udpconnect(netmgr, &udp_connect_addr, &udp_listen_addr, cb,
cbarg, timeout);
if (udp_use_PROXY) {
isc_nm_proxyudpconnect(netmgr, &udp_connect_addr,
&udp_listen_addr, cb, cbarg, timeout,
NULL);
} else {
isc_nm_udpconnect(netmgr, &udp_connect_addr, &udp_listen_addr,
cb, cbarg, timeout);
}
}
static void
@ -1268,8 +1301,17 @@ udp_listen_read_cb(isc_nmhandle_t *handle, isc_result_t eresult,
static void
udp_start_listening(uint32_t nworkers, isc_nm_recv_cb_t cb) {
isc_result_t result = isc_nm_listenudp(
netmgr, nworkers, &udp_listen_addr, cb, NULL, &listen_sock);
isc_result_t result;
if (udp_use_PROXY) {
result = isc_nm_listenproxyudp(netmgr, nworkers,
&udp_listen_addr, cb, NULL,
&listen_sock);
} else {
result = isc_nm_listenudp(netmgr, nworkers, &udp_listen_addr,
cb, NULL, &listen_sock);
}
assert_int_equal(result, ISC_R_SUCCESS);
isc_loop_teardown(mainloop, stop_listening, listen_sock);
@ -1377,6 +1419,10 @@ udp__connect_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) {
switch (eresult) {
case ISC_R_SUCCESS:
if (udp_use_PROXY) {
assert_true(isc_nm_is_proxy_handle(handle));
}
if (have_expected_cconnects(atomic_fetch_add(&cconnects, 1) +
1))
{
@ -1443,6 +1489,19 @@ udp_noop(void **arg ISC_ATTR_UNUSED) {
udp_connect(connect_success_cb, NULL, UDP_T_CONNECT);
}
int
proxyudp_noop_setup(void **state) {
udp_use_PROXY = true;
return (udp_noop_setup(state));
}
int
proxyudp_noop_teardown(void **state) {
int ret = udp_noop_teardown(state);
udp_use_PROXY = false;
return (ret);
}
static void
udp_noresponse_recv_cb(isc_nmhandle_t *handle, isc_result_t eresult,
isc_region_t *region, void *cbarg) {
@ -1529,6 +1588,19 @@ udp_noresponse(void **arg ISC_ATTR_UNUSED) {
udp_connect(udp_noresponse_connect_cb, listen_sock, UDP_T_SOFT);
}
int
proxyudp_noresponse_setup(void **state) {
udp_use_PROXY = true;
return (udp_noresponse_setup(state));
}
int
proxyudp_noresponse_teardown(void **state) {
int ret = udp_noresponse_teardown(state);
udp_use_PROXY = false;
return (ret);
}
static void
udp_timeout_recovery_ssend_cb(isc_nmhandle_t *handle, isc_result_t eresult,
void *cbarg) {
@ -1667,6 +1739,19 @@ udp_timeout_recovery(void **arg ISC_ATTR_UNUSED) {
udp_connect(udp_timeout_recovery_connect_cb, listen_sock, UDP_T_SOFT);
}
int
proxyudp_timeout_recovery_setup(void **state) {
udp_use_PROXY = true;
return (udp_timeout_recovery_setup(state));
}
int
proxyudp_timeout_recovery_teardown(void **state) {
int ret = udp_timeout_recovery_teardown(state);
udp_use_PROXY = false;
return (ret);
}
static void
udp_shutdown_connect_async_cb(void *arg ISC_ATTR_UNUSED);
@ -1722,6 +1807,19 @@ udp_shutdown_connect(void **arg ISC_ATTR_UNUSED) {
isc_async_current(loopmgr, udp_shutdown_connect_async_cb, netmgr);
}
int
proxyudp_shutdown_connect_setup(void **state) {
udp_use_PROXY = true;
return (udp_shutdown_connect_setup(state));
}
int
proxyudp_shutdown_connect_teardown(void **state) {
int ret = udp_shutdown_connect_teardown(state);
udp_use_PROXY = false;
return (ret);
}
static void
udp_shutdown_read_recv_cb(isc_nmhandle_t *handle, isc_result_t eresult,
isc_region_t *region, void *cbarg) {
@ -1824,6 +1922,19 @@ udp_shutdown_read(void **arg ISC_ATTR_UNUSED) {
udp_connect(udp_shutdown_read_connect_cb, NULL, UDP_T_SOFT);
}
int
proxyudp_shutdown_read_setup(void **state) {
udp_use_PROXY = true;
return (udp_shutdown_read_setup(state));
}
int
proxyudp_shutdown_read_teardown(void **state) {
int ret = udp_shutdown_read_teardown(state);
udp_use_PROXY = false;
return (ret);
}
static void
udp_cancel_read_recv_cb(isc_nmhandle_t *handle, isc_result_t eresult,
isc_region_t *region, void *cbarg) {
@ -1941,6 +2052,19 @@ udp_cancel_read(void **arg ISC_ATTR_UNUSED) {
udp_connect(udp_cancel_read_connect_cb, NULL, UDP_T_SOFT);
}
int
proxyudp_cancel_read_setup(void **state) {
udp_use_PROXY = true;
return (udp_cancel_read_setup(state));
}
int
proxyudp_cancel_read_teardown(void **state) {
int ret = udp_cancel_read_teardown(state);
udp_use_PROXY = false;
return (ret);
}
int
udp_recv_one_setup(void **state) {
setup_udp_test(state);
@ -1985,6 +2109,19 @@ udp_recv_one(void **arg ISC_ATTR_UNUSED) {
udp_enqueue_connect(NULL);
}
int
proxyudp_recv_one_setup(void **state) {
udp_use_PROXY = true;
return (udp_recv_one_setup(state));
}
int
proxyudp_recv_one_teardown(void **state) {
int ret = udp_recv_one_teardown(state);
udp_use_PROXY = false;
return (ret);
}
int
udp_recv_two_setup(void **state) {
setup_udp_test(state);
@ -2029,6 +2166,19 @@ udp_recv_two(void **arg ISC_ATTR_UNUSED) {
udp_enqueue_connect(NULL);
}
int
proxyudp_recv_two_setup(void **state) {
udp_use_PROXY = true;
return (udp_recv_two_setup(state));
}
int
proxyudp_recv_two_teardown(void **state) {
int ret = udp_recv_two_teardown(state);
udp_use_PROXY = false;
return (ret);
}
int
udp_recv_send_setup(void **state) {
setup_udp_test(state);
@ -2065,6 +2215,19 @@ udp_recv_send(void **arg ISC_ATTR_UNUSED) {
}
}
int
proxyudp_recv_send_setup(void **state) {
udp_use_PROXY = true;
return (udp_recv_send_setup(state));
}
int
proxyudp_recv_send_teardown(void **state) {
int ret = udp_recv_send_teardown(state);
udp_use_PROXY = false;
return (ret);
}
static void
udp_double_read_send_cb(isc_nmhandle_t *handle, isc_result_t eresult,
void *cbarg) {
@ -2235,3 +2398,16 @@ udp_double_read(void **arg ISC_ATTR_UNUSED) {
udp_enqueue_connect(NULL);
}
int
proxyudp_double_read_setup(void **state) {
udp_use_PROXY = true;
return (udp_double_read_setup(state));
}
int
proxyudp_double_read_teardown(void **state) {
int ret = udp_double_read_teardown(state);
udp_use_PROXY = false;
return (ret);
}

View file

@ -29,6 +29,7 @@
#define TCPDNS_TEST_PORT 9156
#define TLSDNS_TEST_PORT 9157
#define PROXYSTREAM_TEST_PORT 9158
#define PROXYUDP_TEST_PORT 9159
typedef void (*stream_connect_function)(isc_nm_t *nm);
typedef void (*connect_func)(isc_nm_t *);
@ -138,6 +139,8 @@ extern bool stream_PROXY_over_TLS;
extern bool stream;
extern in_port_t stream_port;
extern bool udp_use_PROXY;
extern isc_nm_recv_cb_t connect_readcb;
#define NSENDS 100
@ -295,6 +298,9 @@ get_proxyheader_info(void);
isc_nm_proxy_type_t
get_proxy_type(void);
void
proxy_verify_endpoints(isc_nmhandle_t *handle);
int
stream_noop_setup(void **state ISC_ATTR_UNUSED);
void
@ -463,6 +469,12 @@ udp_noop_teardown(void **state);
void
udp_noop(void **arg ISC_ATTR_UNUSED);
int
proxyudp_noop_setup(void **state);
int
proxyudp_noop_teardown(void **state);
int
udp_noresponse_setup(void **state);
@ -472,6 +484,12 @@ udp_noresponse_teardown(void **state);
void
udp_noresponse(void **arg ISC_ATTR_UNUSED);
int
proxyudp_noresponse_setup(void **state);
int
proxyudp_noresponse_teardown(void **state);
int
udp_timeout_recovery_setup(void **state);
@ -481,6 +499,12 @@ udp_timeout_recovery_teardown(void **state);
void
udp_timeout_recovery(void **arg ISC_ATTR_UNUSED);
int
proxyudp_timeout_recovery_setup(void **state);
int
proxyudp_timeout_recovery_teardown(void **state);
int
udp_shutdown_connect_setup(void **state);
@ -490,6 +514,12 @@ udp_shutdown_connect_teardown(void **state);
void
udp_shutdown_connect(void **arg ISC_ATTR_UNUSED);
int
proxyudp_shutdown_connect_setup(void **state);
int
proxyudp_shutdown_connect_teardown(void **state);
int
udp_shutdown_read_setup(void **state);
@ -499,6 +529,12 @@ udp_shutdown_read_teardown(void **state);
void
udp_shutdown_read(void **arg ISC_ATTR_UNUSED);
int
proxyudp_shutdown_read_setup(void **state);
int
proxyudp_shutdown_read_teardown(void **state);
int
udp_cancel_read_setup(void **state);
@ -508,6 +544,12 @@ udp_cancel_read_teardown(void **state);
void
udp_cancel_read(void **arg ISC_ATTR_UNUSED);
int
proxyudp_cancel_read_setup(void **state);
int
proxyudp_cancel_read_teardown(void **state);
int
udp_recv_one_setup(void **state);
@ -517,6 +559,12 @@ udp_recv_one_teardown(void **state);
void
udp_recv_one(void **arg ISC_ATTR_UNUSED);
int
proxyudp_recv_one_setup(void **state);
int
proxyudp_recv_one_teardown(void **state);
int
udp_recv_two_setup(void **state);
@ -526,6 +574,12 @@ udp_recv_two_teardown(void **state);
void
udp_recv_two(void **arg ISC_ATTR_UNUSED);
int
proxyudp_recv_two_setup(void **state);
int
proxyudp_recv_two_teardown(void **state);
int
udp_recv_send_setup(void **state);
@ -535,6 +589,12 @@ udp_recv_send_teardown(void **state);
void
udp_recv_send(void **arg ISC_ATTR_UNUSED);
int
proxyudp_recv_send_setup(void **state);
int
proxyudp_recv_send_teardown(void **state);
int
udp_double_read_setup(void **state);
@ -543,3 +603,9 @@ udp_double_read_teardown(void **state);
void
udp_double_read(void **arg ISC_ATTR_UNUSED);
int
proxyudp_double_read_setup(void **state);
int
proxyudp_double_read_teardown(void **state);

99
tests/isc/proxyudp_test.c Normal file
View file

@ -0,0 +1,99 @@
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#include <inttypes.h>
#include <sched.h> /* IWYU pragma: keep */
#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
/*
* As a workaround, include an OpenSSL header file before including cmocka.h,
* because OpenSSL 3.1.0 uses __attribute__(malloc), conflicting with a
* redefined malloc in cmocka.h.
*/
#include <openssl/err.h>
#define UNIT_TESTING
#include <cmocka.h>
#include <isc/async.h>
#include <isc/job.h>
#include <isc/nonce.h>
#include <isc/os.h>
#include <isc/quota.h>
#include <isc/refcount.h>
#include <isc/sockaddr.h>
#include <isc/thread.h>
#include <isc/util.h>
#include "uv_wrap.h"
#define KEEP_BEFORE
#include "netmgr/socket.c"
#include "netmgr/udp.c"
#include "netmgr_common.h"
#include "uv.c"
#include <tests/isc.h>
ISC_LOOP_TEST_IMPL(proxyudp_noop) { udp_noop(arg); }
ISC_LOOP_TEST_IMPL(proxyudp_noresponse) { udp_noresponse(arg); }
ISC_LOOP_TEST_IMPL(proxyudp_timeout_recovery) { udp_timeout_recovery(arg); }
ISC_LOOP_TEST_IMPL(proxyudp_shutdown_connect) { udp_shutdown_connect(arg); }
ISC_LOOP_TEST_IMPL(proxyudp_shutdown_read) { udp_shutdown_read(arg); }
ISC_LOOP_TEST_IMPL(proxyudp_cancel_read) { udp_cancel_read(arg); }
ISC_LOOP_TEST_IMPL(proxyudp_recv_one) { udp_recv_one(arg); }
ISC_LOOP_TEST_IMPL(proxyudp_recv_two) { udp_recv_two(arg); }
ISC_LOOP_TEST_IMPL(proxyudp_recv_send) { udp_recv_send(arg); }
ISC_LOOP_TEST_IMPL(proxyudp_double_read) { udp_double_read(arg); }
ISC_TEST_LIST_START
ISC_TEST_ENTRY_CUSTOM(proxyudp_noop, proxyudp_noop_setup,
proxyudp_noop_teardown)
ISC_TEST_ENTRY_CUSTOM(proxyudp_noresponse, proxyudp_noresponse_setup,
proxyudp_noresponse_teardown)
ISC_TEST_ENTRY_CUSTOM(proxyudp_timeout_recovery,
proxyudp_timeout_recovery_setup,
proxyudp_timeout_recovery_teardown)
ISC_TEST_ENTRY_CUSTOM(proxyudp_shutdown_read, proxyudp_shutdown_read_setup,
proxyudp_shutdown_read_teardown)
ISC_TEST_ENTRY_CUSTOM(proxyudp_cancel_read, proxyudp_cancel_read_setup,
proxyudp_cancel_read_teardown)
ISC_TEST_ENTRY_CUSTOM(proxyudp_shutdown_connect,
proxyudp_shutdown_connect_setup,
proxyudp_shutdown_connect_teardown)
ISC_TEST_ENTRY_CUSTOM(proxyudp_double_read, proxyudp_double_read_setup,
proxyudp_double_read_teardown)
ISC_TEST_ENTRY_CUSTOM(proxyudp_recv_one, proxyudp_recv_one_setup,
proxyudp_recv_one_teardown)
ISC_TEST_ENTRY_CUSTOM(proxyudp_recv_two, proxyudp_recv_two_setup,
proxyudp_recv_two_teardown)
ISC_TEST_ENTRY_CUSTOM(proxyudp_recv_send, proxyudp_recv_send_setup,
proxyudp_recv_send_teardown)
ISC_TEST_LIST_END
ISC_TEST_MAIN