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 | |
| 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')
| -rw-r--r-- | addons/BSD/nxd_bsd.c | 579 | ||||
| -rw-r--r-- | addons/BSD/nxd_bsd.h | 7 | ||||
| -rw-r--r-- | addons/ftp/nxd_ftp_server.c | 163 | ||||
| -rw-r--r-- | addons/http/nxd_http_server.c | 2 |
4 files changed, 642 insertions, 109 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); diff --git a/addons/ftp/nxd_ftp_server.c b/addons/ftp/nxd_ftp_server.c index 0075f1f6..a6d02d29 100644 --- a/addons/ftp/nxd_ftp_server.c +++ b/addons/ftp/nxd_ftp_server.c @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Sonnet 4.6). /**************************************************************************/ @@ -81,7 +82,8 @@ NX_CALLER_CHECKING_EXTERNS #define NX_FTP_CODE_BAD_NAME "553" /* Requested action not taken, File name not allowed. */ static VOID _nx_ftp_server_number_to_ascii(UCHAR *buffer_ptr, UINT buffer_size, UINT number, UCHAR pad); - +static VOID _nx_ftp_server_logout_client(NX_FTP_SERVER *ftp_server_ptr, NX_FTP_CLIENT_REQUEST *client_request_ptr); + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -1445,6 +1447,7 @@ ULONG events; /* nx_tcp_socket_transmit_configure Configure data transer socket */ /* _nx_utility_uint_to_string Convert number to string */ /* _nx_ftp_server_data_socket_cleanup Clean up data socket */ +/* _nx_ftp_server_logout_client Logout the client */ /* */ /* CALLED BY */ /* */ @@ -1720,41 +1723,8 @@ ULONG block_size; /* Increment the number of disconnection requests. */ ftp_server_ptr -> nx_ftp_server_disconnection_requests++; - /* Check if this client login. */ - if (client_req_ptr -> nx_ftp_client_request_login) - { - - /* Call the logout function. */ - -#ifndef NX_DISABLE_IPV4 - /* Does this server have an IPv4 login function? */ - if (ftp_server_ptr -> nx_ftp_logout_ipv4) - { - - /* Call the logout which takes IPv4 address input. */ - (ftp_server_ptr -> nx_ftp_logout_ipv4)(ftp_server_ptr, - client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip.nxd_ip_address.v4, - client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_port, - client_req_ptr -> nx_ftp_client_request_username, - client_req_ptr -> nx_ftp_client_request_password, NX_NULL); - } -#endif /* NX_DISABLE_IPV4 */ - if (ftp_server_ptr -> nx_ftp_logout) - { - - /* Call the 'duo' logout function which takes IPv6 or IPv4 IP addresses. */ - (ftp_server_ptr -> nx_ftp_logout)(ftp_server_ptr, &(client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip), - client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_port, - client_req_ptr -> nx_ftp_client_request_username, - client_req_ptr -> nx_ftp_client_request_password, NX_NULL); - } - - /* Set the login as FALSE. */ - client_req_ptr -> nx_ftp_client_request_login = NX_FALSE; - } - - /* Clear authentication. */ - client_req_ptr -> nx_ftp_client_request_authenticated = NX_FALSE; + /* Logout the client. */ + _nx_ftp_server_logout_client(ftp_server_ptr, client_req_ptr); /* Now send a successful response to the client. */ _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, @@ -4554,6 +4524,7 @@ NX_FTP_SERVER *server_ptr; /* fx_file_close Close file */ /* nx_ftp_packet_allocate Allocate a packet */ /* _nx_ftp_server_data_socket_cleanup Clean up data socket */ +/* _nx_ftp_server_logout_client Logout the client */ /* */ /* CALLED BY */ /* */ @@ -5133,6 +5104,7 @@ NX_FTP_SERVER *server_ptr; /* nx_tcp_server_socket_unaccept Unaccept server connection */ /* nx_tcp_socket_disconnect Disconnect socket */ /* _nx_ftp_server_data_socket_cleanup Clean up data socket */ +/* _nx_ftp_server_logout_client Logout the client */ /* */ /* CALLED BY */ /* */ @@ -5187,6 +5159,9 @@ NX_FTP_CLIENT_REQUEST *client_req_ptr; /* Reset the block bytes. */ client_req_ptr -> nx_ftp_client_request_block_bytes = 0; + /* Logout the client. */ + _nx_ftp_server_logout_client(ftp_server_ptr, client_req_ptr); + /* Now disconnect the command socket. */ nx_tcp_socket_disconnect(&(client_req_ptr -> nx_ftp_client_request_control_socket), NX_NO_WAIT); @@ -5324,9 +5299,6 @@ NX_FTP_CLIENT_REQUEST *client_req_ptr; /* Increment the number of disconnection requests. */ ftp_server_ptr -> nx_ftp_server_disconnection_requests++; - /* Clear authentication. */ - client_req_ptr -> nx_ftp_client_request_authenticated = NX_FALSE; - /* Disable the client request activity timeout. */ client_req_ptr -> nx_ftp_client_request_activity_timeout = 0; @@ -5344,38 +5316,8 @@ NX_FTP_CLIENT_REQUEST *client_req_ptr; /* Reset the block bytes. */ client_req_ptr -> nx_ftp_client_request_block_bytes = 0; - /* Check if this client login. */ - if (client_req_ptr -> nx_ftp_client_request_login) - { - - /* Call the logout function. */ - -#ifndef NX_DISABLE_IPV4 - /* Does this server have an IPv4 login function? */ - if (ftp_server_ptr -> nx_ftp_logout_ipv4) - { - - /* Call the logout which takes IPv4 address input. */ - (ftp_server_ptr -> nx_ftp_logout_ipv4)(ftp_server_ptr, - client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip.nxd_ip_address.v4, - client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_port, - client_req_ptr -> nx_ftp_client_request_username, - client_req_ptr -> nx_ftp_client_request_password, NX_NULL); - } -#endif /* NX_DISABLE_IPV4 */ - if (ftp_server_ptr -> nx_ftp_logout) - { - - /* Call the 'duo' logout function which takes IPv6 or IPv4 IP addresses. */ - (ftp_server_ptr -> nx_ftp_logout)(ftp_server_ptr, &(client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip), - client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_port, - client_req_ptr -> nx_ftp_client_request_username, - client_req_ptr -> nx_ftp_client_request_password, NX_NULL); - } - - /* Set the login as FALSE. */ - client_req_ptr -> nx_ftp_client_request_login = NX_FALSE; - } + /* Logout the client. */ + _nx_ftp_server_logout_client(ftp_server_ptr, client_req_ptr); /* Now disconnect the command socket. */ nx_tcp_socket_disconnect(&(client_req_ptr -> nx_ftp_client_request_control_socket), NX_FTP_SERVER_TIMEOUT); @@ -6498,6 +6440,85 @@ UINT size; } } +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ftp_server_logout_client PORTABLE C */ +/* 6.4.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou */ +/* Valentin Batz */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function logs out the client if it was previously logged in */ +/* and resets the authenticated flag so the next connection on this */ +/* socket slot must perform a fresh login. */ +/* */ +/* INPUT */ +/* */ +/* ftp_server_ptr Pointer to FTP server */ +/* client_request_ptr Pointer to FTP client */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* _nx_ftp_server_control_disconnect_processing */ +/* Disconnect processing */ +/* _nx_ftp_server_command_process */ +/* QUIT command */ +/* _nx_ftp_server_timeout_processing */ +/* Timeout processing */ +/* */ +/**************************************************************************/ + +static VOID _nx_ftp_server_logout_client(NX_FTP_SERVER *ftp_server_ptr, NX_FTP_CLIENT_REQUEST *client_request_ptr) +{ + /* Check if this client login. */ + if (client_request_ptr -> nx_ftp_client_request_login) + { + + /* Call the logout function. */ + +#ifndef NX_DISABLE_IPV4 + /* Does this server have an IPv4 logout function? */ + if (ftp_server_ptr -> nx_ftp_logout_ipv4) + { + + /* Call the logout which takes IPv4 address input. */ + (ftp_server_ptr -> nx_ftp_logout_ipv4)(ftp_server_ptr, + client_request_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip.nxd_ip_address.v4, + client_request_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_port, + client_request_ptr -> nx_ftp_client_request_username, + client_request_ptr -> nx_ftp_client_request_password, NX_NULL); + } +#endif /* NX_DISABLE_IPV4 */ + if (ftp_server_ptr -> nx_ftp_logout) + { + + /* Call the 'duo' logout function which takes IPv6 or IPv4 IP addresses. */ + (ftp_server_ptr -> nx_ftp_logout)(ftp_server_ptr, &(client_request_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_ip), + client_request_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_port, + client_request_ptr -> nx_ftp_client_request_username, + client_request_ptr -> nx_ftp_client_request_password, NX_NULL); + } + + /* Clear the login flag. */ + client_request_ptr -> nx_ftp_client_request_login = NX_FALSE; + } + + /* Always clear authenticated so the next connection on this socket slot + must perform a fresh USER/PASS exchange. */ + client_request_ptr -> nx_ftp_client_request_authenticated = NX_FALSE; +} /**************************************************************************/ /* */ diff --git a/addons/http/nxd_http_server.c b/addons/http/nxd_http_server.c index f11ee62a..2eb10f49 100644 --- a/addons/http/nxd_http_server.c +++ b/addons/http/nxd_http_server.c @@ -3838,7 +3838,7 @@ UINT temp_realm_length = 0; "NetX HTTP File Open Failed", sizeof("NetX HTTP File Open Failed") - 1, NX_NULL, 0); /* Error, return to caller. */ - goto put_process_end; + return; } |
