summaryrefslogtreecommitdiff
path: root/test/regression/bsd_test/netx_bsd_socket_options_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/regression/bsd_test/netx_bsd_socket_options_test.c')
-rw-r--r--test/regression/bsd_test/netx_bsd_socket_options_test.c335
1 files changed, 335 insertions, 0 deletions
diff --git a/test/regression/bsd_test/netx_bsd_socket_options_test.c b/test/regression/bsd_test/netx_bsd_socket_options_test.c
new file mode 100644
index 00000000..bdc8f177
--- /dev/null
+++ b/test/regression/bsd_test/netx_bsd_socket_options_test.c
@@ -0,0 +1,335 @@
+/***************************************************************************
+ * Copyright (C) 2026 Eclipse ThreadX contributors
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the MIT License which is available at
+ * https://opensource.org/licenses/MIT.
+ *
+ * AI Disclosure: This file was largely AI-generated by Copilot (Sonnet 4.6).
+ * The AI-generated portions may be considered public domain (CC0-1.0)
+ * and not subject to the project's licence. The human contributor has
+ * reviewed and verified that the code is correct.
+ *
+ * SPDX-License-Identifier: MIT and CC0-1.0
+ **************************************************************************/
+
+/* This test exercises setsockopt/getsockopt for SO_LINGER, IP_TOS, IP_TTL,
+ SO_BROADCAST and TCP_NODELAY, including error-path coverage introduced
+ by the PR #374 bug-fixes. */
+
+#include "tx_api.h"
+#include "nx_api.h"
+#if defined(NX_BSD_ENABLE) && !defined(NX_DISABLE_IPV4) && defined(__PRODUCT_NETXDUO__)
+#include "nxd_bsd.h"
+
+#define DEMO_STACK_SIZE 4096
+#define BSD_THREAD_PRIORITY 2
+
+static TX_THREAD ntest_0;
+static NX_PACKET_POOL pool_0;
+static NX_IP ip_0;
+static ULONG bsd_thread_area[DEMO_STACK_SIZE / sizeof(ULONG)];
+static ULONG error_counter;
+
+static ULONG packet_pool_area[(256 + sizeof(NX_PACKET)) * 16 / 4];
+
+static void ntest_0_entry(ULONG thread_input);
+extern void test_control_return(UINT status);
+extern void _nx_ram_network_driver_256(struct NX_IP_DRIVER_STRUCT *driver_req);
+
+#ifdef CTEST
+VOID test_application_define(void *first_unused_memory)
+#else
+void netx_bsd_socket_options_test_application_define(void *first_unused_memory)
+#endif
+{
+CHAR *pointer = (CHAR *)first_unused_memory;
+UINT status;
+
+ error_counter = 0;
+
+ tx_thread_create(&ntest_0, "thread 0", ntest_0_entry, 0,
+ pointer, DEMO_STACK_SIZE, 3, 3,
+ TX_NO_TIME_SLICE, TX_AUTO_START);
+ pointer += DEMO_STACK_SIZE;
+
+ nx_system_initialize();
+
+ status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 256,
+ packet_pool_area, sizeof(packet_pool_area));
+ if (status)
+ error_counter++;
+
+ status = nx_ip_create(&ip_0, "NetX IP Instance 0",
+ IP_ADDRESS(1, 2, 3, 4), 0xFFFFFF00UL,
+ &pool_0, _nx_ram_network_driver_256,
+ pointer, 2048, 1);
+ pointer += 2048;
+ if (status)
+ error_counter++;
+
+ status = nx_arp_enable(&ip_0, (void *)pointer, 1024);
+ pointer += 1024;
+ if (status)
+ error_counter++;
+
+ status = nx_tcp_enable(&ip_0);
+ if (status)
+ error_counter++;
+
+ status = nx_udp_enable(&ip_0);
+ if (status)
+ error_counter++;
+
+ status = bsd_initialize(&ip_0, &pool_0, (CHAR *)&bsd_thread_area[0],
+ sizeof(bsd_thread_area), BSD_THREAD_PRIORITY);
+ if (status)
+ error_counter++;
+}
+
+static void ntest_0_entry(ULONG thread_input)
+{
+int tcp_sock;
+int udp_sock;
+struct nx_bsd_linger ling_set;
+struct nx_bsd_linger ling_get;
+INT opt_val;
+INT opt_len;
+INT ret;
+
+ NX_PARAMETER_NOT_USED(thread_input);
+
+ /* Create sockets. */
+ tcp_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (tcp_sock < 0)
+ error_counter++;
+
+ udp_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (udp_sock < 0)
+ error_counter++;
+
+ /* ================================================================
+ * SO_LINGER: round-trip on TCP socket
+ * ================================================================ */
+ ling_set.l_onoff = 1;
+ ling_set.l_linger = 5;
+ ret = setsockopt(tcp_sock, SOL_SOCKET, SO_LINGER,
+ &ling_set, (INT)sizeof(ling_set));
+ if (ret != 0)
+ error_counter++;
+
+ opt_len = (INT)sizeof(ling_get);
+ ret = getsockopt(tcp_sock, SOL_SOCKET, SO_LINGER,
+ &ling_get, &opt_len);
+ if (ret != 0)
+ error_counter++;
+ if (ling_get.l_onoff != 1)
+ error_counter++;
+ if (ling_get.l_linger != 5)
+ error_counter++;
+ if (opt_len != (INT)sizeof(struct nx_bsd_linger))
+ error_counter++;
+
+ /* Disable linger and verify l_onoff is cleared. */
+ ling_set.l_onoff = 0;
+ ling_set.l_linger = 0;
+ ret = setsockopt(tcp_sock, SOL_SOCKET, SO_LINGER,
+ &ling_set, (INT)sizeof(ling_set));
+ if (ret != 0)
+ error_counter++;
+
+ opt_len = (INT)sizeof(ling_get);
+ ret = getsockopt(tcp_sock, SOL_SOCKET, SO_LINGER,
+ &ling_get, &opt_len);
+ if (ret != 0)
+ error_counter++;
+ if (ling_get.l_onoff != 0)
+ error_counter++;
+
+ /* Negative l_linger must be rejected with EINVAL. */
+ ling_set.l_onoff = 1;
+ ling_set.l_linger = -1;
+ ret = setsockopt(tcp_sock, SOL_SOCKET, SO_LINGER,
+ &ling_set, (INT)sizeof(ling_set));
+ if (ret == 0)
+ error_counter++;
+
+ /* Short output buffer must be rejected with EINVAL. */
+ opt_len = 1;
+ ret = getsockopt(tcp_sock, SOL_SOCKET, SO_LINGER,
+ &ling_get, &opt_len);
+ if (ret == 0)
+ error_counter++;
+
+ /* SO_LINGER on a UDP socket must fail with ENOPROTOOPT. */
+ ling_set.l_onoff = 1;
+ ling_set.l_linger = 1;
+ ret = setsockopt(udp_sock, SOL_SOCKET, SO_LINGER,
+ &ling_set, (INT)sizeof(ling_set));
+ if (ret == 0)
+ error_counter++;
+
+ /* ================================================================
+ * IP_TOS: round-trip on TCP socket
+ * ================================================================ */
+ opt_val = 0x10;
+ opt_len = (INT)sizeof(INT);
+ ret = setsockopt(tcp_sock, IPPROTO_IP, IP_TOS, &opt_val, opt_len);
+ if (ret != 0)
+ error_counter++;
+
+ opt_val = 0;
+ opt_len = (INT)sizeof(INT);
+ ret = getsockopt(tcp_sock, IPPROTO_IP, IP_TOS, &opt_val, &opt_len);
+ if (ret != 0)
+ error_counter++;
+ if (opt_val != 0x10)
+ error_counter++;
+ if (opt_len != (INT)sizeof(INT))
+ error_counter++;
+
+ /* IP_TOS round-trip on UDP socket. */
+ opt_val = 0x28;
+ opt_len = (INT)sizeof(INT);
+ ret = setsockopt(udp_sock, IPPROTO_IP, IP_TOS, &opt_val, opt_len);
+ if (ret != 0)
+ error_counter++;
+
+ opt_val = 0;
+ opt_len = (INT)sizeof(INT);
+ ret = getsockopt(udp_sock, IPPROTO_IP, IP_TOS, &opt_val, &opt_len);
+ if (ret != 0)
+ error_counter++;
+ if (opt_val != 0x28)
+ error_counter++;
+
+ /* IP_TOS: out-of-range values must be rejected. */
+ opt_val = 256;
+ opt_len = (INT)sizeof(INT);
+ ret = setsockopt(tcp_sock, IPPROTO_IP, IP_TOS, &opt_val, opt_len);
+ if (ret == 0)
+ error_counter++;
+
+ opt_val = -1;
+ opt_len = (INT)sizeof(INT);
+ ret = setsockopt(tcp_sock, IPPROTO_IP, IP_TOS, &opt_val, opt_len);
+ if (ret == 0)
+ error_counter++;
+
+ /* A SO_* option number passed to IPPROTO_IP level must be rejected. */
+ opt_val = 1;
+ opt_len = (INT)sizeof(INT);
+ ret = setsockopt(tcp_sock, IPPROTO_IP, SO_BROADCAST, &opt_val, opt_len);
+ if (ret == 0)
+ error_counter++;
+
+ /* ================================================================
+ * IP_TTL: round-trip on TCP socket with INT-sized input
+ * ================================================================ */
+ opt_val = 64;
+ opt_len = (INT)sizeof(INT);
+ ret = setsockopt(tcp_sock, IPPROTO_IP, IP_TTL, &opt_val, opt_len);
+ if (ret != 0)
+ error_counter++;
+
+ {
+ UCHAR ttl_get = 0;
+ INT ttl_len = (INT)sizeof(UCHAR);
+
+ ret = getsockopt(tcp_sock, IPPROTO_IP, IP_TTL, &ttl_get, &ttl_len);
+ if (ret != 0)
+ error_counter++;
+ if (ttl_get != 64)
+ error_counter++;
+ }
+
+ /* IP_TTL: round-trip on UDP socket. */
+ opt_val = 128;
+ opt_len = (INT)sizeof(INT);
+ ret = setsockopt(udp_sock, IPPROTO_IP, IP_TTL, &opt_val, opt_len);
+ if (ret != 0)
+ error_counter++;
+
+ {
+ UCHAR ttl_get = 0;
+ INT ttl_len = (INT)sizeof(UCHAR);
+
+ ret = getsockopt(udp_sock, IPPROTO_IP, IP_TTL, &ttl_get, &ttl_len);
+ if (ret != 0)
+ error_counter++;
+ if (ttl_get != 128)
+ error_counter++;
+ }
+
+ /* IP_TTL: out-of-range INT values must be rejected. */
+ opt_val = 300;
+ opt_len = (INT)sizeof(INT);
+ ret = setsockopt(tcp_sock, IPPROTO_IP, IP_TTL, &opt_val, opt_len);
+ if (ret == 0)
+ error_counter++;
+
+ opt_val = -1;
+ opt_len = (INT)sizeof(INT);
+ ret = setsockopt(tcp_sock, IPPROTO_IP, IP_TTL, &opt_val, opt_len);
+ if (ret == 0)
+ error_counter++;
+
+ /* ================================================================
+ * SO_BROADCAST: getsockopt validates option_length
+ * ================================================================ */
+ opt_val = 0;
+ opt_len = (INT)sizeof(INT);
+ ret = getsockopt(tcp_sock, SOL_SOCKET, SO_BROADCAST, &opt_val, &opt_len);
+ if (ret != 0)
+ error_counter++;
+ if (opt_val != 1)
+ error_counter++;
+ if (opt_len != (INT)sizeof(INT))
+ error_counter++;
+
+ opt_val = 0;
+ opt_len = 1;
+ ret = getsockopt(tcp_sock, SOL_SOCKET, SO_BROADCAST, &opt_val, &opt_len);
+ if (ret == 0)
+ error_counter++;
+
+ /* ================================================================
+ * TCP_NODELAY: getsockopt validates option_length
+ * ================================================================ */
+ opt_val = 0;
+ opt_len = (INT)sizeof(INT);
+ ret = getsockopt(tcp_sock, IPPROTO_TCP, TCP_NODELAY, &opt_val, &opt_len);
+ if (ret != 0)
+ error_counter++;
+ if (opt_val != 1)
+ error_counter++;
+ if (opt_len != (INT)sizeof(INT))
+ error_counter++;
+
+ opt_val = 0;
+ opt_len = 1;
+ ret = getsockopt(tcp_sock, IPPROTO_TCP, TCP_NODELAY, &opt_val, &opt_len);
+ if (ret == 0)
+ error_counter++;
+
+ /* Clean up. */
+ soc_close(tcp_sock);
+ soc_close(udp_sock);
+
+ if (error_counter)
+ test_control_return(1);
+ else
+ test_control_return(0);
+}
+
+#else
+#ifdef CTEST
+VOID test_application_define(void *first_unused_memory)
+#else
+void netx_bsd_socket_options_test_application_define(void *first_unused_memory)
+#endif
+{
+ NX_PARAMETER_NOT_USED(first_unused_memory);
+ test_control_return(3);
+}
+#endif /* NX_BSD_ENABLE && !NX_DISABLE_IPV4 && __PRODUCT_NETXDUO__ */