summaryrefslogtreecommitdiff
path: root/addons/BSD
diff options
context:
space:
mode:
authorFrédéric Desbiens <[email protected]>2026-06-08 10:03:52 +0200
committerGitHub <[email protected]>2026-06-08 10:03:52 +0200
commit1a0e9e43a03e37ddecfb6b49e9b078d6e1803d05 (patch)
treec60ec41b4ff4fd2d7566c505cbdd423ceddd65f3 /addons/BSD
parent8b6e03ac30ab688bec02c69d42f2304b7f72a202 (diff)
parent4d88828b06d164a5b7e82152395a92254abcd6e4 (diff)
Merge pull request #391 from eclipse-threadx/devv6.5.1.202602_reldev
Merging changes for the v.6.5.1.202602 release
Diffstat (limited to 'addons/BSD')
-rw-r--r--addons/BSD/nxd_bsd.c579
-rw-r--r--addons/BSD/nxd_bsd.h7
2 files changed, 549 insertions, 37 deletions
diff --git a/addons/BSD/nxd_bsd.c b/addons/BSD/nxd_bsd.c
index ef27b0dd..b69edf57 100644
--- a/addons/BSD/nxd_bsd.c
+++ b/addons/BSD/nxd_bsd.c
@@ -8,8 +8,7 @@
*
* SPDX-License-Identifier: MIT
**************************************************************************/
-
-/**************************************************************************/
+/* Some portions generated by Copilot (claude-sonnet-4.6). */
/**************************************************************************/
/** */
/** BSD 4.3 Socket API Compatible Interface to NetX Duo */
@@ -140,6 +139,7 @@ static UINT nx_bsd_isxdigit(UCHAR c);
/* Standard BSD callback functions to register with NetX Duo. */
static VOID nx_bsd_tcp_receive_notify(NX_TCP_SOCKET *socket_ptr);
+static VOID nx_bsd_tcp_exception_notify(NX_TCP_SOCKET *socket_ptr);
static VOID nx_bsd_tcp_socket_disconnect_notify(NX_TCP_SOCKET *socket_ptr);
static VOID nx_bsd_udp_receive_notify(NX_UDP_SOCKET *socket_ptr);
#ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
@@ -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 */
@@ -935,7 +936,8 @@ UINT index;
including the ones covered by tcp_socket_disconnect_notify. */
status = nx_tcp_socket_create(nx_bsd_default_ip, tcp_socket_ptr, "NetX BSD TCP Socket",
- NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, NX_BSD_TCP_WINDOW, NX_NULL,
+ NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, NX_BSD_TCP_WINDOW,
+ nx_bsd_tcp_exception_notify,
nx_bsd_tcp_socket_disconnect_notify);
/* Check for a successful status. */
@@ -3015,8 +3017,11 @@ struct nx_bsd_sockaddr_in6
/* Reset the master_socket_id */
ret = nx_bsd_tcp_create_listen_socket(sockID, 0);
- if(ret < 0)
+ if (ret < 0)
{
+ /* Could not create the next listen socket (e.g. all BSD socket slots are in use).
+ Mark the secondary slot invalid so it is not reused, but still return the
+ already-accepted socket descriptor to the caller. */
(bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = NX_BSD_MAX_SOCKETS;
}
@@ -3748,7 +3753,7 @@ USHORT peer_port = 0;
/* This is a UDP or raw socket. */
- /* Check whther or not the socket is AF_PACKET family. */
+ /* Check whether or not the socket is AF_PACKET family. */
if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
{
@@ -3927,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);
}
@@ -3982,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);
}
/**************************************************************************/
@@ -4031,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));
}
/**************************************************************************/
@@ -4098,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;
@@ -4249,7 +4270,7 @@ struct nx_bsd_sockaddr_in6
status = nx_tcp_socket_receive(tcp_socket_ptr, &packet_ptr, TX_NO_WAIT);
/* Check for no packet on the queue. */
- if (status == NX_NOT_CONNECTED)
+ if (status == NX_NOT_CONNECTED || status == NX_NOT_BOUND)
{
/* Release the protection mutex. */
@@ -4384,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)
@@ -4891,7 +4957,23 @@ UINT index;
/* Release the mutex while disconnecting. */
tx_mutex_put(nx_bsd_protection_ptr);
- nx_tcp_socket_disconnect(tcp_socket_ptr, timeout);
+ if (!(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_LINGER))
+ {
+ /* SO_LINGER disabled: normal graceful close. */
+ nx_tcp_socket_disconnect(tcp_socket_ptr, timeout);
+ }
+ else if (bsd_socket_ptr -> nx_bsd_option_linger.l_linger == 0)
+ {
+ /* l_linger == 0: abort immediately with RST. */
+ nx_tcp_socket_disconnect(tcp_socket_ptr, NX_NO_WAIT);
+ }
+ else
+ {
+ /* l_linger > 0: wait up to l_linger seconds for graceful close. */
+ ULONG ticks = (ULONG)(bsd_socket_ptr -> nx_bsd_option_linger.l_linger) * NX_IP_PERIODIC_RATE;
+
+ nx_tcp_socket_disconnect(tcp_socket_ptr, ticks);
+ }
tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
@@ -5026,6 +5108,8 @@ UINT index;
tx_mutex_put(nx_bsd_protection_ptr);
+ nx_bsd_select_wakeup((UINT)sockID, FDSET_READ);
+
/* Return */
return(NX_SOC_OK);
@@ -5105,6 +5189,8 @@ UINT index;
/* Release the protection mutex. */
tx_mutex_put(nx_bsd_protection_ptr);
+ nx_bsd_select_wakeup((UINT)sockID, FDSET_READ);
+
return(NX_SOC_OK);
}
@@ -6092,7 +6178,7 @@ ULONG ticks;
if (option_level == IPPROTO_IP)
{
- if((option_name <= SO_MAX) || (option_name > IP_OPTION_MAX))
+ if ((option_name < IP_TOS) || (option_name > IP_OPTION_MAX))
{
/* Error, one or more invalid arguments. */
@@ -6119,6 +6205,20 @@ ULONG ticks;
return NX_SOC_ERROR;
}
}
+ else if(option_level == IPPROTO_TCP)
+ {
+ if((option_name != TCP_NODELAY))
+ {
+
+ /* Error, one or more invalid arguments. */
+
+ /* Set the socket error if extended socket options enabled. */
+ nx_bsd_set_errno(ENOPROTOOPT);
+
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+ }
+ }
else
{
@@ -6155,6 +6255,44 @@ ULONG ticks;
switch (option_name)
{
+ case IP_TOS:
+
+ if (*option_length < (INT)sizeof(INT))
+ {
+
+ tx_mutex_put(nx_bsd_protection_ptr);
+
+ /* Set the socket error if extended socket options enabled. */
+ nx_bsd_set_errno(EINVAL);
+
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+ }
+ else if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
+ {
+ ULONG tmp_option_value = bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_type_of_service;
+ *((INT *)option_value) = (INT)(tmp_option_value >> 16);
+ }
+ else if (bsd_socket_ptr -> nx_bsd_socket_udp_socket)
+ {
+ ULONG tmp_option_value = bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_type_of_service;
+ *((INT *)option_value) = (INT)(tmp_option_value >> 16);
+ }
+ else
+ {
+ tx_mutex_put(nx_bsd_protection_ptr);
+
+ /* Raw sockets do not support IP_TOS. */
+ nx_bsd_set_errno(ENOPROTOOPT);
+
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+ }
+
+ *option_length = (INT)sizeof(INT);
+
+ break;
+
case SO_ERROR:
{
@@ -6195,6 +6333,26 @@ ULONG ticks;
break;
+ case SO_BROADCAST:
+
+ if (*option_length < (INT)sizeof(INT))
+ {
+
+ tx_mutex_put(nx_bsd_protection_ptr);
+
+ /* Set the socket error if extended socket options enabled. */
+ nx_bsd_set_errno(EINVAL);
+
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+ }
+
+ /* This is the default behavior of NetX. All sockets have this capability. */
+ *((INT *)option_value) = 1;
+ *option_length = (INT)sizeof(INT);
+
+ break;
+
case SO_KEEPALIVE:
/* Determine if NetX Duo supports keepalive. */
@@ -6222,6 +6380,40 @@ ULONG ticks;
break;
+ case SO_LINGER:
+
+ /* Only available to TCP BSD sockets. */
+ if (!bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
+ {
+ tx_mutex_put(nx_bsd_protection_ptr);
+
+ /* Set the socket error if extended socket options enabled. */
+ nx_bsd_set_errno(ENOPROTOOPT);
+
+ /* Return an error status. */
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+ }
+
+ if (*option_length < (INT)sizeof(struct nx_bsd_linger))
+ {
+ tx_mutex_put(nx_bsd_protection_ptr);
+
+ /* Set the socket error if extended socket options enabled. */
+ nx_bsd_set_errno(EINVAL);
+
+ /* Return an error status. */
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+ }
+
+ (*((struct nx_bsd_linger *)option_value)).l_onoff =
+ (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_LINGER) ? 1 : 0;
+ (*((struct nx_bsd_linger *)option_value)).l_linger = bsd_socket_ptr -> nx_bsd_option_linger.l_linger;
+ *option_length = (INT)sizeof(struct nx_bsd_linger);
+
+ break;
+
case SO_RCVTIMEO:
/* Check if the receive time out is set. */
@@ -6250,6 +6442,20 @@ ULONG ticks;
case SO_RCVBUF:
+ /* Only available to TCP sockets. */
+ if (!bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
+ {
+
+ tx_mutex_put(nx_bsd_protection_ptr);
+
+ /* Set the socket error if extended socket options enabled. */
+ nx_bsd_set_errno(ENOPROTOOPT);
+
+ /* Return an error status. */
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+ }
+
soc_window_size = (struct nx_bsd_sock_winsize *)option_value;
soc_window_size -> winsize = (INT)(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_default);
*option_length = sizeof(soc_window_size);
@@ -6277,10 +6483,31 @@ ULONG ticks;
break;
+ case TCP_NODELAY:
+
+ if (*option_length < (INT)sizeof(INT))
+ {
+
+ tx_mutex_put(nx_bsd_protection_ptr);
+
+ /* Set the socket error if extended socket options enabled. */
+ nx_bsd_set_errno(EINVAL);
+
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+ }
+
+ /* This is the default behavior of NetX. All sockets have this attribute. */
+ *((INT *)option_value) = 1;
+ *option_length = (INT)sizeof(INT);
+
+ break;
+
+ case IP_TTL:
case IP_MULTICAST_TTL:
/* Validate the option length. */
- if(*option_length != sizeof(UCHAR))
+ if (*option_length < (INT)sizeof(UCHAR))
{
tx_mutex_put(nx_bsd_protection_ptr);
@@ -6305,23 +6532,63 @@ ULONG ticks;
return NX_SOC_ERROR;
}
- /* Make sure socket is UDP type. */
- if(bsd_socket_ptr -> nx_bsd_socket_udp_socket == NX_NULL)
+ /* Socket is UDP type. */
+ if (bsd_socket_ptr -> nx_bsd_socket_udp_socket != NX_NULL)
+ {
+
+ /* Get the TTL value. */
+ *(UCHAR *)option_value = (UCHAR)(bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_time_to_live);
+ }
+ /* Socket is TCP type. */
+ else if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket != NX_NULL)
+ {
+
+ if (option_name == IP_MULTICAST_TTL)
+ {
+
+ tx_mutex_put(nx_bsd_protection_ptr);
+
+ /* Set the socket error if extended socket options enabled. */
+ nx_bsd_set_errno(ENOPROTOOPT);
+
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+ }
+
+ /* Get the TTL value. */
+ *(UCHAR *)option_value = (UCHAR)(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_time_to_live);
+ }
+ else
{
tx_mutex_put(nx_bsd_protection_ptr);
- /* Set the socket error if extended socket options enabled. */
+ /* Raw sockets do not support IP_TTL/IP_MULTICAST_TTL. */
nx_bsd_set_errno(ENOPROTOOPT);
NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
return NX_SOC_ERROR;
}
- /* Set the TTL value. */
- *(UCHAR*)option_value = (UCHAR)(bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_time_to_live);
+ *option_length = (INT)sizeof(UCHAR);
+
break;
+ case IP_MULTICAST_IF:
+
+ /* This is not supported yet. */
+
+ tx_mutex_put(nx_bsd_protection_ptr);
+
+ /* Set the socket error if extended socket options enabled. */
+ nx_bsd_set_errno(ENOPROTOOPT);
+
+ /* Return an error status. */
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+
+ break;
+
default:
tx_mutex_put(nx_bsd_protection_ptr);
@@ -6431,7 +6698,7 @@ ULONG physical_addr_lsw;
if (option_level == IPPROTO_IP)
{
- if((option_name <= SO_MAX) || (option_name > IP_OPTION_MAX))
+ if ((option_name < IP_TOS) || (option_name > IP_OPTION_MAX))
{
/* Error, one or more invalid arguments. */
@@ -6507,9 +6774,70 @@ ULONG physical_addr_lsw;
switch (option_name)
{
+ case IP_TOS:
+
+ if (option_length != (INT)sizeof(INT))
+ {
+
+ /* Set the socket error if extended socket options enabled. */
+ nx_bsd_set_errno(EINVAL);
+
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+ }
+ else
+ {
+ INT tos_in = *((const INT *)option_value);
+
+ if ((tos_in < 0) || (tos_in > 0xFF))
+ {
+
+ /* Set the socket error if extended socket options enabled. */
+ nx_bsd_set_errno(EINVAL);
+
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+ }
+ else
+ {
+ ULONG type_of_service = (ULONG)tos_in << 16;
+
+ if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
+ {
+ bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_type_of_service = type_of_service;
+ }
+ else if (bsd_socket_ptr -> nx_bsd_socket_udp_socket)
+ {
+ bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_type_of_service = type_of_service;
+ }
+ else
+ {
+
+ /* Raw sockets do not support IP_TOS. */
+ nx_bsd_set_errno(ENOPROTOOPT);
+
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+ }
+ }
+ }
+
+ break;
+
case SO_BROADCAST:
/* This is the default behavior of NetX. All sockets have this capability. */
+ if (*((INT *)option_value) == 0)
+ {
+
+ nx_bsd_set_errno(EINVAL);
+
+ /* Return an error status. */
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+
+ return NX_SOC_ERROR;
+ }
+
break;
case SO_KEEPALIVE:
@@ -6563,10 +6891,56 @@ ULONG physical_addr_lsw;
break;
case SO_LINGER:
+ {
+ INT l_linger_val;
+
+ /* Only available to TCP BSD sockets. */
+ if (!bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
+ {
+
+ /* Set the socket error if extended socket options enabled. */
+ nx_bsd_set_errno(ENOPROTOOPT);
+
+ /* Return an error status. */
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+ }
- /* The Linger socket option is not supported in NetX Duo BSD. */
+ if (option_length != (INT)sizeof(struct nx_bsd_linger))
+ {
+
+ /* Set the socket error if extended socket options enabled. */
+ nx_bsd_set_errno(EINVAL);
- return NX_NOT_ENABLED;
+ /* Return an error status. */
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+ }
+
+ l_linger_val = (*((const struct nx_bsd_linger *)option_value)).l_linger;
+ if (l_linger_val < 0)
+ {
+
+ /* Negative linger time is invalid. */
+ nx_bsd_set_errno(EINVAL);
+
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+ }
+
+ if ((*((const struct nx_bsd_linger *)option_value)).l_onoff)
+ {
+ bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_LINGER;
+ }
+ else
+ {
+ bsd_socket_ptr -> nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_LINGER);
+ }
+ bsd_socket_ptr -> nx_bsd_option_linger.l_onoff = (*((const struct nx_bsd_linger *)option_value)).l_onoff;
+ bsd_socket_ptr -> nx_bsd_option_linger.l_linger = l_linger_val;
+
+ break;
+ }
case SO_SNDTIMEO:
@@ -6640,13 +7014,24 @@ ULONG physical_addr_lsw;
case TCP_NODELAY:
/* This is the default behavior of NetX. All sockets have this attribute. */
+ if (*((INT *)option_value) == 0)
+ {
+
+ nx_bsd_set_errno(EINVAL);
+
+ /* Return an error status. */
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+
+ return NX_SOC_ERROR;
+ }
break;
+ case IP_TTL:
case IP_MULTICAST_TTL:
/* Validate the option length. */
- if(option_length != sizeof(UCHAR) && option_length != sizeof(INT))
+ if ((option_length != (INT)sizeof(UCHAR)) && (option_length != (INT)sizeof(INT)))
{
/* Set the socket error if extended socket options enabled. */
@@ -6667,24 +7052,68 @@ ULONG physical_addr_lsw;
return NX_SOC_ERROR;
}
- /* Make sure socket is UDP type. */
- if(bsd_socket_ptr -> nx_bsd_socket_udp_socket == NX_NULL)
+ /* When option_length == sizeof(INT), validate range 0..255. */
+ if (option_length == (INT)sizeof(INT))
{
- /* Set the socket error if extended socket options enabled. */
- nx_bsd_set_errno(ENOPROTOOPT);
+ INT ttl_in = *(const INT *)option_value;
- NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
- return NX_SOC_ERROR;
+ if ((ttl_in < 0) || (ttl_in > 0xFF))
+ {
+
+ /* Set the socket error if extended socket options enabled. */
+ nx_bsd_set_errno(EINVAL);
+
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+ }
}
- /* Set the TTL value. */
- if (option_length == sizeof(UCHAR))
+ /* Socket is UDP type. */
+ if (bsd_socket_ptr -> nx_bsd_socket_udp_socket != NX_NULL)
{
- bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_time_to_live = *(UCHAR*)option_value;
+
+ /* Set the TTL value. */
+ if (option_length == (INT)sizeof(UCHAR))
+ {
+ bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_time_to_live = *(const UCHAR *)option_value;
+ }
+ else
+ {
+ bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_time_to_live = (UCHAR)(*(const INT *)option_value);
+ }
+ }
+ /* Socket is TCP type. */
+ else if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket != NX_NULL)
+ {
+
+ if (option_name == IP_MULTICAST_TTL)
+ {
+
+ /* Set the socket error if extended socket options enabled. */
+ nx_bsd_set_errno(ENOPROTOOPT);
+
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+ }
+
+ /* Set the TTL value. */
+ if (option_length == (INT)sizeof(UCHAR))
+ {
+ bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_time_to_live = *(const UCHAR *)option_value;
+ }
+ else
+ {
+ bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_time_to_live = (UCHAR)(*(const INT *)option_value);
+ }
}
else
{
- bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_time_to_live = (UCHAR)(*(INT*)option_value);
+
+ /* Raw sockets do not support IP_TTL/IP_MULTICAST_TTL. */
+ nx_bsd_set_errno(ENOPROTOOPT);
+
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
}
break;
@@ -6698,6 +7127,13 @@ ULONG physical_addr_lsw;
/* This is not supported yet. */
+ /* Set the socket error if extended socket options enabled. */
+ nx_bsd_set_errno(ENOPROTOOPT);
+
+ /* Return an error status. */
+ NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
+ return NX_SOC_ERROR;
+
break;
#if defined(NX_BSD_RAW_SUPPORT) && defined(NX_ENABLE_VLAN)
@@ -7791,6 +8227,21 @@ INT ret;
nx_bsd_socket_array[i].nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
nx_bsd_socket_array[i].nx_bsd_socket_received_packet_count++;
+ /* Check for urgent data (URG bit) now, while the packet is still
+ accessible. The exceptfds scan runs after readfds and would miss
+ this packet because nx_tcp_socket_receive() has already removed it
+ from the TCP receive queue. */
+ if (exceptfds && NX_BSD_FD_ISSET(i + NX_BSD_SOCKFD_START, exceptfds))
+ {
+ NX_TCP_HEADER *tcp_header_ptr;
+
+ tcp_header_ptr = (NX_TCP_HEADER *)packet_ptr -> nx_packet_prepend_ptr;
+ if (tcp_header_ptr -> nx_tcp_header_word_3 & NX_TCP_URG_BIT)
+ {
+ NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &exceptfds_found);
+ }
+ }
+
/* Add this socket to the read ready list. */
NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
}
@@ -7839,16 +8290,17 @@ INT ret;
/* Yes, decrement the number of read selectors left to search for. */
writefds_left--;
- /* Is this BSD socket in use? */
+ /* Is this BSD socket not in use? */
if (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
{
- /* Yes, add this socket to the write ready list. */
+ /* Closed/unallocated descriptor: report as writable. */
NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &writefds_found);
}
- /* Check to see if there is a connection request pending. */
- else if (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_REQUEST)
+ /* Check to see if there is a connection request pending on a client socket. */
+ else if ((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_REQUEST) &&
+ !(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET))
{
/* Yes, add this socket to the write ready list. */
@@ -7861,6 +8313,21 @@ INT ret;
NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &writefds_found);
}
+ /* Is this a TCP socket that is connected? */
+ else if ((nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket) &&
+ (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED))
+ {
+
+ /* Yes, add this socket to the write ready list. */
+ NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &writefds_found);
+ }
+ /* Is this BSD socket bound? */
+ else if (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND)
+ {
+
+ /* Yes, add this socket to the write ready list. */
+ NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &writefds_found);
+ }
}
}
@@ -7972,6 +8439,12 @@ INT ret;
This happens if the wait option is set to zero. */
if (status == TX_NO_EVENTS)
{
+ if(readfds)
+ NX_BSD_FD_ZERO(readfds);
+ if(writefds)
+ NX_BSD_FD_ZERO(writefds);
+ if(exceptfds)
+ NX_BSD_FD_ZERO(exceptfds);
/* Determine if the effected sockets are non blocking (zero ticks for the wait option). */
if (ticks == 0)
@@ -8086,6 +8559,38 @@ UINT bsd_socket_index;
}
+
+static VOID nx_bsd_tcp_exception_notify(NX_TCP_SOCKET *socket_ptr)
+{
+UINT bsd_socket_index;
+
+ /* Figure out what BSD socket this is. */
+ bsd_socket_index = (UINT) socket_ptr -> nx_tcp_socket_reserved_ptr;
+
+ /* Determine if this is a good index into the BSD socket array. */
+ if (bsd_socket_index >= NX_BSD_MAX_SOCKETS)
+ {
+
+ /* Bad socket index... simply return! */
+ return;
+ }
+
+ /* Now check if the socket may have been released (e.g. socket closed) while
+ waiting for the mutex. */
+ if( socket_ptr -> nx_tcp_socket_id == 0 )
+ {
+
+ return;
+ }
+
+ /* Check the suspended socket list for one ready to receive or send packets. */
+ nx_bsd_select_wakeup(bsd_socket_index, FDSET_EXCEPTION);
+
+
+ return;
+}
+
+
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
diff --git a/addons/BSD/nxd_bsd.h b/addons/BSD/nxd_bsd.h
index a35fee4d..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
@@ -300,6 +301,7 @@ extern "C" {
#define AF_INET 2 /* IPv4 socket (UDP, TCP, etc) */
#define AF_INET6 3 /* IPv6 socket (UDP, TCP, etc) */
#define AF_PACKET 4 /* Raw Packet type (Link Layer packets) */
+#define AF_MAX AF_PACKET
/* Protocol families, same as address families. */
#define PF_INET AF_INET
@@ -570,6 +572,8 @@ extern "C" {
/* This second set of socket options take the socket level (category) IPPROTO_IP. */
+#define IP_TOS 25 /* Type Of Service */
+#define IP_TTL 26 /* Specify the TTL value. */
#define IP_MULTICAST_IF 27 /* Specify outgoing multicast interface */
#define IP_MULTICAST_TTL 28 /* Specify the TTL value to use for outgoing multicast packet. */
#define IP_MULTICAST_LOOP 29 /* Whether or not receive the outgoing multicast packet, loopbacloopbackk mode. */
@@ -960,6 +964,8 @@ typedef struct NX_BSD_SOCKET_STRUCT
INT nx_bsd_option_linger_time;
UINT nx_bsd_option_linger_time_closed;
UINT nx_bsd_option_linger_start_close;
+ struct nx_bsd_linger
+ nx_bsd_option_linger;
UINT nx_bsd_socket_time_wait_remaining;
ULONG nx_bsd_option_receive_timeout;
ULONG nx_bsd_option_send_timeout;
@@ -1009,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);