diff options
| author | Frédéric Desbiens <[email protected]> | 2026-06-08 10:03:52 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-06-08 10:03:52 +0200 |
| commit | 1a0e9e43a03e37ddecfb6b49e9b078d6e1803d05 (patch) | |
| tree | c60ec41b4ff4fd2d7566c505cbdd423ceddd65f3 /addons/BSD/nxd_bsd.c | |
| parent | 8b6e03ac30ab688bec02c69d42f2304b7f72a202 (diff) | |
| parent | 4d88828b06d164a5b7e82152395a92254abcd6e4 (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/nxd_bsd.c')
| -rw-r--r-- | addons/BSD/nxd_bsd.c | 579 |
1 files changed, 542 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 */ |
