]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
PROXY over UDP unit tests
authorArtem Boldariev <artem@boldariev.com>
Fri, 13 Oct 2023 12:31:32 +0000 (15:31 +0300)
committerArtem Boldariev <artem@boldariev.com>
Wed, 6 Dec 2023 13:15:25 +0000 (15:15 +0200)
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
tests/isc/netmgr_common.c
tests/isc/netmgr_common.h
tests/isc/proxyudp_test.c [new file with mode: 0644]

index 5bdf2fb3dca38e822916132127ac7c9506e92f36..5cdd915aebc3dd1d1296a25172a7a08caa4b65f5 100644 (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
index fadbb6a03600eaa05dc5dd4a23d03cd8d09e5e84..e5d685f4fe8d163d8983ad41f8e00667ac4dfd89 100644 (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);
+}
index 3df02c883b354b56b6e5f4366986d4d94a7a9258..230e2499d4a4e998678ccffc35a0cae06b8006ad 100644 (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);
diff --git a/tests/isc/proxyudp_test.c b/tests/isc/proxyudp_test.c
new file mode 100644 (file)
index 0000000..cf544fe
--- /dev/null
@@ -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