From b6cdebcf5cd504228d3e12422bdf26cbf0474c2b Mon Sep 17 00:00:00 2001 From: Artem Boldariev Date: Fri, 13 Oct 2023 15:31:32 +0300 Subject: [PATCH] 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. --- tests/isc/Makefile.am | 15 +++ tests/isc/netmgr_common.c | 188 ++++++++++++++++++++++++++++++++++++-- tests/isc/netmgr_common.h | 66 +++++++++++++ tests/isc/proxyudp_test.c | 99 ++++++++++++++++++++ 4 files changed, 362 insertions(+), 6 deletions(-) create mode 100644 tests/isc/proxyudp_test.c diff --git a/tests/isc/Makefile.am b/tests/isc/Makefile.am index 5bdf2fb3dc..5cdd915aeb 100644 --- a/tests/isc/Makefile.am +++ b/tests/isc/Makefile.am @@ -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 diff --git a/tests/isc/netmgr_common.c b/tests/isc/netmgr_common.c index fadbb6a036..e5d685f4fe 100644 --- a/tests/isc/netmgr_common.c +++ b/tests/isc/netmgr_common.c @@ -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); +} diff --git a/tests/isc/netmgr_common.h b/tests/isc/netmgr_common.h index 3df02c883b..230e2499d4 100644 --- a/tests/isc/netmgr_common.h +++ b/tests/isc/netmgr_common.h @@ -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); diff --git a/tests/isc/proxyudp_test.c b/tests/isc/proxyudp_test.c new file mode 100644 index 0000000000..cf544fed1e --- /dev/null +++ b/tests/isc/proxyudp_test.c @@ -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 +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include + +/* + * 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 + +#define UNIT_TESTING +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uv_wrap.h" +#define KEEP_BEFORE + +#include "netmgr/socket.c" +#include "netmgr/udp.c" +#include "netmgr_common.h" +#include "uv.c" + +#include + +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