diff options
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.c | 335 |
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__ */ |
