summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormzgrebnak <[email protected]>2026-05-29 16:34:38 +0200
committerGitHub <[email protected]>2026-05-29 10:34:38 -0400
commit09ce97f8f9019724407917c197c2a0c0e859bf2d (patch)
tree3f0683ac14105149cf0759ea1fa133ed9675cd34
parent53070b69eed6af6840b0a890fe749e73e3f280f2 (diff)
Added BSD recvfromto support (#376)
* recvfromto support * nx_bsd_inet_aton, disabling other format than four numbers separated by dots. Otherwise used in nx_bsd_inet_pton It accepts unallowed format of IP address. * bsd: address PR review feedback - Fix build failure: add missing nx_bsd_recvfromto() prototype to nxd_bsd.h near the other receive prototypes. The nx_bsd_recvfromto macro maps to recvfromto, but without a prior declaration the compiler emits -Werror=missing-declarations. - Revert inet_aton() change: restore the 1-part, 2-part and 3-part abbreviated IPv4 address formats (a.b.c and a.b). The PR removed them, breaking existing tests that rely on these forms. - Add IPv6 destination address support in recvfromto(): when the receiving BSD socket is AF_INET6, extract the destination IPv6 address from the IPv6 packet header and populate a sockaddr_in6 in toAddr, mirroring the existing IPv4 path. - Add regression test netx_bsd_recvfromto_test covering: * recvfromto() populates fromAddr (sender) and toAddr (destination) with correct address/port values for IPv4 UDP * recvfromto() with NULL toAddr/toAddrLen works like recvfrom() * inet_aton() still accepts abbreviated a.b and a.b.c forms Register test in regression/CMakeLists.txt. --------- Co-authored-by: Frédéric Desbiens <[email protected]> Co-authored-by: Copilot <[email protected]>
-rw-r--r--addons/BSD/nxd_bsd.c72
-rw-r--r--addons/BSD/nxd_bsd.h2
-rw-r--r--test/cmake/netxduo/regression/CMakeLists.txt3
-rw-r--r--test/regression/bsd_test/netx_bsd_recvfromto_test.c315
4 files changed, 386 insertions, 6 deletions
diff --git a/addons/BSD/nxd_bsd.c b/addons/BSD/nxd_bsd.c
index 10a2dee5..b69edf57 100644
--- a/addons/BSD/nxd_bsd.c
+++ b/addons/BSD/nxd_bsd.c
@@ -164,7 +164,8 @@ static VOID _nxd_bsd_ipv4_packet_send(NX_PACKET *packet_ptr);
static INT nx_bsd_send_internal(INT sockID, const CHAR *msg, INT msgLength, INT flags,
NXD_ADDRESS *dst_address, USHORT dst_port, UINT local_interface_index);
static INT nx_bsd_recv_internal(INT sockID, struct nx_bsd_iovec *iov, size_t iovlen, INT flags,
- struct nx_bsd_sockaddr *fromAddr, INT *fromAddrLen);
+ struct nx_bsd_sockaddr *fromAddr, INT *fromAddrLen,
+ struct nx_bsd_sockaddr *toAddr, INT *toAddrLen);
#ifdef FEATURE_NX_IPV6
static VOID _nxd_bsd_ipv6_packet_send(NX_PACKET *packet_ptr, ULONG *src_addr, ULONG *dest_addr);
#endif /* FEATURE_NX_IPV6 */
@@ -3931,7 +3932,7 @@ struct nx_bsd_iovec iov;
iov.iov_len = (size_t)bufferLength;
/* Call the recv_internal() function. */
- return nx_bsd_recv_internal(sockID, &iov, 1, flags, NX_NULL, NX_NULL);
+ return nx_bsd_recv_internal(sockID, &iov, 1, flags, NX_NULL, NX_NULL, NX_NULL, NX_NULL);
}
@@ -3986,7 +3987,21 @@ struct nx_bsd_iovec iov;
iov.iov_len = (size_t)bufferLength;
/* Call the recv_internal() function. */
- return nx_bsd_recv_internal(sockID, &iov, 1, flags, fromAddr, fromAddrLen);
+ return nx_bsd_recv_internal(sockID, &iov, 1, flags, fromAddr, fromAddrLen, NX_NULL, NX_NULL);
+}
+
+
+INT nx_bsd_recvfromto(INT sockID, CHAR *rcvBuffer, INT bufferLength, INT flags,
+ struct nx_bsd_sockaddr *fromAddr, INT *fromAddrLen,
+ struct nx_bsd_sockaddr *toAddr, INT *toAddrLen)
+{
+struct nx_bsd_iovec iov;
+
+ iov.iov_base = rcvBuffer;
+ iov.iov_len = (size_t)bufferLength;
+
+ /* Call the recv_internal() function. */
+ return nx_bsd_recv_internal(sockID, &iov, 1, flags, fromAddr, fromAddrLen, toAddr, toAddrLen);
}
/**************************************************************************/
@@ -4035,7 +4050,7 @@ INT fromAddrLen = 0;
fromAddrLen = (INT)(msg -> msg_namelen);
}
- return(nx_bsd_recv_internal(sockID, msg -> msg_iov, msg -> msg_iovlen, flags, (struct nx_bsd_sockaddr *)(msg -> msg_name), &fromAddrLen));
+ return(nx_bsd_recv_internal(sockID, msg -> msg_iov, msg -> msg_iovlen, flags, (struct nx_bsd_sockaddr *)(msg -> msg_name), &fromAddrLen, NX_NULL, NX_NULL));
}
/**************************************************************************/
@@ -4102,7 +4117,9 @@ INT fromAddrLen = 0;
/* recvfrom */
/* */
/**************************************************************************/
-static INT nx_bsd_recv_internal(INT sockID, struct nx_bsd_iovec *iov, size_t iovlen, INT flags, struct nx_bsd_sockaddr *fromAddr, INT *fromAddrLen)
+static INT nx_bsd_recv_internal(INT sockID, struct nx_bsd_iovec *iov, size_t iovlen, INT flags,
+ struct nx_bsd_sockaddr *fromAddr, INT *fromAddrLen,
+ struct nx_bsd_sockaddr *toAddr, INT *toAddrLen)
{
UINT status;
NX_PACKET *packet_ptr;
@@ -4388,6 +4405,51 @@ struct nx_bsd_sockaddr_in6
/* Get the sender and port from the UDP packet. */
nxd_udp_source_extract(packet_ptr, &bsd_socket_ptr -> nx_bsd_socket_source_ip_address, (UINT *)&bsd_socket_ptr -> nx_bsd_socket_source_port);
+
+ if(toAddr && (*toAddrLen != 0))
+ {
+#ifndef NX_DISABLE_IPV4
+ if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
+ {
+ ULONG nx_ip_header_destination_ip = ((NX_IPV4_HEADER *)packet_ptr -> nx_packet_ip_header) -> nx_ip_header_destination_ip;
+ ULONG *prepend_ptr = (ULONG *)packet_ptr -> nx_packet_prepend_ptr;
+ USHORT dst_port = (USHORT)(*(prepend_ptr - 2U) & 0xFFFFU);
+ struct nx_bsd_sockaddr_in destination_address;
+
+ destination_address.sin_family = AF_INET;
+ destination_address.sin_addr.s_addr = ntohl(nx_ip_header_destination_ip);
+ destination_address.sin_port = ntohs(dst_port);
+
+ if(*toAddrLen > (INT)sizeof(struct nx_bsd_sockaddr_in))
+ {
+ *toAddrLen = (INT)sizeof(struct nx_bsd_sockaddr_in);
+ }
+ memcpy(toAddr, &destination_address, (UINT)(*toAddrLen));
+ }
+#endif /* NX_DISABLE_IPV4 */
+#ifdef FEATURE_NX_IPV6
+ if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
+ {
+ NX_IPV6_HEADER *ipv6_header = (NX_IPV6_HEADER *)packet_ptr -> nx_packet_ip_header;
+ ULONG *prepend_ptr = (ULONG *)packet_ptr -> nx_packet_prepend_ptr;
+ USHORT dst_port = (USHORT)(*(prepend_ptr - 2U) & 0xFFFFU);
+ struct nx_bsd_sockaddr_in6 destination_address6;
+
+ destination_address6.sin6_family = AF_INET6;
+ destination_address6.sin6_addr._S6_un._S6_u32[0] = ntohl(ipv6_header -> nx_ip_header_destination_ip[0]);
+ destination_address6.sin6_addr._S6_un._S6_u32[1] = ntohl(ipv6_header -> nx_ip_header_destination_ip[1]);
+ destination_address6.sin6_addr._S6_un._S6_u32[2] = ntohl(ipv6_header -> nx_ip_header_destination_ip[2]);
+ destination_address6.sin6_addr._S6_un._S6_u32[3] = ntohl(ipv6_header -> nx_ip_header_destination_ip[3]);
+ destination_address6.sin6_port = ntohs(dst_port);
+
+ if(*toAddrLen > (INT)sizeof(struct nx_bsd_sockaddr_in6))
+ {
+ *toAddrLen = (INT)sizeof(struct nx_bsd_sockaddr_in6);
+ }
+ memcpy(toAddr, &destination_address6, (UINT)(*toAddrLen));
+ }
+#endif /* FEATURE_NX_IPV6 */
+ }
}
#if defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)
diff --git a/addons/BSD/nxd_bsd.h b/addons/BSD/nxd_bsd.h
index 15d1c1ac..5223efd0 100644
--- a/addons/BSD/nxd_bsd.h
+++ b/addons/BSD/nxd_bsd.h
@@ -238,6 +238,7 @@ extern "C" {
#define nx_bsd_inet_ntop inet_ntop
#define nx_bsd_listen listen
#define nx_bsd_recvfrom recvfrom
+#define nx_bsd_recvfromto recvfromto
#define nx_bsd_recv recv
#define nx_bsd_recvmsg recvmsg
#define nx_bsd_sendto sendto
@@ -1014,6 +1015,7 @@ VOID nx_bsd_raw_receive_notify(NX_IP *ip_ptr, UINT bsd_socket_index);
#endif
UINT nx_bsd_socket_set_inherited_settings(UINT master_sock_id, UINT secondary_sock_id);
INT nx_bsd_recvfrom(INT sockID, CHAR *buffer, INT buffersize, INT flags,struct nx_bsd_sockaddr *fromAddr, INT *fromAddrLen);
+INT nx_bsd_recvfromto(INT sockID, CHAR *rcvBuffer, INT bufferLength, INT flags, struct nx_bsd_sockaddr *fromAddr, INT *fromAddrLen, struct nx_bsd_sockaddr *toAddr, INT *toAddrLen);
INT nx_bsd_recv(INT sockID, VOID *rcvBuffer, INT bufferLength, INT flags);
INT nx_bsd_recvmsg(INT sockID, struct nx_bsd_msghdr *msg, INT flags);
INT nx_bsd_sendto(INT sockID, CHAR *msg, INT msgLength, INT flags, struct nx_bsd_sockaddr *destAddr, INT destAddrLen);
diff --git a/test/cmake/netxduo/regression/CMakeLists.txt b/test/cmake/netxduo/regression/CMakeLists.txt
index 4dbad145..794d4b36 100644
--- a/test/cmake/netxduo/regression/CMakeLists.txt
+++ b/test/cmake/netxduo/regression/CMakeLists.txt
@@ -55,7 +55,8 @@ if("-DNX_BSD_ENABLE" IN_LIST ${CMAKE_BUILD_TYPE})
${SOURCE_DIR}/bsd_test/netx_bsd_tcp_fionread_test.c
${SOURCE_DIR}/bsd_test/netx_bsd_select_spurious_event_test.c
${SOURCE_DIR}/bsd_test/netx_bsd_socket_options_test.c
- ${SOURCE_DIR}/bsd_test/netx_bsd_select_improvements_test.c)
+ ${SOURCE_DIR}/bsd_test/netx_bsd_select_improvements_test.c
+ ${SOURCE_DIR}/bsd_test/netx_bsd_recvfromto_test.c)
if("-DNX_BSD_RAW_SUPPORT" IN_LIST ${CMAKE_BUILD_TYPE})
list(
APPEND
diff --git a/test/regression/bsd_test/netx_bsd_recvfromto_test.c b/test/regression/bsd_test/netx_bsd_recvfromto_test.c
new file mode 100644
index 00000000..223e5c04
--- /dev/null
+++ b/test/regression/bsd_test/netx_bsd_recvfromto_test.c
@@ -0,0 +1,315 @@
+/***************************************************************************
+ * 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 covers the recvfromto() API from PR #376:
+ *
+ * 1. recvfromto() populates fromAddr with the sender's address/port and
+ * toAddr with the destination (local) address/port of the UDP packet.
+ *
+ * 2. recvfromto() with NULL toAddr/toAddrLen works like recvfrom().
+ *
+ * 3. inet_aton() still accepts abbreviated IPv4 forms such as a.b.c
+ * and a.b (regression for the inet_aton revert).
+ */
+
+#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
+#define TEST_PORT 4444
+
+static TX_THREAD ntest_0;
+static TX_THREAD ntest_1;
+
+static NX_PACKET_POOL pool_0;
+static NX_IP ip_0; /* BSD receiver: 1.2.3.4 */
+static NX_IP ip_1; /* NX sender: 1.2.3.5 */
+static TX_SEMAPHORE sema_rx_ready;
+static TX_SEMAPHORE sema_done;
+
+static ULONG error_counter;
+
+static ULONG packet_pool_area[(512 + sizeof(NX_PACKET)) * 32 / 4];
+static ULONG bsd_thread_area[DEMO_STACK_SIZE / sizeof(ULONG)];
+
+static void ntest_0_entry(ULONG thread_input);
+static void ntest_1_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_recvfromto_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;
+
+ tx_thread_create(&ntest_1, "thread 1", ntest_1_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", 512,
+ 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_ip_create(&ip_1, "NetX IP Instance 1",
+ IP_ADDRESS(1, 2, 3, 5), 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_arp_enable(&ip_1, (void *)pointer, 1024);
+ pointer += 1024;
+ if (status)
+ error_counter++;
+
+ status = nx_udp_enable(&ip_0);
+ status += nx_udp_enable(&ip_1);
+ 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++;
+
+ status = tx_semaphore_create(&sema_rx_ready, "RX READY", 0);
+ if (status)
+ error_counter++;
+
+ status = tx_semaphore_create(&sema_done, "DONE", 0);
+ if (status)
+ error_counter++;
+}
+
+/* Thread 0: BSD receiver */
+static void ntest_0_entry(ULONG thread_input)
+{
+INT sock;
+struct nx_bsd_sockaddr_in local_addr;
+struct nx_bsd_sockaddr_in from_addr;
+struct nx_bsd_sockaddr_in to_addr;
+INT from_len;
+INT to_len;
+CHAR buf[64];
+INT ret;
+UINT actual_status;
+
+ /* Wait for IP stack initialisation. */
+ nx_ip_status_check(&ip_0, NX_IP_INITIALIZE_DONE, &actual_status,
+ NX_IP_PERIODIC_RATE);
+
+ /* --- Test 1: recvfromto() populates fromAddr and toAddr --- */
+ sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock < 0)
+ {
+ error_counter++;
+ test_control_return(1);
+ return;
+ }
+
+ memset(&local_addr, 0, sizeof(local_addr));
+ local_addr.sin_family = AF_INET;
+ local_addr.sin_port = htons(TEST_PORT);
+ local_addr.sin_addr.s_addr = htonl(IP_ADDRESS(1, 2, 3, 4));
+
+ if (bind(sock, (struct nx_bsd_sockaddr *)&local_addr, sizeof(local_addr)) < 0)
+ {
+ error_counter++;
+ soc_close(sock);
+ test_control_return(1);
+ return;
+ }
+
+ /* Signal sender that receiver is ready. */
+ tx_semaphore_put(&sema_rx_ready);
+
+ memset(&from_addr, 0, sizeof(from_addr));
+ memset(&to_addr, 0, sizeof(to_addr));
+ from_len = sizeof(from_addr);
+ to_len = sizeof(to_addr);
+
+ ret = recvfromto(sock, buf, sizeof(buf), 0,
+ (struct nx_bsd_sockaddr *)&from_addr, &from_len,
+ (struct nx_bsd_sockaddr *)&to_addr, &to_len);
+ if (ret <= 0)
+ {
+ error_counter++;
+ }
+ else
+ {
+ /* Validate fromAddr: must be 1.2.3.5 : any port */
+ if (from_addr.sin_family != AF_INET)
+ error_counter++;
+ if (ntohl(from_addr.sin_addr.s_addr) != IP_ADDRESS(1, 2, 3, 5))
+ error_counter++;
+
+ /* Validate toAddr: must be 1.2.3.4 : TEST_PORT */
+ if (to_addr.sin_family != AF_INET)
+ error_counter++;
+ if (ntohl(to_addr.sin_addr.s_addr) != IP_ADDRESS(1, 2, 3, 4))
+ error_counter++;
+ if (ntohs(to_addr.sin_port) != TEST_PORT)
+ error_counter++;
+
+ /* toAddrLen must be trimmed to sizeof(sockaddr_in). */
+ if (to_len != (INT)sizeof(struct nx_bsd_sockaddr_in))
+ error_counter++;
+ }
+
+ soc_close(sock);
+
+ /* --- Test 2: recvfromto() with NULL toAddr works like recvfrom() --- */
+ sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock < 0)
+ {
+ error_counter++;
+ test_control_return(1);
+ return;
+ }
+
+ memset(&local_addr, 0, sizeof(local_addr));
+ local_addr.sin_family = AF_INET;
+ local_addr.sin_port = htons(TEST_PORT);
+ local_addr.sin_addr.s_addr = htonl(IP_ADDRESS(1, 2, 3, 4));
+
+ if (bind(sock, (struct nx_bsd_sockaddr *)&local_addr, sizeof(local_addr)) < 0)
+ {
+ error_counter++;
+ soc_close(sock);
+ test_control_return(1);
+ return;
+ }
+
+ tx_semaphore_put(&sema_rx_ready);
+
+ memset(&from_addr, 0, sizeof(from_addr));
+ from_len = sizeof(from_addr);
+
+ ret = recvfromto(sock, buf, sizeof(buf), 0,
+ (struct nx_bsd_sockaddr *)&from_addr, &from_len,
+ NX_NULL, NX_NULL);
+ if (ret <= 0)
+ error_counter++;
+
+ soc_close(sock);
+
+ /* --- Test 3: inet_aton() still accepts abbreviated IPv4 forms --- */
+ {
+ struct in_addr in_val;
+ INT rc;
+
+ /* a.b format: 11.657930 == 11.0x0a0a0a == 11.10.10.10 */
+ rc = inet_aton("11.657930", &in_val);
+ if (rc == 0)
+ error_counter++;
+
+ /* a.b.c format: 11.10.2570 == 11.10.0x0a0a == 11.10.10.10 */
+ rc = inet_aton("11.10.2570", &in_val);
+ if (rc == 0)
+ error_counter++;
+
+ /* standard dotted-decimal must still work */
+ rc = inet_aton("11.10.10.10", &in_val);
+ if (rc == 0)
+ error_counter++;
+ }
+
+ tx_semaphore_put(&sema_done);
+}
+
+/* Thread 1: NX UDP sender */
+static void ntest_1_entry(ULONG thread_input)
+{
+NX_UDP_SOCKET udp_socket;
+NX_PACKET *packet_ptr;
+NXD_ADDRESS dest_addr;
+UINT actual_status;
+
+ nx_ip_status_check(&ip_1, NX_IP_INITIALIZE_DONE, &actual_status,
+ NX_IP_PERIODIC_RATE);
+
+ nx_udp_socket_create(&ip_1, &udp_socket, "UDP sender",
+ NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 8);
+ nx_udp_socket_bind(&udp_socket, NX_ANY_PORT, NX_WAIT_FOREVER);
+
+ memset(&dest_addr, 0, sizeof(dest_addr));
+ dest_addr.nxd_ip_version = NX_IP_VERSION_V4;
+ dest_addr.nxd_ip_address.v4 = IP_ADDRESS(1, 2, 3, 4);
+
+ /* Send for Test 1 */
+ tx_semaphore_get(&sema_rx_ready, NX_IP_PERIODIC_RATE);
+
+ nx_packet_allocate(&pool_0, &packet_ptr, NX_UDP_PACKET, NX_WAIT_FOREVER);
+ nx_packet_data_append(packet_ptr, "hello", 5, &pool_0, NX_WAIT_FOREVER);
+ nxd_udp_socket_send(&udp_socket, packet_ptr, &dest_addr, TEST_PORT);
+
+ /* Send for Test 2 */
+ tx_semaphore_get(&sema_rx_ready, NX_IP_PERIODIC_RATE);
+
+ nx_packet_allocate(&pool_0, &packet_ptr, NX_UDP_PACKET, NX_WAIT_FOREVER);
+ nx_packet_data_append(packet_ptr, "world", 5, &pool_0, NX_WAIT_FOREVER);
+ nxd_udp_socket_send(&udp_socket, packet_ptr, &dest_addr, TEST_PORT);
+
+ nx_udp_socket_unbind(&udp_socket);
+ nx_udp_socket_delete(&udp_socket);
+
+ /* Wait for receiver to finish then report result. */
+ tx_semaphore_get(&sema_done, 5 * NX_IP_PERIODIC_RATE);
+ test_control_return(error_counter ? 1 : 0);
+}
+
+#else /* !(NX_BSD_ENABLE && !NX_DISABLE_IPV4) */
+#ifdef CTEST
+VOID test_application_define(void *first_unused_memory)
+#else
+void netx_bsd_recvfromto_test_application_define(void *first_unused_memory)
+#endif
+{
+ NX_PARAMETER_NOT_USED(first_unused_memory);
+ test_control_return(3); /* skip */
+}
+#endif /* NX_BSD_ENABLE && !NX_DISABLE_IPV4 */