1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** BSD 4.3 Socket API Compatible Interface to NetX Duo                   */
16 /**                                                                       */
17 /**************************************************************************/
18 /**************************************************************************/
19 
20 
21 /* Include necessary files.  */
22 #include "nx_api.h"
23 #include "nx_packet.h"
24 #include "nx_tcp.h"
25 #include "nx_ip.h"
26 
27 #include "nx_ipv6.h"
28 #include "nx_ipv4.h"
29 #include "nxd_bsd.h"
30 
31 #ifdef NX_BSD_ENABLE_DNS
32 #include "nxd_dns.h"
33 #endif
34 
35 
36 #include "nx_udp.h"
37 #include "nx_igmp.h"
38 #include "nx_system.h"
39 #ifdef FEATURE_NX_IPV6
40 #include "nx_icmpv6.h"
41 #endif
42 #include "tx_timer.h"
43 
44 /* Define a NetX packet pool pointer for BSD use.  */
45 
46 NX_PACKET_POOL          *nx_bsd_default_packet_pool;
47 
48 
49 /* Define the default IP instance for BSD use.   */
50 
51 NX_IP                   *nx_bsd_default_ip;
52 
53 
54 /* Define the single mutex protection for the BSD layer calls.  */
55 
56 TX_MUTEX                *nx_bsd_protection_ptr;
57 
58 
59 /* Define IP fast periodic timer entry. */
60 VOID                    (*nx_bsd_ip_fast_periodic_timer_entry)(ULONG id);
61 
62 /* Define BSD system clock time. The precision depends on _nx_ip_fast_timer_rate. */
63 ULONG                   nx_bsd_system_clock;
64 
65 /* Define BSD system clock timer rate. */
66 ULONG                   nx_bsd_timer_rate;
67 
68 /* Define the event flag group for notifying threads suspended on BSD sockets to wakeup.  */
69 
70 TX_EVENT_FLAGS_GROUP    nx_bsd_events;
71 
72 
73 /* Define the array of BSD managed sockets.  */
74 
75 NX_BSD_SOCKET           nx_bsd_socket_array[NX_BSD_MAX_SOCKETS];
76 
77 /* Define the raw socket protocol hash table. */
78 
79 NX_BSD_SOCKET           *nx_bsd_socket_raw_protocol_table[NX_BSD_SOCKET_RAW_PROTOCOL_TABLE_SIZE];
80 
81 /* Create some buffer space for number string conversions. */
82 #define                 NX_BSD_URL_BUFSIZE  18
83 CHAR                    nx_bsd_url_buffer[NX_BSD_URL_BUFSIZE];
84 
85 /* Define the search index for the BSD array.  */
86 
87 UINT                    nx_bsd_socket_array_index;
88 
89 
90 /* Define the block pool that will be used to dynamically allocate either NetX UDP or TCP sockets.  */
91 
92 TX_BLOCK_POOL           nx_bsd_socket_block_pool;
93 
94 /* Define the memory area for the socket block pool... use TCP socket size, since it is the larger.  */
95 
96 static ULONG            nx_bsd_socket_pool_memory[NX_BSD_MAX_SOCKETS * (sizeof(NX_TCP_SOCKET) + sizeof(VOID *)) / sizeof(ULONG)];
97 
98 /* Define the block pool that will be used to dynamically allocate addrinfo struct. */
99 
100 TX_BLOCK_POOL           nx_bsd_addrinfo_block_pool;
101 
102 /* Define the memory area for addrinfo pool. sizeof(addrinfo) is the MAX of:
103  * {sizeof(addrinfo)== 32, sizeof(sockaddr_in) == 16, or sizeof(sockaddr_in6)} = 28.
104  * Every address may be  mapped to 3 socktypes, SOCK_STREAM, SOCK_DGRAM and SOCK_RAW,
105  * 3 blocks for addrinfo) + 1 block for IP adddress = 4 blocks */
106 
107 static ULONG            nx_bsd_addrinfo_pool_memory[(NX_BSD_IPV4_ADDR_MAX_NUM + NX_BSD_IPV6_ADDR_MAX_NUM) * 4
108                                                     *(sizeof(struct nx_bsd_addrinfo) + sizeof(VOID *)) / sizeof(ULONG)];
109 
110 #ifdef NX_BSD_ENABLE_DNS
111 
112 /* The global DNS client instance. */
113 extern NX_DNS *_nx_dns_instance_ptr;
114 
115 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
116 /* Define the block pool that will be used to dynamically allocate canonical name buffer. */
117 TX_BLOCK_POOL           nx_bsd_cname_block_pool;
118 
119 /* Here we just support a CNAME per IP address. */
120 static ULONG            nx_bsd_cname_pool_memory[(NX_BSD_IPV4_ADDR_MAX_NUM + NX_BSD_IPV6_ADDR_MAX_NUM) *
121                                                           (NX_DNS_NAME_MAX + 1) / sizeof(ULONG)];
122 #endif /* NX_DNS_ENABLE_EXTENDED_RR_TYPES */
123 #endif /* NX_BSD_ENABLE_DNS */
124 
125 /* Buffer used to store IP address get from DNS. */
126 static ULONG           nx_bsd_ipv4_addr_buffer[NX_BSD_IPV4_ADDR_PER_HOST];
127 static ULONG           nx_bsd_ipv6_addr_buffer[NX_BSD_IPV6_ADDR_PER_HOST * 4];
128 
129 /* Utility character type functions*/
130 static UINT nx_bsd_isspace(UCHAR c);
131 static UINT nx_bsd_islower(UCHAR c);
132 static UINT nx_bsd_isdigit(UCHAR c);
133 static UINT nx_bsd_isxdigit(UCHAR c);
134 
135 /* Standard BSD callback functions to register with NetX Duo. */
136 
137 static VOID  nx_bsd_tcp_receive_notify(NX_TCP_SOCKET *socket_ptr);
138 static VOID  nx_bsd_tcp_socket_disconnect_notify(NX_TCP_SOCKET *socket_ptr);
139 static VOID  nx_bsd_udp_receive_notify(NX_UDP_SOCKET *socket_ptr);
140 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
141 static UINT  nx_bsd_raw_packet_filter(NX_IP *ip_ptr, ULONG protocol, NX_PACKET *packet_ptr);
142 #ifdef FEATURE_NX_IPV6
143 static VOID  _nxd_bsd_swap_ipv6_extension_headers(NX_PACKET *packet_ptr, UCHAR header_type);
144 #endif /* FEATURE_NX_IPV6 */
145 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
146 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
147 static VOID  nx_bsd_tcp_establish_notify(NX_TCP_SOCKET *socket_ptr);
148 #endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */
149 static VOID  nx_bsd_select_wakeup(UINT sock_id, UINT fdsets);
150 static VOID  nx_bsd_set_error_code(NX_BSD_SOCKET *bsd_socket_ptr, UINT status_code);
151 static VOID  nx_bsd_udp_packet_received(INT sockID, NX_PACKET *packet_ptr);
152 static UINT  nx_bsd_tcp_syn_received_notify(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr);
153 static INT   nx_bsd_tcp_create_listen_socket(INT master_sockid, INT backlog);
154 static VOID  nx_bsd_tcp_pending_connection(UINT local_port, NX_TCP_SOCKET *socket_ptr);
155 static INT   nx_bsd_find_interface_by_source_addr(UINT addr_family, ULONG* ip_addr);
156 #ifndef NX_DISABLE_IPV4
157 static VOID  _nxd_bsd_ipv4_packet_send(NX_PACKET *packet_ptr);
158 #endif /* NX_DISABLE_IPV4 */
159 static INT   nx_bsd_send_internal(INT sockID, const CHAR *msg, INT msgLength, INT flags,
160                                   NXD_ADDRESS *dst_address, USHORT dst_port, UINT local_interface_index);
161 
162 #ifdef FEATURE_NX_IPV6
163 static VOID  _nxd_bsd_ipv6_packet_send(NX_PACKET *packet_ptr, ULONG *src_addr, ULONG *dest_addr);
164 #endif /* FEATURE_NX_IPV6 */
165 
166 static INT   inet_ntoa_internal(const VOID *src, CHAR *dst, ULONG dst_size);
167 static INT   bsd_string_to_number(const CHAR *string, UINT *number);
168 static ULONG _nx_bsd_string_length(CHAR * string);
169 
170 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
171 static INT   nx_bsd_pppoe_internal_sendto(NX_BSD_SOCKET *bsd_socket_ptr, CHAR *msg, INT msgLength,
172                                           INT flags,  struct nx_bsd_sockaddr* destAddr, INT destAddrLen);
173 static UINT  nx_bsd_socket_create_id = 0;
174 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
175 
176 #ifdef NX_BSD_RAW_SUPPORT
177 static INT   _nx_bsd_hardware_internal_sendto(NX_BSD_SOCKET *bsd_socket_ptr, CHAR *msg, INT msgLength,
178                                               INT flags,  struct nx_bsd_sockaddr* destAddr, INT destAddrLen);
179 static VOID  _nx_bsd_hardware_packet_received(NX_PACKET *packet_ptr, UCHAR *consumed);
180 #endif /* NX_BSD_RAW_SUPPORT */
181 static VOID  _nx_bsd_fast_periodic_timer_entry(ULONG id);
182 
183 #ifndef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
184 TX_THREAD               nx_bsd_task_thread;
185 static VOID             nx_bsd_thread_entry(ULONG info);
186 #else
187 static TX_TIMER         nx_bsd_timer;
188 static VOID             nx_bsd_timer_entry(ULONG info);
189 #endif
190 UINT  bsd_number_convert(UINT number, CHAR *string, ULONG buffer_len, UINT base);
191 VOID  nx_bsd_socket_timed_wait_callback(NX_TCP_SOCKET *tcp_socket_ptr);
192 
193 #define FDSET_READ       1
194 #define FDSET_WRITE      2
195 #define FDSET_EXCEPTION  4
196 
197 extern TX_THREAD       *_tx_thread_current_ptr;
198 
199 static ULONG  _nx_bsd_serv_list_len;
200 static struct NX_BSD_SERVICE_LIST  *_nx_bsd_serv_list_ptr;
201 
202 
203 /**************************************************************************/
204 /*                                                                        */
205 /*  FUNCTION                                               RELEASE        */
206 /*                                                                        */
207 /*    bsd_initialize                                      PORTABLE C      */
208 /*                                                           6.3.0        */
209 /*  AUTHOR                                                                */
210 /*                                                                        */
211 /*    Yuxin Zhou, Microsoft Corporation                                   */
212 /*                                                                        */
213 /*  DESCRIPTION                                                           */
214 /*                                                                        */
215 /*    This function sets up all data structures and NetX, and ThreadX     */
216 /*    resources needed by the BSD compatibility layer. It is recommended  */
217 /*    to call this routine from tx_application_define.                    */
218 /*                                                                        */
219 /*  INPUTS                                                                */
220 /*                                                                        */
221 /*    *default_ip                           NX_IP created for BSD API     */
222 /*    *default_pool                         Packet Pool used by BSD API   */
223 /*    *bsd_thread_stack_area                Stack memory pointer for the  */
224 /*                                            BSD thread stack space      */
225 /*     bsd_thread_stack_size                Size of thread stack          */
226 /*     bsd_thread_priority                  BSD thread priority           */
227 /*                                                                        */
228 /*  OUTPUT                                                                */
229 /*                                                                        */
230 /*    NX_SUCCESS                            Successful completion         */
231 /*    NX_BSD_BLOCK_POOL_ERROR               Error creating socket block   */
232 /*                                            pool                        */
233 /*    NX_BSD_EVENT_ERROR                    Error creating the event flag */
234 /*                                            group                       */
235 /*    NX_BSD_MUTEX_ERROR                    Error creating mutex          */
236 /*    NX_BSD_ENVIRONMENT_ERROR              Error environment             */
237 /*                                                                        */
238 /*  CALLS                                                                 */
239 /*                                                                        */
240 /*    memset                                Set memory                    */
241 /*    tx_block_pool_create                  Create a block pool           */
242 /*    tx_block_pool_delete                  Delete a block pool           */
243 /*    tx_event_flags_create                 Create event flag group       */
244 /*    tx_mutex_create                       Create protection mutex       */
245 /*    tx_mutex_delete                       Delete protection mutex       */
246 /*                                                                        */
247 /*  CALLED BY                                                             */
248 /*                                                                        */
249 /*    Start-up code                                                       */
250 /*                                                                        */
251 /*  RELEASE HISTORY                                                       */
252 /*                                                                        */
253 /*    DATE              NAME                      DESCRIPTION             */
254 /*                                                                        */
255 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
256 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
257 /*                                            resulting in version 6.1    */
258 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
259 /*                                            used new API/structs naming,*/
260 /*                                            resulting in version 6.3.0  */
261 /*                                                                        */
262 /**************************************************************************/
nx_bsd_initialize(NX_IP * default_ip,NX_PACKET_POOL * default_pool,CHAR * bsd_thread_stack_area,ULONG bsd_thread_stack_size,UINT bsd_thread_priority)263 INT  nx_bsd_initialize(NX_IP *default_ip, NX_PACKET_POOL *default_pool, CHAR *bsd_thread_stack_area,
264                     ULONG bsd_thread_stack_size, UINT bsd_thread_priority)
265 {
266 
267 INT         i;
268 UINT        status;
269 ULONG       info;
270 
271 #ifndef NX_ENABLE_EXTENDED_NOTIFY_SUPPORT
272 
273     /* Error, return the error message.  */
274     /* BSD doesn't work with out NX_ENABLE_EXTENDED_NOTIFY_SUPPORT option. */
275     NX_BSD_ERROR(NX_BSD_ENVIRONMENT_ERROR, __LINE__);
276     return(NX_BSD_ENVIRONMENT_ERROR);
277 #endif /* NX_ENABLE_EXTENDED_NOTIFY_SUPPORT */
278 
279     /* Create a block pool for dynamically allocating sockets.  */
280     status =  tx_block_pool_create(&nx_bsd_socket_block_pool, "NetX BSD Socket Block Pool", sizeof(NX_TCP_SOCKET),
281                                    nx_bsd_socket_pool_memory, sizeof(nx_bsd_socket_pool_memory));
282 
283     /* Determine if the pool was created.  */
284     if (status)
285     {
286 
287         /* Error, return the error message.  */
288         NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
289         return(NX_BSD_BLOCK_POOL_ERROR);
290     }
291 
292     /* Create a block pool for dynamically allocating addrinfo. */
293     status = tx_block_pool_create(&nx_bsd_addrinfo_block_pool, "NetX BSD Addrinfo Block Pool", sizeof(struct nx_bsd_addrinfo),
294                                   nx_bsd_addrinfo_pool_memory, sizeof(nx_bsd_addrinfo_pool_memory));
295 
296     /* Determine if the pool was created. */
297     if(status)
298     {
299 
300         /* Error, return the error messafe. */
301         NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
302 
303         /* Delete the block pool.  */
304         tx_block_pool_delete(&nx_bsd_socket_block_pool);
305         return(NX_BSD_BLOCK_POOL_ERROR);
306 
307     }
308 
309 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
310     /* Create a block pool for dynamically allocating canonical name buffer. */
311     status = tx_block_pool_create(&nx_bsd_cname_block_pool, "NetX BSD CNAME Block Pool", (NX_DNS_NAME_MAX + 1),
312                                   nx_bsd_cname_pool_memory, sizeof(nx_bsd_cname_pool_memory));
313 
314     /* Determine if the pool was created. */
315     if(status)
316     {
317 
318         /* Error, return the error messafe. */
319         NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
320 
321         /* Delete the block pool.  */
322         tx_block_pool_delete(&nx_bsd_socket_block_pool);
323         tx_block_pool_delete(&nx_bsd_addrinfo_block_pool);
324         return(NX_BSD_BLOCK_POOL_ERROR);
325 
326     }
327 #endif
328 
329     nx_bsd_protection_ptr = &default_ip -> nx_ip_protection;
330 
331     /* Create the BSD event flag group.   */
332     status =  tx_event_flags_create(&nx_bsd_events, "NetX BSD Events");
333 
334     /* Check the return status.  */
335     if (status)
336     {
337         /* Delete the block pool.  */
338         tx_block_pool_delete(&nx_bsd_socket_block_pool);
339         tx_block_pool_delete(&nx_bsd_addrinfo_block_pool);
340 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
341         tx_block_pool_delete(&nx_bsd_cname_block_pool);
342 #endif
343 
344         /* Error present, return error code.  */
345         NX_BSD_ERROR(NX_BSD_EVENT_ERROR, __LINE__);
346         return(NX_BSD_EVENT_ERROR);
347     }
348 
349     /* Set the array index to 0.  */
350     nx_bsd_socket_array_index =  0;
351 
352     /* Loop through the BSD socket array and clear it out!  */
353     for (i = 0; i < NX_BSD_MAX_SOCKETS; i++)
354     {
355 
356         /* Clear the BSD socket structure.  */
357         memset((VOID*) &nx_bsd_socket_array[i], 0, sizeof(NX_BSD_SOCKET));
358     }
359 
360     /* Save the IP instance and NX_PACKET_POOL for BSD Socket API.  */
361     nx_bsd_default_ip =           default_ip;
362     nx_bsd_default_packet_pool =  default_pool;
363 
364 
365     if ((bsd_thread_stack_area == TX_NULL) || (bsd_thread_stack_size == 0))
366     {
367         /* Return error.  */
368         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
369         return(NX_SOC_ERROR);
370     }
371 
372 #ifndef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
373     /* Create a thread for BSD socket features requiring periodic tasks.  */
374     info = 0 ;
375     status = tx_thread_create(&nx_bsd_task_thread, "BSD thread task", nx_bsd_thread_entry, info,
376                               bsd_thread_stack_area, bsd_thread_stack_size, bsd_thread_priority,
377                               bsd_thread_priority, 1, TX_AUTO_START);
378 
379      if (status != TX_SUCCESS)
380      {
381          /* Delete the event flag group.  */
382          tx_event_flags_delete(&nx_bsd_events);
383 
384          /* Delete the block pool.  */
385          tx_block_pool_delete(&nx_bsd_socket_block_pool);
386          tx_block_pool_delete(&nx_bsd_addrinfo_block_pool);
387 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
388         tx_block_pool_delete(&nx_bsd_cname_block_pool);
389 #endif
390 
391          /* Error, return the error message.  */
392          NX_BSD_ERROR(NX_BSD_THREAD_ERROR, __LINE__);
393 
394          /* Return an error.  */
395          return(NX_IP_INTERNAL_ERROR);
396      }
397 #else
398 
399     info = 0 ;
400 
401     /* Create a one shot timer. Do not activate it. We will use it if
402        a socket being disconnected is NOT enabled for REUSEADDR socket option. */
403     status = tx_timer_create(&nx_bsd_timer, "BSD Timer",
404                              nx_bsd_timer_entry, info,
405                              NX_BSD_TIMER_RATE, NX_BSD_TIMER_RATE, TX_AUTO_START);
406 
407     if (status != TX_SUCCESS)
408     {
409 
410         /* Delete the event flag group.  */
411         tx_event_flags_delete(&nx_bsd_events);
412 
413         /* Delete the block pool.  */
414         tx_block_pool_delete(&nx_bsd_socket_block_pool);
415         tx_block_pool_delete(&nx_bsd_addrinfo_block_pool);
416 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
417         tx_block_pool_delete(&nx_bsd_cname_block_pool);
418 #endif
419 
420 #ifndef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
421         /* Delete the thread. */
422         tx_thread_delete(&nx_bsd_task_thread);
423 #endif
424         /* Error, return the error message.  */
425         NX_BSD_ERROR(NX_BSD_THREAD_ERROR, __LINE__);
426 
427         /* Return an error.  */
428         return(NX_IP_INTERNAL_ERROR);
429     }
430 #endif
431 
432 #ifdef NX_BSD_RAW_SUPPORT
433     _nx_driver_hardware_packet_received_callback = _nx_bsd_hardware_packet_received;
434 #endif /* NX_BSD_RAW_SUPPORT */
435 
436     /* Calculate BSD system timer rate. */
437     nx_bsd_timer_rate = (NX_IP_PERIODIC_RATE + (NX_IP_FAST_TIMER_RATE - 1)) / NX_IP_FAST_TIMER_RATE;
438 
439     /* Return success!  */
440     return(NX_SOC_OK);
441 }
442 
443 
444 /**************************************************************************/
445 /*                                                                        */
446 /*  FUNCTION                                               RELEASE        */
447 /*                                                                        */
448 /*    nx_bsd_timeout_process                              PORTABLE C      */
449 /*                                                           6.1          */
450 /*  AUTHOR                                                                */
451 /*                                                                        */
452 /*    Yuxin Zhou, Microsoft Corporation                                   */
453 /*                                                                        */
454 /*  DESCRIPTION                                                           */
455 /*                                                                        */
456 /*    This function checks for sockets waiting to make a TCP connection.  */
457 /*                                                                        */
458 /*  INPUT                                                                 */
459 /*                                                                        */
460 /*    None                                                                */
461 /*                                                                        */
462 /*  OUTPUT                                                                */
463 /*                                                                        */
464 /*    None                                                                */
465 /*                                                                        */
466 /*  CALLS                                                                 */
467 /*                                                                        */
468 /*    tx_mutex_get                         Obtain exclusive access to     */
469 /*    tx_mutex_put                         Release exclusive access       */
470 /*    nx_tcp_server_socket_unaccept        Remove socket from listen list */
471 /*    nx_tcp_server_socket_relisten        Restore socket to listening    */
472 /*    nx_tcp_server_socket_accept          Accept to connection request   */
473 /*                                                                        */
474 /*  CALLED BY                                                             */
475 /*                                                                        */
476 /*    ThreadX                                                             */
477 /*                                                                        */
478 /*  RELEASE HISTORY                                                       */
479 /*                                                                        */
480 /*    DATE              NAME                      DESCRIPTION             */
481 /*                                                                        */
482 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
483 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
484 /*                                            resulting in version 6.1    */
485 /*                                                                        */
486 /**************************************************************************/
nx_bsd_timeout_process()487 static VOID nx_bsd_timeout_process()
488 {
489 
490 INT             i;
491 ULONG           status;
492 INT             master_socket_index;
493 NX_BSD_SOCKET  *bsd_socket_ptr;
494 
495 
496    /* Obtain the BSD lock. */
497    status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
498 
499    if(status)
500    {
501        /* Mutex operation failed.  This should be fatal. */
502        return;
503    }
504 
505    for( i = 0; i < NX_BSD_MAX_SOCKETS; i++)
506    {
507 
508        /* Skip the unused sockets. */
509        if(!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
510        {
511 
512            continue;
513        }
514 
515        /* Skip if it is not TCP server socket. */
516        if((nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket == NX_NULL) ||
517           ((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CLIENT)))
518        {
519            continue;
520        }
521 
522        /* Check for sockets trying to make a TCP connection.
523           Detect that the socket state is CLOSED, which is an indication
524           that the attempted connection failed, and we shall signal any pending
525           select on the socket. */
526        if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_INPROGRESS)
527        {
528 
529            /* Is the NetX socket closed? */
530            if(nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket -> nx_tcp_socket_state == NX_TCP_CLOSED)
531            {
532 
533                /* Yes. Set up a local pointer to the BSD socket. */
534                bsd_socket_ptr = &nx_bsd_socket_array[i];
535 
536                /* Is this a secondary socket (passive open)? */
537                if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET)
538                {
539 
540                    /* Yes; Is the socket is connected yet? */
541                    if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED))
542                    {
543 
544                        /* No; Turn off the disconnection_request flag. */
545                        bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_DISCONNECTION_REQUEST);
546 
547                        /* Remove the underlying NetX socket from the listen state. */
548                        nx_tcp_server_socket_unaccept(bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
549 
550                        /* Check if a listen request is queued up for this socket. */
551                        nx_bsd_tcp_pending_connection(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port,
552                                                      bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
553 
554                        /* Relisten on this socket. */
555                        status = nx_tcp_server_socket_relisten(nx_bsd_default_ip,
556                                                               bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port,
557                                                               bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
558                        /* Set the socket to accept the connection. */
559                        nx_tcp_server_socket_accept(bsd_socket_ptr -> nx_bsd_socket_tcp_socket, NX_NO_WAIT);
560 
561                        /* Check the result of the relisten call. */
562                        if(status == NX_CONNECTION_PENDING)
563                        {
564 
565                            bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
566                        }
567                        else if(status != NX_SUCCESS)
568                        {
569 
570 
571                            /* Failed the relisten on the secondary socket.  Set the error code on the
572                               master socket, and wake it up. */
573 
574                            master_socket_index = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id;
575 
576                            nx_bsd_socket_array[master_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
577                            nx_bsd_set_error_code(&nx_bsd_socket_array[master_socket_index], status);
578 
579                            nx_bsd_select_wakeup((UINT)master_socket_index, (FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION));
580                        }
581                    }
582                }
583                else
584                {
585                    /* The underlying socket is closed.  This indicates an error, and since is a non-blocking
586                       socket, we need to wake up the corresponding thread. */
587 
588                    /* Mark this socket as error, and remove the CONNECT and INPROGRESS flags */
589                    nx_bsd_socket_array[i].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
590                    nx_bsd_socket_array[i].nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
591                    nx_bsd_socket_array[i].nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTED);
592                    nx_bsd_socket_array[i].nx_bsd_socket_error_code = ECONNREFUSED;
593 
594                    /* Wake up the socket that could be listening on it. */
595                    /* Notice that on error the both read and write are selectable. */
596                    nx_bsd_select_wakeup((UINT)i, FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION);
597                }
598            }
599        }
600    }
601 
602    /* Release the mutex. */
603    tx_mutex_put(nx_bsd_protection_ptr);
604 }
605 
606 /**************************************************************************/
607 /*                                                                        */
608 /*  FUNCTION                                               RELEASE        */
609 /*                                                                        */
610 /*    nx_bsd_thread_entry                                 PORTABLE C      */
611 /*                                                           6.1          */
612 /*  AUTHOR                                                                */
613 /*                                                                        */
614 /*    Yuxin Zhou, Microsoft Corporation                                   */
615 /*                                                                        */
616 /*  DESCRIPTION                                                           */
617 /*                                                                        */
618 /*    This function checks for events indicating BSD TCP socket tasks are */
619 /*    waiting to  be performed.                                           */
620 /*                                                                        */
621 /*  INPUT                                                                 */
622 /*                                                                        */
623 /*    None                                                                */
624 /*                                                                        */
625 /*  OUTPUT                                                                */
626 /*                                                                        */
627 /*    None                                                                */
628 /*                                                                        */
629 /*  CALLS                                                                 */
630 /*                                                                        */
631 /*    tx_event_flags_get                   Check for registered events    */
632 /*    nx_bsd_timeout_process               Process BSD tasks              */
633 /*                                                                        */
634 /*  CALLED BY                                                             */
635 /*                                                                        */
636 /*    ThreadX                                                             */
637 /*                                                                        */
638 /*  RELEASE HISTORY                                                       */
639 /*                                                                        */
640 /*    DATE              NAME                      DESCRIPTION             */
641 /*                                                                        */
642 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
643 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
644 /*                                            resulting in version 6.1    */
645 /*                                                                        */
646 /**************************************************************************/
647 
648 #ifndef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
nx_bsd_thread_entry(ULONG info)649 VOID nx_bsd_thread_entry(ULONG info)
650 {
651     NX_PARAMETER_NOT_USED(info);
652 
653     while(1)
654     {
655 
656         /* Wait for timeout. */
657         tx_thread_sleep(NX_BSD_TIMER_RATE);
658 
659         /* Timeout process. */
660         nx_bsd_timeout_process();
661     }
662 }
663 #endif
664 
665 /**************************************************************************/
666 /*                                                                        */
667 /*  FUNCTION                                               RELEASE        */
668 /*                                                                        */
669 /*    socket                                              PORTABLE C      */
670 /*                                                           6.3.0        */
671 /*  AUTHOR                                                                */
672 /*                                                                        */
673 /*    Yuxin Zhou, Microsoft Corporation                                   */
674 /*                                                                        */
675 /*  DESCRIPTION                                                           */
676 /*                                                                        */
677 /*    Creates a TCP or UDP socket, which may then be used as an end point */
678 /*    of communication for sending and receiving data using the specified */
679 /*    protocol.                                                           */
680 /*                                                                        */
681 /*  INPUT                                                                 */
682 /*                                                                        */
683 /*    protocolFamily                        Protocol family e.g AF_INET   */
684 /*    type                                  Type of the socket TCP or UDP */
685 /*    protocol                              Socket protocol               */
686 /*                                                                        */
687 /*  OUTPUT                                                                */
688 /*                                                                        */
689 /*    socket descriptor                     On success                    */
690 /*    NX_SOC_ERROR (-1)                     On failure                    */
691 /*                                                                        */
692 /*  CALLS                                                                 */
693 /*                                                                        */
694 /*    memset                                Clears memory                 */
695 /*    nx_tcp_socket_create                  Create TCP BSD Socket         */
696 /*    nx_udp_socket_create                  Create UDP BSD Socket         */
697 /*    nx_tcp_socket_receive_notify          TCP receive notify function   */
698 /*    nx_udp_socket_receive_notify          UDP receive notify function   */
699 /*    tx_block_allocate                     Allocate socket memory        */
700 /*    tx_block_release                      Release socket memory         */
701 /*    tx_mutex_get                          Get protection                */
702 /*    tx_mutex_put                          Release protection            */
703 /*                                                                        */
704 /*  CALLED BY                                                             */
705 /*                                                                        */
706 /*    Application Code                                                    */
707 /*                                                                        */
708 /*  RELEASE HISTORY                                                       */
709 /*                                                                        */
710 /*    DATE              NAME                      DESCRIPTION             */
711 /*                                                                        */
712 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
713 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
714 /*                                            resulting in version 6.1    */
715 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
716 /*                                            used new API/structs naming,*/
717 /*                                            resulting in version 6.3.0  */
718 /*                                                                        */
719 /**************************************************************************/
nx_bsd_socket(INT protocolFamily,INT type,INT protocol)720 INT  nx_bsd_socket(INT protocolFamily, INT type, INT protocol)
721 {
722 
723 INT             i;
724 UINT            status;
725 NX_TCP_SOCKET   *tcp_socket_ptr;
726 NX_UDP_SOCKET   *udp_socket_ptr;
727 VOID            *socket_memory = NX_NULL;
728 NX_BSD_SOCKET   *bsd_socket_ptr;
729 
730 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
731 UINT            index;
732 #else
733 
734     NX_PARAMETER_NOT_USED(protocol);
735 #endif
736 
737     /* Check for a supported protocol family.  */
738 #ifndef NX_DISABLE_IPV4
739     if (protocolFamily == AF_INET)
740     {
741     }
742     else
743 #endif /* NX_DISABLE_IPV4 */
744 #ifdef FEATURE_NX_IPV6
745     if (protocolFamily == AF_INET6)
746     {
747     }
748     else
749 #endif /* FEATURE_NX_IPV6 */
750 #if defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)
751     if (protocolFamily == AF_PACKET)
752     {
753     }
754     else
755 #endif /* defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT) */
756     {
757 
758         /* Set the socket error. */
759         nx_bsd_set_errno(EAFNOSUPPORT);
760 
761         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
762         return(NX_SOC_ERROR);
763     }
764 
765     /* Check for a supported socket type.   */
766 #if defined(NX_ENABLE_IP_RAW_PACKET_FILTER) || defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT)
767     if ((type != SOCK_STREAM) && (type != SOCK_DGRAM) && (type != SOCK_RAW))
768 #else
769     if ((type != SOCK_STREAM) && (type != SOCK_DGRAM))
770 #endif
771     {
772 
773         /* Set the socket error. */
774         nx_bsd_set_errno(EPROTOTYPE);
775 
776         /* Invalid type.  */
777         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
778         return(NX_SOC_ERROR);
779     }
780 
781 #if defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)
782     /* An extra check when BSD RAW Packet type is enabled:
783        Only RAW_SOCKET type is supported in AF_PACKET family. */
784     if((protocolFamily == AF_PACKET) && (type != SOCK_RAW))
785     {
786         /* Set the socket error. */
787         nx_bsd_set_errno(EPROTOTYPE);
788 
789         /* Invalid type.  */
790         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
791         return(NX_SOC_ERROR);
792     }
793 #endif /* defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT) */
794 
795 
796     /* Obtain the BSD protection socket.  */
797     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
798 
799     /* Check the status.  */
800     if (status)
801     {
802 
803         /* Set the socket error. */
804         nx_bsd_set_errno(EACCES);
805 
806         /* Error getting the protection mutex.  */
807         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
808         return(NX_SOC_ERROR);
809     }
810 
811     /* Check whether IP fast timer is created or not. */
812     if ((nx_bsd_ip_fast_periodic_timer_entry == NX_NULL) ||
813         (nx_bsd_default_ip -> nx_ip_fast_periodic_timer.tx_timer_internal.tx_timer_internal_timeout_function != _nx_bsd_fast_periodic_timer_entry))
814     {
815 
816         /* BSD socket requires a fast periodic timer to calculate wait option in recv() function. */
817         /* Create IP fast periodic timer. */
818         _nx_ip_fast_periodic_timer_create(nx_bsd_default_ip);
819 
820         /* Replace timer expiration function entry. */
821         nx_bsd_ip_fast_periodic_timer_entry = nx_bsd_default_ip -> nx_ip_fast_periodic_timer.tx_timer_internal.tx_timer_internal_timeout_function;
822         nx_bsd_default_ip -> nx_ip_fast_periodic_timer.tx_timer_internal.tx_timer_internal_timeout_function = _nx_bsd_fast_periodic_timer_entry;
823     }
824 
825     /* Now find a free slot in the BSD socket array.  */
826     for (i = 0; i < NX_BSD_MAX_SOCKETS; i++)
827     {
828 
829         /* See if this entry is available.  Check the in use flag. */
830         if (!(nx_bsd_socket_array[nx_bsd_socket_array_index].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
831         {
832 
833             /* Yes, Ok to use this socket. */
834 
835             /* Clear the entire structure.  */
836             memset((VOID*) &nx_bsd_socket_array[nx_bsd_socket_array_index], 0, sizeof(NX_BSD_SOCKET));
837             nx_bsd_socket_array[nx_bsd_socket_array_index].nx_bsd_socket_id = (INT)nx_bsd_socket_array_index;
838 
839             /* Mark this socket as in-use.  */
840             nx_bsd_socket_array[nx_bsd_socket_array_index].nx_bsd_socket_status_flags |=  NX_BSD_SOCKET_IN_USE;
841 
842             /* Get out of the loop.  */
843             break;
844         }
845         else
846         {
847 
848             /* Try the next socket.  */
849             nx_bsd_socket_array_index++;
850 
851             /* Check if we need to wrap around to the start of the socket table.  */
852             if (nx_bsd_socket_array_index >= NX_BSD_MAX_SOCKETS)
853             {
854 
855                 /* Reset the index to 0.  */
856                 nx_bsd_socket_array_index =  0;
857             }
858         }
859     }
860 
861     /* Check if a free socket was found.  */
862     if (i >= NX_BSD_MAX_SOCKETS)
863     {
864 
865         /* No, set the error status and return. */
866 
867         /* Set the socket error. */
868         nx_bsd_set_errno(ENFILE);
869 
870         /* Release the mutex.  */
871         tx_mutex_put(nx_bsd_protection_ptr);
872 
873         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
874         return(NX_SOC_ERROR);
875     }
876 
877     /* Mark the location of the free socket. */
878     i = (INT)nx_bsd_socket_array_index;
879 
880     /* Update the socket index to the next entry.  */
881     nx_bsd_socket_array_index++;
882 
883     /* Check if we need to wrap around to the start of the table.  */
884     if (nx_bsd_socket_array_index >= NX_BSD_MAX_SOCKETS)
885     {
886 
887         /* Reset the index to 0.  */
888         nx_bsd_socket_array_index =  0;
889     }
890 
891     /* Set up a pointer to the BSD socket to use. */
892     bsd_socket_ptr =  &nx_bsd_socket_array[i];
893 
894     /* For TCP or UDP sockets we need to allocate memory to create the NetX Duo socket
895        (not necessary for raw socket). */
896 
897     if ((type == SOCK_STREAM) || (type == SOCK_DGRAM))
898     {
899 
900         /* Allocate a socket from the block pool.  */
901         status =  tx_block_allocate(&nx_bsd_socket_block_pool, &socket_memory, NX_BSD_TIMEOUT);
902 
903         /* Check for error status.  */
904         if (status != TX_SUCCESS)
905         {
906 
907             /* Set the socket error. */
908             nx_bsd_set_errno(ENOMEM);
909 
910             /* Clear the allocated internal BSD socket.  */
911             bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_IN_USE);
912 
913             /* Release the mutex.  */
914             tx_mutex_put(nx_bsd_protection_ptr);
915 
916             /* Error getting NetX socket memory.  */
917             NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
918             return(NX_SOC_ERROR);
919         }
920 
921         /* Clear the socket memory.  */
922         memset((VOID*) socket_memory, 0, sizeof(NX_TCP_SOCKET));
923 
924     }
925 
926     /* Is this a stream socket e.g. TCP?  */
927     if (type == SOCK_STREAM)
928     {
929         bsd_socket_ptr -> nx_bsd_socket_protocol = NX_PROTOCOL_TCP;
930 
931         /* Mark the master/secondary socket id as invalid. */
932         (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id = NX_BSD_MAX_SOCKETS;
933         (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = NX_BSD_MAX_SOCKETS;
934 
935         /* Yes, allocate memory for a TCP socket.  */
936         tcp_socket_ptr =  (NX_TCP_SOCKET *) socket_memory;
937 
938         /* Create a NetX TCP socket. */
939         /* Note that the nx_bsd_tcp_socket_disconnect_notify is invoked when an
940            established connection is disconnected.
941            The disconnect_complete_notify is called for all types of disconnect,
942            including the ones covered by tcp_socket_disconnect_notify. */
943 
944         status =  nx_tcp_socket_create(nx_bsd_default_ip, tcp_socket_ptr, "NetX BSD TCP Socket",
945                                        NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, NX_BSD_TCP_WINDOW, NX_NULL,
946                                        nx_bsd_tcp_socket_disconnect_notify);
947 
948         /* Check for a successful status.  */
949         if (status == NX_SUCCESS)
950         {
951 
952             /* Register a receive notify callback.  */
953             status =  nx_tcp_socket_receive_notify(tcp_socket_ptr, nx_bsd_tcp_receive_notify);
954 
955             /* Check for invalid input. */
956             if (status != NX_SUCCESS)
957             {
958 
959                 /* Set the socket error if extended socket options enabled. */
960                 nx_bsd_set_errno(EINVAL);
961 
962                 /* Release the allocated socket memory block.  */
963                 tx_block_release(socket_memory);
964 
965                 /* Release the mutex.  */
966                 tx_mutex_put(nx_bsd_protection_ptr);
967 
968                 /* Error getting NetX socket memory.  */
969                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
970                 return(NX_SOC_ERROR);
971             }
972 
973 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
974 
975             /* Set the SYN received notify function */
976             tcp_socket_ptr -> nx_tcp_socket_syn_received_notify = nx_bsd_tcp_syn_received_notify;
977 #endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */
978 
979 #ifdef NX_ENABLE_TCP_KEEPALIVE
980             /* Set the keep alive feature to disabled. */
981             tcp_socket_ptr -> nx_tcp_socket_keepalive_enabled = NX_FALSE;
982 #endif /* NX_ENABLE_TCP_KEEPALIVE */
983 
984             /* Set the socket reuse feature to enabled. This is the default NetX socket behavior. */
985             bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR;
986 
987 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
988             /* Register an establish notify callback for the specified server socket with NetX.  */
989             nx_tcp_socket_establish_notify(tcp_socket_ptr, nx_bsd_tcp_establish_notify);
990 
991             /* Register a disconnect complete notify callback for the specified server socket with NetX.  */
992             /* The callback function is the same as the one used for TCP disconnect callback. */
993             status += nx_tcp_socket_disconnect_complete_notify(tcp_socket_ptr, nx_bsd_tcp_socket_disconnect_notify);
994 #endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */
995 
996             /* Return successful completion.  */
997 
998             /* Save the TCP pointer in the appropriate place.  */
999             bsd_socket_ptr -> nx_bsd_socket_tcp_socket =  tcp_socket_ptr;
1000 
1001             /* Set up pointer in the NetX socket back to the BSD socket.   */
1002             tcp_socket_ptr -> nx_tcp_socket_reserved_ptr =  (VOID *) i;
1003 
1004 
1005         }
1006     }
1007     else if (type == SOCK_DGRAM)
1008     {
1009 
1010         bsd_socket_ptr -> nx_bsd_socket_protocol = NX_PROTOCOL_UDP;
1011 
1012         /* Make a double circular list. */
1013         bsd_socket_ptr -> nx_bsd_socket_next = bsd_socket_ptr;
1014         bsd_socket_ptr -> nx_bsd_socket_previous = bsd_socket_ptr;
1015 
1016         /* Allocate memory for a UDP socket.  */
1017         udp_socket_ptr =  (NX_UDP_SOCKET *) socket_memory;
1018 
1019         /* Create a NetX UDP socket */
1020         status =  nx_udp_socket_create(nx_bsd_default_ip, udp_socket_ptr, "NetX BSD UDP Socket",
1021                                        NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE,
1022                                        (nx_bsd_default_packet_pool -> nx_packet_pool_total)/8+1);
1023 
1024         /* Check for successful result. */
1025         if (status == NX_SUCCESS)
1026         {
1027 
1028             /* Register a receive notify callback.  */
1029             status = nx_udp_socket_receive_notify(udp_socket_ptr, nx_bsd_udp_receive_notify);
1030 
1031             /* Check for errors.  */
1032             if (status != NX_SUCCESS)
1033             {
1034 
1035                 /* Release the allocated socket memory block.  */
1036                 tx_block_release(socket_memory);
1037 
1038                 /* Release the mutex.  */
1039                 tx_mutex_put(nx_bsd_protection_ptr);
1040 
1041                 /* Set the socket error if extended socket options enabled. */
1042                 nx_bsd_set_errno(EINVAL);
1043 
1044                 /* Error getting NetX socket memory.  */
1045                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1046                 return(NX_SOC_ERROR);
1047             }
1048 
1049             /* Save the UDP pointer in the BSD socket.  */
1050             bsd_socket_ptr -> nx_bsd_socket_udp_socket =  udp_socket_ptr;
1051 
1052             /* Set the reserved UDP socket pointer back to the BSD socket.  */
1053             udp_socket_ptr -> nx_udp_socket_reserved_ptr =  (VOID *) (i + 0x00010000);
1054         }
1055     }
1056 #if defined(NX_ENABLE_IP_RAW_PACKET_FILTER) || defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT)
1057     else if (type == SOCK_RAW)
1058     {
1059 
1060 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
1061         /* Check if raw sockets are enabled in NetX Duo. */
1062         if (((protocolFamily == AF_INET) ||
1063              (protocolFamily == AF_INET6)) &&
1064              (nx_bsd_default_ip -> nx_ip_raw_ip_processing == NX_NULL))
1065         {
1066             /* No, Enable raw socket handling in NetX Duo. */
1067             status = nx_ip_raw_packet_enable(nx_bsd_default_ip);
1068 
1069             if (status != NX_SUCCESS)
1070             {
1071 
1072                 /* Release the mutex.  */
1073                 tx_mutex_put(nx_bsd_protection_ptr);
1074 
1075                 nx_bsd_set_errno(EPROTONOSUPPORT);
1076 
1077                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1078                 return NX_SOC_ERROR;
1079             }
1080         }
1081 
1082         /* Check if we set the packet filter already. */
1083          if (((protocolFamily == AF_INET) ||
1084              (protocolFamily == AF_INET6)) &&
1085              (nx_bsd_default_ip -> nx_ip_raw_packet_filter == NX_NULL))
1086         {
1087 
1088             /*  We have not. Do so now. Set the raw packet filter to the IP instance. */
1089             status = nx_ip_raw_packet_filter_set(nx_bsd_default_ip, nx_bsd_raw_packet_filter);
1090 
1091             /* Has a raw packet filter been successfully set? */
1092             if (status != NX_SUCCESS)
1093             {
1094 
1095                 /* Release the mutex.  */
1096                 tx_mutex_put(nx_bsd_protection_ptr);
1097 
1098                 nx_bsd_set_errno(EPROTONOSUPPORT);
1099 
1100                 /* No, return error status. */
1101                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1102                 return NX_SOC_ERROR;
1103             }
1104         }
1105 
1106         /*  For IPv6 raw socket, by default the header is not included in the received packet. */
1107         if(protocolFamily == AF_INET6)
1108         {
1109             bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_RX_NO_HDR;
1110         }
1111 
1112         /* Set the raw socket protocol to the BSD raw socket. */
1113         bsd_socket_ptr -> nx_bsd_socket_protocol = (USHORT)protocol;
1114         bsd_socket_ptr -> nx_bsd_socket_option_flags |=  NX_BSD_SOCKET_ENABLE_RAW_SOCKET;
1115 
1116         /* Calculate the hash index in the raw socket protocol table. */
1117         index = (UINT) ((protocol + (protocol >> 8)) & NX_BSD_SOCKET_RAW_PROTOCOL_TABLE_MASK);
1118 
1119         /* Determine if the list is NULL. */
1120         if(nx_bsd_socket_raw_protocol_table[index])
1121         {
1122             /* There are already sockets on the list... just add this one to the end. */
1123             bsd_socket_ptr -> nx_bsd_socket_next = nx_bsd_socket_raw_protocol_table[index];
1124             bsd_socket_ptr -> nx_bsd_socket_previous = (nx_bsd_socket_raw_protocol_table[index]) -> nx_bsd_socket_previous;
1125             ((nx_bsd_socket_raw_protocol_table[index]) -> nx_bsd_socket_previous) -> nx_bsd_socket_next = bsd_socket_ptr;
1126             (nx_bsd_socket_raw_protocol_table[index]) -> nx_bsd_socket_previous = bsd_socket_ptr;
1127         }
1128         else
1129         {
1130             /* Nothing is on the list. Add this one to an empty list. */
1131             bsd_socket_ptr -> nx_bsd_socket_next = bsd_socket_ptr;
1132             bsd_socket_ptr -> nx_bsd_socket_previous = bsd_socket_ptr;
1133             nx_bsd_socket_raw_protocol_table[index] = bsd_socket_ptr;
1134         }
1135 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
1136 
1137         if(protocolFamily == AF_PACKET)
1138         {
1139 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
1140             bsd_socket_ptr -> nx_bsd_socket_create_id = nx_bsd_socket_create_id;
1141             nx_bsd_socket_create_id++;
1142 #elif defined(NX_BSD_RAW_SUPPORT)
1143             bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
1144             bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
1145 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
1146         }
1147 
1148     }
1149 #endif  /* NX_ENABLE_IP_RAW_PACKET_FILTER || NX_BSD_RAW_PPPOE_SUPPORT || NX_BSD_RAW_SUPPORT */
1150 
1151     else
1152     {
1153         /* Not a supported socket type.   */
1154        nx_bsd_set_errno(EOPNOTSUPP);
1155 
1156         /* Invalid type.  */
1157         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1158         return(NX_SOC_ERROR);
1159     }
1160 
1161     /* Set the protocol family: AF_INET or AF_INET6.   */
1162     bsd_socket_ptr -> nx_bsd_socket_family = (ULONG)protocolFamily;
1163 
1164     /* For UDP and RAW sockets, set the maximum receive queue depth. */
1165     if(bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
1166     {
1167 
1168         bsd_socket_ptr -> nx_bsd_socket_received_packet_count_max = NX_BSD_SOCKET_QUEUE_MAX;
1169     }
1170 
1171     /* Check for error creating the NetX Duo socket.  */
1172     if (status != NX_SUCCESS)
1173     {
1174 
1175         /* Release the BSD protection.  */
1176 
1177         /* Clear the BSD socket in use flag.  */
1178         bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_IN_USE);
1179 
1180         if ((type == SOCK_DGRAM) || (type == SOCK_STREAM))
1181         {
1182             /* Release the socket memory block allocated for TCP or UDP socket.  */
1183             tx_block_release(socket_memory);
1184         }
1185 
1186         /* Release the mutex.  */
1187         tx_mutex_put(nx_bsd_protection_ptr);
1188 
1189         /* Set the socket error if extended socket options enabled. */
1190         nx_bsd_set_errno(EINVAL);
1191 
1192         /* Error present, return error code.  */
1193         NX_BSD_ERROR(status, __LINE__);
1194         return(NX_SOC_ERROR);
1195     }
1196 
1197     /* Release the mutex.  */
1198     tx_mutex_put(nx_bsd_protection_ptr);
1199 
1200     /* Return success!  */
1201     return(i + NX_BSD_SOCKFD_START);
1202 }
1203 
1204 
1205 /**************************************************************************/
1206 /*                                                                        */
1207 /*  FUNCTION                                               RELEASE        */
1208 /*                                                                        */
1209 /*    connect                                             PORTABLE C      */
1210 /*                                                           6.3.0        */
1211 /*  AUTHOR                                                                */
1212 /*                                                                        */
1213 /*    Yuxin Zhou, Microsoft Corporation                                   */
1214 /*                                                                        */
1215 /*  DESCRIPTION                                                           */
1216 /*                                                                        */
1217 /*    Establishes a connection between a client socket and a remote server*/
1218 /*    socket associated with the remote address, if any. Upon returning   */
1219 /*    successfully, the given socket's local and remote IP address and    */
1220 /*    port information are filled in. If the socket was not previously    */
1221 /*    bound to a local port, one is assigned randomly.                    */
1222 /*                                                                        */
1223 /*    For TCP sockets, connect() completes with a connection handshake is */
1224 /*    complete, or if an error occurs.   A TCP negotiation is performed   */
1225 /*    to open a connection and success implies the existence of a reliable*/
1226 /*    channel to that socket.                                             */
1227 /*                                                                        */
1228 /*    For UDP sockets, the connection is established simply by setting the*/
1229 /*    supplied destination (remote) IP address and port for the remote    */
1230 /*    host.                                                               */
1231 /*                                                                        */
1232 /*    For non blocking sockets, the function returns immediately if a     */
1233 /*    connection is not possible.  The socket thread error is set to      */
1234 /*    EINPROGRESS to distinguish from blocking sockets.                   */
1235 /*                                                                        */
1236 /*  INPUT                                                                 */
1237 /*                                                                        */
1238 /*     sockID                               Socket descriptor             */
1239 /*    *remoteAddress                        Remote address structure      */
1240 /*     addressLength                        Address structure length      */
1241 /*                                                                        */
1242 /*  OUTPUT                                                                */
1243 /*                                                                        */
1244 /*    NX_SOC_OK (0)                         If success                    */
1245 /*    NX_SOC_ERROR (-1)                     If failure or if called with  */
1246 /*                                            an UDP socket               */
1247 /*                                                                        */
1248 /*  CALLS                                                                 */
1249 /*                                                                        */
1250 /*    nx_ip_status_check                    Check to make sure link is up */
1251 /*    nx_tcp_client_socket_bind             Bind a TCP socket to a port   */
1252 /*    nxd_tcp_client_socket_connect         Connect to a TCP server       */
1253 /*    tx_mutex_get                          Get protection                */
1254 /*    tx_mutex_put                          Release protection            */
1255 /*    tx_thread_identify                    Get current thread pointer    */
1256 /*                                                                        */
1257 /*  CALLED BY                                                             */
1258 /*                                                                        */
1259 /*    Application Code                                                    */
1260 /*                                                                        */
1261 /*  RELEASE HISTORY                                                       */
1262 /*                                                                        */
1263 /*    DATE              NAME                      DESCRIPTION             */
1264 /*                                                                        */
1265 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1266 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1267 /*                                            resulting in version 6.1    */
1268 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
1269 /*                                            used new API/structs naming,*/
1270 /*                                            resulting in version 6.3.0  */
1271 /*                                                                        */
1272 /**************************************************************************/
nx_bsd_connect(INT sockID,struct nx_bsd_sockaddr * remoteAddress,INT addressLength)1273 INT  nx_bsd_connect(INT sockID, struct nx_bsd_sockaddr *remoteAddress, INT addressLength)
1274 {
1275 UINT                status;
1276 NX_TCP_SOCKET       *tcp_socket_ptr;
1277 NX_UDP_SOCKET       *udp_socket_ptr;
1278 NX_BSD_SOCKET       *bsd_socket_ptr;
1279 ULONG               timeout;
1280 ULONG               actual_status;
1281 
1282     /* Check for a valid socket ID.  */
1283     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
1284     {
1285 
1286         /* Set the socket error. */
1287         nx_bsd_set_errno(EBADF);
1288 
1289         /* Return an error. */
1290         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1291         return(NX_SOC_ERROR);
1292     }
1293 
1294     /* Adjust the sockID to index into the BSD socket table.  */
1295     sockID =  sockID - NX_BSD_SOCKFD_START;
1296 
1297     /* Ensure the IP instance has been initialized.  */
1298     status =  nx_ip_status_check(nx_bsd_default_ip, NX_IP_INITIALIZE_DONE, &actual_status, NX_BSD_TIMEOUT);
1299 
1300     /* Check the status.  */
1301     if (status != NX_SUCCESS)
1302     {
1303 
1304         /* Set the socket error. */
1305         nx_bsd_set_errno(EFAULT);
1306 
1307         /* Return an error. */
1308         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1309         return(NX_SOC_ERROR);
1310     }
1311 
1312     /* Set a pointer to the BSD socket.  */
1313     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
1314 
1315     /* Make sure the socket is valid. */
1316     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
1317     {
1318 
1319         /* Socket is no longer in use.   */
1320 
1321         /* Set the socket error if extended socket options enabled. */
1322         nx_bsd_set_errno(EBADF);
1323 
1324         /* Return an error.  */
1325         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1326         return(NX_SOC_ERROR);
1327     }
1328 
1329     /* Obtain the BSD protection.  */
1330     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
1331 
1332     /* Check the status.  */
1333     if (status != NX_SUCCESS)
1334     {
1335 
1336         /* Set the socket error if extended socket options enabled. */
1337         nx_bsd_set_errno(EACCES);
1338 
1339         /* Return an error. */
1340         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
1341         return(NX_SOC_ERROR);
1342     }
1343 
1344     /* Check whether supplied address structure and length is valid */
1345     if (remoteAddress == NX_NULL )
1346     {
1347 
1348         /* For UDP socket or RAW socket, a NULL remoteAddress dis-associate
1349            a remote address bound to the socket. */
1350         if (bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
1351         {
1352             memset(&bsd_socket_ptr -> nx_bsd_socket_peer_ip, 0, sizeof(NXD_ADDRESS));
1353             bsd_socket_ptr -> nx_bsd_socket_peer_port = 0;
1354 
1355             /* Clear the connect flag. */
1356             bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTED);
1357 
1358             /* All done.  Return. */
1359 
1360             /* Release the mutex.  */
1361             tx_mutex_put(nx_bsd_protection_ptr);
1362 
1363             return(NX_SOC_OK);
1364 
1365         }
1366         else
1367         {
1368             /* For TCP socket, each socket can only be connected once, and
1369                the remote address must be set correctly. */
1370 
1371             /* Release the mutex.  */
1372             tx_mutex_put(nx_bsd_protection_ptr);
1373             /* Set the socket error if extended socket options enabled. */
1374             nx_bsd_set_errno(EAFNOSUPPORT);
1375 
1376             /* Return an error. */
1377             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1378             return(NX_SOC_ERROR);
1379         }
1380     }
1381 
1382 
1383     /* Check if the remote address family matches the local BSD socket address family. */
1384     if((remoteAddress -> sa_family != bsd_socket_ptr -> nx_bsd_socket_family) ||
1385        ((remoteAddress -> sa_family == AF_INET) && (addressLength != sizeof(struct nx_bsd_sockaddr_in))) ||
1386        ((remoteAddress -> sa_family == AF_INET6) && (addressLength != sizeof(struct nx_bsd_sockaddr_in6))))
1387     {
1388 
1389         /* Mismatch! */
1390 
1391         /* Release the mutex.  */
1392         tx_mutex_put(nx_bsd_protection_ptr);
1393 
1394         /* Set the socket error if extended socket options enabled. */
1395         nx_bsd_set_errno(EAFNOSUPPORT);
1396 
1397         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1398         return(ERROR);
1399     }
1400 
1401 #ifndef NX_DISABLE_IPV4
1402     /* Check the socket family type.  */
1403     if(remoteAddress -> sa_family == AF_INET)
1404     {
1405 
1406         /* This is an IPv4 socket type. */
1407 
1408         /* Set the UDP remote host IP address and port for the UDP 'connection'; for NetX Duo
1409            set the IP version. */
1410         /* NetX API expects multi byte values to be in host byte order.
1411            Therefore ntohl/s are used to make the conversion. */
1412         bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_version = NX_IP_VERSION_V4;
1413         bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v4 =  htonl(((struct nx_bsd_sockaddr_in *) remoteAddress ) -> sin_addr.s_addr);
1414         bsd_socket_ptr -> nx_bsd_socket_peer_port =  htons(((struct nx_bsd_sockaddr_in *) remoteAddress ) -> sin_port);
1415     }
1416     else
1417 #endif /* NX_DISABLE_IPV4 */
1418 
1419 #ifdef FEATURE_NX_IPV6
1420     if(remoteAddress -> sa_family == AF_INET6)
1421     {
1422 
1423         /* This is an IPv6 enabled socket family type). */
1424         bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_version = NX_IP_VERSION_V6;
1425         /* NetX API expects multi byte values to be in host byte order.
1426            Therefore ntohl/s are used to make the conversion. */
1427         /* Get remote address and port. */
1428         bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[0] = htonl(((struct nx_bsd_sockaddr_in6*)remoteAddress) -> sin6_addr._S6_un._S6_u32[0]);
1429         bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[1] = htonl(((struct nx_bsd_sockaddr_in6*)remoteAddress) -> sin6_addr._S6_un._S6_u32[1]);
1430         bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[2] = htonl(((struct nx_bsd_sockaddr_in6*)remoteAddress) -> sin6_addr._S6_un._S6_u32[2]);
1431         bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[3] = htonl(((struct nx_bsd_sockaddr_in6*)remoteAddress) -> sin6_addr._S6_un._S6_u32[3]);
1432 
1433         bsd_socket_ptr -> nx_bsd_socket_peer_port =  htons(((struct nx_bsd_sockaddr_in6 *) remoteAddress ) -> sin6_port);
1434 
1435     }
1436     else
1437 #endif /* FEATURE_NX_IPV6 */
1438     {
1439 
1440         /* Address family not supported. */
1441 
1442         /* Release the mutex.  */
1443         tx_mutex_put(nx_bsd_protection_ptr);
1444 
1445         /* Set the socket error if extended socket options enabled. */
1446         nx_bsd_set_errno(EAFNOSUPPORT);
1447 
1448         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1449         return(ERROR);
1450     }
1451 
1452 
1453     /* Handle the UDP 'connection' request.  */
1454     if (bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
1455     {
1456 
1457         udp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_udp_socket;
1458 
1459         /* Check to see if the UDP socket is already bound.  */
1460         if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND))
1461         {
1462 
1463             /* Not yet, bind to a randomly selected available free port.  */
1464             status =  nx_udp_socket_bind(udp_socket_ptr, NX_ANY_PORT, NX_BSD_TIMEOUT);
1465 
1466             /* Check for error.  */
1467             if (status != NX_SUCCESS)
1468             {
1469 
1470                 /* Release the mutex.  */
1471                 tx_mutex_put(nx_bsd_protection_ptr);
1472 
1473                 /* Set the socket error based on NetX error status return. */
1474                 nx_bsd_set_error_code(bsd_socket_ptr, status);
1475 
1476                 /* Return an error.  */
1477                 NX_BSD_ERROR(ERROR, __LINE__);
1478                 return(ERROR);
1479             }
1480 
1481             /* Bind is successful. Obtain the port number. */
1482             bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)udp_socket_ptr -> nx_udp_socket_port;
1483             bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
1484             bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
1485             bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
1486        }
1487 
1488        /* Mark the socket as connected. */
1489        bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
1490 
1491        /* Release the mutex.  */
1492        tx_mutex_put(nx_bsd_protection_ptr);
1493 
1494        /* Return successful status.  */
1495        return(NX_SOC_OK);
1496     }
1497     else if (bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
1498     {
1499 
1500         /* This is not UDP or TCP socket.  So it must be raw socket. */
1501         /* We treat raw socket the same as UDP socket.  For connec, raw socket
1502            associates the remote address as its default destination address when
1503            transmit, and also limit the reception of data from that remote address. */
1504 
1505         /* Mark the socket as connected. */
1506         bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
1507 
1508         /* Release the mutex.  */
1509         tx_mutex_put(nx_bsd_protection_ptr);
1510 
1511         /* Return successful status.  */
1512         return(NX_SOC_OK);
1513     }
1514 
1515     /* This is a TCP BSD socket. */
1516 
1517     /* If the socket is already connected. */
1518     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
1519     {
1520 
1521         /* If INPROGRESS is set, clear the INPROGRESS flag and return OK.
1522            The INPROGRESS flag needs to be cleared so the next connect call would return EISCONN */
1523         if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_INPROGRESS)
1524         {
1525 
1526             bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
1527 
1528             /* Release the protection mutex.  */
1529             tx_mutex_put(nx_bsd_protection_ptr);
1530 
1531             return(NX_SOC_OK);
1532         }
1533 
1534         /* Already connected. */
1535         nx_bsd_set_errno(EISCONN);
1536 
1537         tx_mutex_put(nx_bsd_protection_ptr);
1538 
1539         /* Return an error.  */
1540         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1541         return(NX_SOC_ERROR);
1542 
1543     }
1544 
1545     /* If the socket is marked as EINPROGRESS, return EALREADY. */
1546     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_INPROGRESS)
1547     {
1548 
1549 
1550         nx_bsd_set_errno(EALREADY);
1551 
1552         /* Release the protection mutex.  */
1553         tx_mutex_put(nx_bsd_protection_ptr);
1554 
1555         /* Return an error.  */
1556         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1557         return(NX_SOC_ERROR);
1558 
1559     }
1560     /* If the socket has an error */
1561     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
1562     {
1563         INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
1564 
1565         /* Now clear the error code. */
1566         bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
1567 
1568         /* Clear the error flag.  The application is expected to close the socket at this point.*/
1569         bsd_socket_ptr -> nx_bsd_socket_status_flags =
1570             bsd_socket_ptr -> nx_bsd_socket_status_flags & ((ULONG)(~NX_BSD_SOCKET_ERROR));
1571 
1572         nx_bsd_set_errno(errcode);
1573 
1574         /* Release the protection mutex.  */
1575         tx_mutex_put(nx_bsd_protection_ptr);
1576 
1577         /* Return an error.  */
1578         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1579 
1580         /* At this point the error flag is cleared.  Application should
1581            detect and handle the error codition. This socket is still bound
1582            to the port (either the application called bind(), or a bind
1583            operation was executed as part of the connect call) is able to
1584            handle another "connect" call, or be closed. */
1585         return(NX_SOC_ERROR);
1586     }
1587 
1588     /* Set a NetX tcp pointer.  */
1589     tcp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
1590 
1591     /* Mark this as a client TCP socket. */
1592     bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CLIENT;
1593 
1594     /* Is the TCP socket already bound?  */
1595     if (tcp_socket_ptr -> nx_tcp_socket_port == 0)
1596     {
1597 
1598         /* Not yet; bind to a randomly selected available free port. */
1599 
1600         /* Call NetX TCP bind service with NX_NO_WAIT.  */
1601         status =  nx_tcp_client_socket_bind(tcp_socket_ptr, NX_ANY_PORT, NX_NO_WAIT);
1602 
1603         /* Check for error.  */
1604         if (status != NX_SUCCESS)
1605         {
1606 
1607             /* Clear the client socket flag.  */
1608             bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CLIENT);
1609 
1610             /* Set the socket error depending on NetX error status return. */
1611             nx_bsd_set_error_code(bsd_socket_ptr, status);
1612 
1613             /* Return an error.  */
1614             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1615 
1616             /* Release the protection mutex.  */
1617             tx_mutex_put(nx_bsd_protection_ptr);
1618 
1619             return(NX_SOC_ERROR);
1620         }
1621 
1622         /* Mark the socket as bound. */
1623         bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
1624         bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)tcp_socket_ptr -> nx_tcp_socket_port;
1625         bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
1626         bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
1627 
1628     }
1629 
1630     /* Mark this BSD socket as busy.  */
1631     bsd_socket_ptr -> nx_bsd_socket_busy = tx_thread_identify();
1632 
1633     /* Attempt to make the connection.  If the socket is non-blocking,
1634        set the timeout to 0.  Otherwise, use wait-forever */
1635     if (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING)
1636     {
1637 
1638         /* Yes, the socket is enabled for non blocking. Do not wait.  */
1639         timeout = 0;
1640     }
1641     else
1642     {
1643         /* This call may be blocked internally. Release the mutex
1644            so the nx_tcp_client_socket_connect can suspend waiting
1645            for a connection. */
1646         timeout = NX_WAIT_FOREVER;
1647         tx_mutex_put(nx_bsd_protection_ptr);
1648     }
1649 
1650     /* Make the connection. */
1651     status =  nxd_tcp_client_socket_connect(tcp_socket_ptr, &(bsd_socket_ptr -> nx_bsd_socket_peer_ip), bsd_socket_ptr -> nx_bsd_socket_peer_port, timeout);
1652     if(timeout != 0)
1653     {
1654         /* The mutex was released prior to the call.  Accquire the mutex
1655            again. */
1656         tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
1657 
1658         /* Verify that the socket is still valid. */
1659         if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
1660         {
1661             /* The socket is no longer in use. */
1662 
1663             /* Set the socket error code. */
1664             nx_bsd_set_errno(EBADF);
1665 
1666             /* Release the protection mutex.  */
1667             tx_mutex_put(nx_bsd_protection_ptr);
1668 
1669             /* Return error code.  */
1670             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1671             return(NX_SOC_ERROR);
1672         }
1673 
1674         if (status == NX_NOT_CONNECTED)
1675         {
1676 
1677             if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR) ||
1678                 (tcp_socket_ptr -> nx_tcp_socket_timeout_retries >= tcp_socket_ptr -> nx_tcp_socket_timeout_max_retries))
1679             {
1680 
1681                 /* Connect timeouts since NX_BSD_SOCKET_ERROR is not set or
1682                  * number of timeout retry has been exceeded. */
1683                 status = NX_WAIT_ABORTED;
1684             }
1685 
1686             bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
1687             bsd_socket_ptr -> nx_bsd_socket_error_code = ENOTCONN;
1688         }
1689     }
1690 
1691     /* Check for an error.  */
1692     if (status != NX_SUCCESS)
1693     {
1694 
1695         /* Set the socket error depending on NetX error status return. */
1696         nx_bsd_set_error_code(bsd_socket_ptr, status);
1697 
1698 
1699         /* Make sure this thread is still the owner.  */
1700         if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
1701         {
1702 
1703             /* Clear the busy flag.  */
1704             bsd_socket_ptr -> nx_bsd_socket_busy =  TX_NULL;
1705         }
1706 
1707         /* Release the protection mutex.  */
1708         tx_mutex_put(nx_bsd_protection_ptr);
1709 
1710         /* Return error code.  */
1711         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1712         return(NX_SOC_ERROR);
1713     }
1714 
1715     /* At this point NX TCP connect service returns success, so the connection is established. */
1716 
1717     /* Mark the socket as connected. */
1718     bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
1719 
1720     /* Clear the CONNECTION_INPROGRESS flag. */
1721     bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
1722 
1723     /* Mark the connection_request flag */
1724     bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_REQUEST;
1725 
1726     /* Make sure thread making the bind call is the current thread.  */
1727     if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
1728     {
1729 
1730         /* OK to clear the busy flag.  */
1731         bsd_socket_ptr -> nx_bsd_socket_busy =  TX_NULL;
1732 
1733         /* Check if the connect call was successful.  */
1734         if (status == NX_SUCCESS)
1735         {
1736 
1737             /* It was. Release the protection mutex.  */
1738             tx_mutex_put(nx_bsd_protection_ptr);
1739 
1740             /* Successful connection. Return the success status.  */
1741             return(NX_SOC_OK);
1742         }
1743     }
1744 
1745     /* Error condition: the thread that was executing connect is not the current thread. */
1746 
1747     /* Clear the connected flags and peer infomration .*/
1748     bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTED);
1749     bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_REQUEST);
1750     memset(&bsd_socket_ptr -> nx_bsd_socket_source_ip_address, 0, sizeof(NXD_ADDRESS));
1751     bsd_socket_ptr -> nx_bsd_socket_source_port = 0;
1752 
1753     /* Release the protection mutex.  */
1754     tx_mutex_put(nx_bsd_protection_ptr);
1755 
1756     /* Set the socket error. */
1757     nx_bsd_set_errno(EINTR);
1758 
1759     /* Return an error.  */
1760     NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1761     return(NX_SOC_ERROR);
1762 }
1763 
1764 /**************************************************************************/
1765 /*                                                                        */
1766 /*  FUNCTION                                               RELEASE        */
1767 /*                                                                        */
1768 /*    bind                                                PORTABLE C      */
1769 /*                                                           6.3.0        */
1770 /*  AUTHOR                                                                */
1771 /*                                                                        */
1772 /*    Yuxin Zhou, Microsoft Corporation                                   */
1773 /*                                                                        */
1774 /*  DESCRIPTION                                                           */
1775 /*                                                                        */
1776 /*    This function binds a socket to a local port. The port in the struct*/
1777 /*    in the struct sockaddr structure may be wildcarded, in which case   */
1778 /*    NetX will select a port number.                                     */
1779 /*                                                                        */
1780 /*    To wildcard the port, set the sin_port field of the address to 0.   */
1781 /*                                                                        */
1782 /*  INPUT                                                                 */
1783 /*                                                                        */
1784 /*    sockID                                Socket descriptor             */
1785 /*    *localAddress                         Populated socket address      */
1786 /*    addressLength                         Socket address length         */
1787 /*                                                                        */
1788 /*  OUTPUT                                                                */
1789 /*                                                                        */
1790 /*    NX_SOC_OK (0)                         If success                    */
1791 /*    NX_SOC_ERROR (-1)                     If failure                    */
1792 /*                                                                        */
1793 /*  CALLS                                                                 */
1794 /*                                                                        */
1795 /*    nx_ip_status_check                    Check for link up             */
1796 /*    nx_tcp_client_socket_bind             Binds a TCP socket to a port  */
1797 /*    nx_udp_client_socket_bind             Binds a UDP socket to a port  */
1798 /*    tx_mutex_get                          Get protection                */
1799 /*    tx_mutex_put                          Release protection            */
1800 /*    tx_thread_identify                    Gets the current thread       */
1801 /*                                                                        */
1802 /*  CALLED BY                                                             */
1803 /*                                                                        */
1804 /*    Application Code                                                    */
1805 /*                                                                        */
1806 /*  RELEASE HISTORY                                                       */
1807 /*                                                                        */
1808 /*    DATE              NAME                      DESCRIPTION             */
1809 /*                                                                        */
1810 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1811 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1812 /*                                            resulting in version 6.1    */
1813 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
1814 /*                                            used new API/structs naming,*/
1815 /*                                            resulting in version 6.3.0  */
1816 /*                                                                        */
1817 /**************************************************************************/
nx_bsd_bind(INT sockID,const struct nx_bsd_sockaddr * localAddress,INT addressLength)1818 INT  nx_bsd_bind(INT sockID, const struct nx_bsd_sockaddr *localAddress, INT addressLength)
1819 {
1820 
1821 INT                 local_port = 0;
1822 UINT                status;
1823 NX_TCP_SOCKET       *tcp_socket_ptr;
1824 NX_UDP_SOCKET       *udp_socket_ptr;
1825 NX_BSD_SOCKET       *bsd_socket_ptr;
1826 INT                 i;
1827 INT                 address_conflict;
1828 
1829 
1830     /* Check for invalid socket ID.  */
1831     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
1832     {
1833 
1834         /* Set the socket error. */
1835         nx_bsd_set_errno(EBADF);
1836 
1837         /* Error, invalid socket ID.  */
1838         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1839         return(NX_SOC_ERROR);
1840     }
1841 
1842     /* Check for a valid input local address and address length input buffer.  */
1843     if ((localAddress == NX_NULL ) || (addressLength == 0))
1844     {
1845 
1846         /* Set the socket error if extended socket options enabled. */
1847         nx_bsd_set_errno(EFAULT);
1848 
1849         /* Error, invalid local address. */
1850         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1851         return(NX_SOC_ERROR);
1852     }
1853 
1854     if (((localAddress -> sa_family == AF_INET) && (addressLength != sizeof(struct nx_bsd_sockaddr_in))) ||
1855         ((localAddress -> sa_family == AF_INET6) && (addressLength != sizeof(struct nx_bsd_sockaddr_in6))))
1856     {
1857         nx_bsd_set_errno(EAFNOSUPPORT);
1858 
1859         /* Return an error.  */
1860         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1861         return(NX_SOC_ERROR);
1862     }
1863 
1864     /* Normalize the socket ID.  */
1865     sockID =  sockID - NX_BSD_SOCKFD_START;
1866 
1867     /* Get the protection mutex.  */
1868     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
1869 
1870     /* Check the status.  */
1871     if (status != NX_SUCCESS)
1872     {
1873 
1874         /* Set the socket error if extended socket options enabled. */
1875         nx_bsd_set_errno(EACCES);
1876 
1877         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
1878         return(NX_SOC_ERROR);
1879     }
1880 
1881     /* Set up a pointer to the BSD socket.  */
1882     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
1883 
1884     /* See if the socket is still in use.  */
1885     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
1886     {
1887 
1888         /* Socket is no longer in use.   */
1889 
1890         /* Release the protection mutex.  */
1891         tx_mutex_put(nx_bsd_protection_ptr);
1892 
1893         /* Set the socket error if extended socket options enabled. */
1894         nx_bsd_set_errno(EBADF);
1895 
1896         /* Return an error.  */
1897         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1898         return(NX_SOC_ERROR);
1899     }
1900 
1901     /* If the socket has an error */
1902     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
1903     {
1904 
1905         /* Clear the error flag.  The application is expected to close the socket at this point.*/
1906         bsd_socket_ptr -> nx_bsd_socket_status_flags =
1907             bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
1908 
1909         nx_bsd_set_errno(bsd_socket_ptr -> nx_bsd_socket_error_code);
1910 
1911         /* Clear the error code. */
1912         bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
1913 
1914         /* Release the protection mutex.  */
1915         tx_mutex_put(nx_bsd_protection_ptr);
1916 
1917         /* Return an error.  */
1918         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1919 
1920         /* At this point the error flag is cleared.  Application should
1921            detect and handle the error codition. This socket is still bound
1922            to the port (either the application called bind(), or a bind
1923            operation was executed as part of the connect call) is able to
1924            handle another "connect" call, or be closed. */
1925         return(NX_SOC_ERROR);
1926     }
1927 
1928     /* Check the address family. */
1929     if (bsd_socket_ptr -> nx_bsd_socket_family != localAddress -> sa_family)
1930     {
1931         nx_bsd_set_errno(EAFNOSUPPORT);
1932         /* Release the protection mutex.  */
1933         tx_mutex_put(nx_bsd_protection_ptr);
1934 
1935         /* Return an error.  */
1936         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1937         return(NX_SOC_ERROR);
1938     }
1939 
1940     /* Check to see if the socket is already bound.  */
1941     if (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND)
1942     {
1943 
1944         /* It is. */
1945 
1946         /* Set the socket error if extended socket options enabled. */
1947         nx_bsd_set_errno(EINVAL);
1948 
1949         /* Release the protection mutex.  */
1950         tx_mutex_put(nx_bsd_protection_ptr);
1951 
1952         /* Return an error.  */
1953         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1954         return(NX_SOC_ERROR);
1955     }
1956 
1957     /* Zero out the local bind info */
1958     bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = 0;
1959 
1960 #ifndef NX_DISABLE_IPV4
1961     if(localAddress -> sa_family == AF_INET)
1962     {
1963 
1964     ULONG local_addr;
1965     INT if_index;
1966 
1967         /* Pickup the local port.  */
1968         local_port = ntohs(((struct nx_bsd_sockaddr_in *) localAddress) -> sin_port);
1969 
1970         /* Pick up the local IP address */
1971         local_addr = ntohl(((struct nx_bsd_sockaddr_in*)localAddress) -> sin_addr.s_addr);
1972 
1973         if(local_addr == INADDR_ANY)
1974         {
1975 
1976             bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
1977             bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
1978         }
1979         else
1980         {
1981 
1982             for(if_index = 0; if_index < NX_MAX_IP_INTERFACES; if_index++)
1983             {
1984 
1985                 if((nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_valid) &&
1986                    (nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_ip_address == local_addr))
1987                 {
1988 
1989                     bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = (ULONG)(&nx_bsd_default_ip -> nx_ip_interface[if_index]);
1990                     bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = (UINT)if_index;
1991                     break;
1992                 }
1993             }
1994         }
1995     }
1996 #endif /* NX_DISABLE_IPV4 */
1997 #ifdef FEATURE_NX_IPV6
1998     if(localAddress -> sa_family == AF_INET6)
1999     {
2000 
2001     ULONG ipv6_addr[4];
2002     INT if_index;
2003 
2004         /* Pickup the local port.  */
2005         local_port = ntohs(((struct nx_bsd_sockaddr_in6 *) localAddress) -> sin6_port);
2006 
2007         ipv6_addr[0] = ntohl((((struct nx_bsd_sockaddr_in6*)localAddress)) -> sin6_addr._S6_un._S6_u32[0]);
2008         ipv6_addr[1] = ntohl((((struct nx_bsd_sockaddr_in6*)localAddress)) -> sin6_addr._S6_un._S6_u32[1]);
2009         ipv6_addr[2] = ntohl((((struct nx_bsd_sockaddr_in6*)localAddress)) -> sin6_addr._S6_un._S6_u32[2]);
2010         ipv6_addr[3] = ntohl((((struct nx_bsd_sockaddr_in6*)localAddress)) -> sin6_addr._S6_un._S6_u32[3]);
2011 
2012         if((ipv6_addr[0] | ipv6_addr[1] | ipv6_addr[2] | ipv6_addr[3]) == 0)
2013         {
2014 
2015             bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
2016             bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
2017         }
2018         else
2019         {
2020 
2021             for(if_index = 0; if_index < NX_MAX_IPV6_ADDRESSES; if_index++)
2022             {
2023 
2024                 if((nx_bsd_default_ip -> nx_ipv6_address[if_index].nxd_ipv6_address[0] == ipv6_addr[0]) &&
2025                    (nx_bsd_default_ip -> nx_ipv6_address[if_index].nxd_ipv6_address[1] == ipv6_addr[1]) &&
2026                    (nx_bsd_default_ip -> nx_ipv6_address[if_index].nxd_ipv6_address[2] == ipv6_addr[2]) &&
2027                    (nx_bsd_default_ip -> nx_ipv6_address[if_index].nxd_ipv6_address[3] == ipv6_addr[3]))
2028                 {
2029 
2030                     bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = (ULONG)(&nx_bsd_default_ip -> nx_ipv6_address[if_index]);
2031 
2032                     bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = (UINT)if_index;
2033                     break;
2034                 }
2035             }
2036         }
2037     }
2038 #endif
2039 #ifdef NX_BSD_RAW_SUPPORT
2040     if ((localAddress -> sa_family == AF_PACKET) && (addressLength == sizeof(struct nx_bsd_sockaddr_ll)))
2041     {
2042     UINT if_index;
2043 
2044         if_index = (UINT)(((struct sockaddr_ll *)localAddress) -> sll_ifindex);
2045         bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = (ULONG)(&nx_bsd_default_ip -> nx_ip_interface[if_index]);
2046         bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = if_index;
2047     }
2048 #endif /* NX_BSD_RAW_SUPPORT */
2049 
2050     /* Check if the bind information is correctly set. */
2051     if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == 0)
2052     {
2053 
2054         /* Release the protection mutex.  */
2055         tx_mutex_put(nx_bsd_protection_ptr);
2056 
2057         /* Set the socket error if extended socket options enabled. */
2058         nx_bsd_set_errno(EADDRNOTAVAIL);
2059 
2060         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
2061         return(NX_SOC_ERROR);
2062     }
2063 
2064     /* At this point the local bind interface and port are known.
2065        If port number is specified, we need to go through the existing sockets
2066        and make sure there is no conflict. */
2067     address_conflict = 0;
2068 
2069     if(local_port)
2070     {
2071 
2072         for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
2073         {
2074 
2075             /* Skip its own entry. */
2076             if((i == sockID) ||
2077                /* Skip invalid entries. */
2078                (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE)) ||
2079                /* Skip the entries with different protocol ID */
2080                (nx_bsd_socket_array[i].nx_bsd_socket_protocol != bsd_socket_ptr -> nx_bsd_socket_protocol) ||
2081                /* Skip the unbound entries */
2082                (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND)))
2083             {
2084 
2085                 continue;
2086             }
2087 
2088             /* Check for port number and interface ID */
2089             if(nx_bsd_socket_array[i].nx_bsd_socket_local_port == (USHORT)local_port)
2090             {
2091 
2092                 address_conflict = 1;
2093 
2094                 if((nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface == bsd_socket_ptr -> nx_bsd_socket_local_bind_interface) &&
2095                    (nx_bsd_socket_array[i].nx_bsd_socket_family == bsd_socket_ptr -> nx_bsd_socket_family))
2096                 {
2097 
2098                     /* This is completely duplicate binding.  */
2099 
2100                     /* If it is a TCP non-listen socket (in other words a TCP server socket that is
2101                        already in connection, and the REUSEADDR is set, it is OK. */
2102                     if((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED) &&
2103                        (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CLIENT)) &&
2104                        (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR))
2105                     {
2106 
2107                         address_conflict = 0;
2108                     }
2109                 }
2110                 else
2111                 {
2112 
2113                     /* If the REUSEADDR option is set, the socket can be bound to its specififed local address. */
2114                     if(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR)
2115                     {
2116 
2117                         address_conflict = 0;
2118 
2119                         if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
2120                         {
2121 
2122                             UINT counter;
2123 
2124                             /* For UDP socket, it needs to share the underlying NetX UDP socket. */
2125                             nx_udp_socket_delete(bsd_socket_ptr -> nx_bsd_socket_udp_socket);
2126 
2127                             /* Free the memory. */
2128                             memset((VOID*)bsd_socket_ptr -> nx_bsd_socket_udp_socket, 0, sizeof(NX_UDP_SOCKET));
2129 
2130                             tx_block_release((VOID*)bsd_socket_ptr -> nx_bsd_socket_udp_socket);
2131 
2132                             /* Add this bsd udp socket to the list that map to the same NetX udp socket. */
2133 
2134                             /* See if this is the only bsd udp socket on the list. */
2135                             if ((&nx_bsd_socket_array[i]) == nx_bsd_socket_array[i].nx_bsd_socket_next)
2136                             {
2137 
2138                                 /* Yes, the only bsd udp socket on the list. */
2139                                 /* Update the list. */
2140                                 bsd_socket_ptr -> nx_bsd_socket_next = &nx_bsd_socket_array[i];
2141                                 bsd_socket_ptr -> nx_bsd_socket_previous = &nx_bsd_socket_array[i];
2142                                 nx_bsd_socket_array[i].nx_bsd_socket_next = bsd_socket_ptr;
2143                                 nx_bsd_socket_array[i].nx_bsd_socket_previous = bsd_socket_ptr;
2144 
2145                             }
2146                             else
2147                             {
2148 
2149                                 /* At least one more bsd udp socket on this list. */
2150                                 /* Update the list. */
2151                                 bsd_socket_ptr -> nx_bsd_socket_next = nx_bsd_socket_array[i].nx_bsd_socket_next;
2152                                 bsd_socket_ptr -> nx_bsd_socket_previous = &nx_bsd_socket_array[i];
2153                                 (nx_bsd_socket_array[i].nx_bsd_socket_next) -> nx_bsd_socket_previous = bsd_socket_ptr;
2154                                 nx_bsd_socket_array[i].nx_bsd_socket_next = bsd_socket_ptr;
2155                             }
2156 
2157 
2158                             bsd_socket_ptr -> nx_bsd_socket_udp_socket = nx_bsd_socket_array[i].nx_bsd_socket_udp_socket;
2159 
2160                             /* Increase the counter. */
2161                             counter = (UINT)bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_reserved_ptr;
2162                             counter = ((counter & 0xFFFF0000) + 0x00010000 + (counter & 0x0000FFFF)) & 0xFFFFFFFF;
2163 
2164                             bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_reserved_ptr = (VOID*)counter;
2165 
2166                             bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)local_port;
2167                             bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
2168 
2169                             /* Release the protection mutex.  */
2170                             tx_mutex_put(nx_bsd_protection_ptr);
2171 
2172                             return(NX_SOC_OK);
2173                         }
2174                         else if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
2175                         {
2176 
2177                             /* Just point this BSD TCP socket to the same secondary socket. */
2178                             (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id;
2179 
2180                             bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
2181 
2182                             bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)local_port;
2183 #if defined(__PRODUCT_NETXDUO__) && !defined(NX_DISABLE_IPV4)
2184                             /* Handle client sockets differently. Share the port here for sockets with different IP/IPv6 addresses. */
2185                             if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_client_type == NX_TRUE)
2186                             {
2187 
2188                                 /* Handle client sockets differently. Share the port here for sockets with different IP/IPv6 addresses. */
2189                                 if (((bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6) && (nx_bsd_socket_array[i].nx_bsd_socket_family == AF_INET)) ||
2190                                     ((bsd_socket_ptr -> nx_bsd_socket_family == AF_INET) && (nx_bsd_socket_array[i].nx_bsd_socket_family == AF_INET6)))
2191 
2192                                 {
2193 
2194                                 NX_IP *ip_ptr = nx_bsd_default_ip;
2195                                 NX_TCP_SOCKET *socket_ptr = bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
2196 
2197 
2198                                     /* Calculate the hash index in the TCP port array of the associated IP instance.  */
2199                                     UINT index =  (UINT) ((local_port + (local_port >> 8)) & NX_TCP_PORT_TABLE_MASK);
2200 
2201                                     /* This non server socket needs to share a port with the other client socket. */
2202                                     socket_ptr -> nx_tcp_socket_port = (UINT)local_port;
2203 
2204 
2205                                     tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
2206 
2207                                     /* Add this socket to the list of bound sockets.  */
2208                                     socket_ptr -> nx_tcp_socket_bound_next =   ip_ptr -> nx_ip_tcp_port_table[index];
2209                                     socket_ptr -> nx_tcp_socket_bound_previous =  (ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous;
2210                                     ((ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous) -> nx_tcp_socket_bound_next =  socket_ptr;
2211                                     (ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous = socket_ptr;
2212 
2213 
2214                                     tx_mutex_put(&ip_ptr -> nx_ip_protection);
2215                                 }
2216                             }
2217 #endif
2218 
2219                             /* Release the protection mutex.  */
2220                             tx_mutex_put(nx_bsd_protection_ptr);
2221 
2222                             return(NX_SOC_OK);
2223                         }
2224                     }
2225                 }
2226 
2227                 if(address_conflict)
2228                 {
2229 
2230                     break; /* Break out of the for loop */
2231                 }
2232             }
2233         }
2234     }
2235 
2236 #ifdef NX_BSD_RAW_SUPPORT
2237     if (localAddress -> sa_family == AF_PACKET)
2238     {
2239         for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
2240         {
2241 
2242             /* Skip its own entry. */
2243             if((i == sockID) ||
2244                /* Skip invalid entries. */
2245                (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE)) ||
2246                /* Skip the entries with different protocol ID */
2247                (nx_bsd_socket_array[i].nx_bsd_socket_protocol != bsd_socket_ptr -> nx_bsd_socket_protocol) ||
2248                /* Skip the entries with different address family. */
2249                (nx_bsd_socket_array[i].nx_bsd_socket_family != bsd_socket_ptr -> nx_bsd_socket_family) ||
2250                /* Skip the unbound entries */
2251                (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND)))
2252             {
2253 
2254                 continue;
2255             }
2256 
2257             if (nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface_index == bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index)
2258             {
2259 
2260                 /* Bind to same interface. */
2261                 address_conflict = 1;
2262                 break;
2263             }
2264 
2265             if (nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface_index == NX_BSD_LOCAL_IF_INADDR_ANY)
2266             {
2267 
2268                 /* A socket is bound to any interface. */
2269                 address_conflict = 1;
2270                 break;
2271             }
2272         }
2273     }
2274 #endif /* NX_BSD_RAW_SUPPORT */
2275 
2276     if(address_conflict)
2277     {
2278 
2279         /* Release the protection mutex.  */
2280         tx_mutex_put(nx_bsd_protection_ptr);
2281 
2282         /* Set the socket error if extended socket options enabled. */
2283         nx_bsd_set_errno(EADDRINUSE);
2284 
2285         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
2286         return(NX_SOC_ERROR);
2287     }
2288 
2289     /* Mark this BSD socket as busy.  */
2290     bsd_socket_ptr -> nx_bsd_socket_busy = tx_thread_identify();
2291 
2292     /* Determine what type of bind is required.  */
2293     if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
2294     {
2295 
2296         /* Setup TCP socket pointer.  */
2297         tcp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
2298 
2299         /* Call NetX to bind the client socket.  */
2300         status =  nx_tcp_client_socket_bind(tcp_socket_ptr, (UINT)local_port, NX_NO_WAIT);
2301 
2302         /* Update the port. */
2303         if((status == NX_SUCCESS) && (local_port == 0))
2304             local_port = (INT)(tcp_socket_ptr -> nx_tcp_socket_port);
2305 
2306     }
2307     else if (bsd_socket_ptr -> nx_bsd_socket_udp_socket)
2308     {
2309 
2310         /* Set up a pointer to the UDP socket.  */
2311         udp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_udp_socket;
2312 
2313         /* Bind the UDP socket to the specified port in NetX.  */
2314         status =  nx_udp_socket_bind(udp_socket_ptr, (UINT)local_port, NX_BSD_TIMEOUT);
2315 
2316         /* Update the port. */
2317         if((status == NX_SUCCESS) && (local_port == 0))
2318             local_port = (INT)(udp_socket_ptr -> nx_udp_socket_port);
2319     }
2320     else
2321     {
2322 
2323         /* Raw socket.  All done.  Just need to set status = NX_SUCCESS and continue. */
2324         status = NX_SUCCESS;
2325     }
2326 
2327 
2328     /* Check if we were able to bind the port. */
2329     if (status == NX_SUCCESS)
2330     {
2331 
2332         bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)local_port;
2333         bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
2334 
2335 
2336         /* Make sure this thread is still the owner.  */
2337         if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
2338         {
2339 
2340             /* Clear the busy flag.  */
2341             bsd_socket_ptr -> nx_bsd_socket_busy =  TX_NULL;
2342         }
2343 
2344         /* Release the protection mutex.  */
2345         tx_mutex_put(nx_bsd_protection_ptr);
2346 
2347         /* Return successful status.  */
2348         return(NX_SOC_OK);
2349 
2350     }
2351 
2352     /* Release the protection mutex.  */
2353     tx_mutex_put(nx_bsd_protection_ptr);
2354 
2355     /* Set the socket error, if extended socket options enabled,  depending on the status returned by NetX. */
2356     nx_bsd_set_error_code(bsd_socket_ptr, status);
2357 
2358     /* Return an error, unsuccessful socket bind call.  */
2359     NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2360     return(NX_SOC_ERROR);
2361 
2362 }
2363 
2364 
2365 /**************************************************************************/
2366 /*                                                                        */
2367 /*  FUNCTION                                               RELEASE        */
2368 /*                                                                        */
2369 /*    listen                                              PORTABLE C      */
2370 /*                                                           6.3.0        */
2371 /*  AUTHOR                                                                */
2372 /*                                                                        */
2373 /*    Yuxin Zhou, Microsoft Corporation                                   */
2374 /*                                                                        */
2375 /*  DESCRIPTION                                                           */
2376 /*                                                                        */
2377 /*    This function sets the given socket ready to accept incoming client */
2378 /*    connections. The socket must already be associated with a local port*/
2379 /*    which means the bind() must have been called previously.            */
2380 /*    After this call, incoming TCP connections requests addressed to the */
2381 /*    local port (and IP address, if specified previously) will be        */
2382 /*    completed & queued until they are passed to the program via accept()*/
2383 /*                                                                        */
2384 /*  INPUT                                                                 */
2385 /*                                                                        */
2386 /*    sockID                                socket descriptor             */
2387 /*    backlog                               Maximum number of new         */
2388 /*                                          connections queued            */
2389 /*                                                                        */
2390 /*                                                                        */
2391 /*  OUTPUT                                                                */
2392 /*                                                                        */
2393 /*    NX_SOC_OK (0)                         If success                    */
2394 /*    NX_SOC_ERROR (-1)                     If failure.                   */
2395 /*                                                                        */
2396 /*  CALLS                                                                 */
2397 /*                                                                        */
2398 /*    socket                                Create a server socket        */
2399 /*    nx_tcp_server_socket_listen           Enable a server socket listen */
2400 /*    tx_mutex_get                          Get protection                */
2401 /*    tx_mutex_put                          Release protection            */
2402 /*                                                                        */
2403 /*                                                                        */
2404 /*  CALLED BY                                                             */
2405 /*                                                                        */
2406 /*    Application Code                                                    */
2407 /*                                                                        */
2408 /*  RELEASE HISTORY                                                       */
2409 /*                                                                        */
2410 /*    DATE              NAME                      DESCRIPTION             */
2411 /*                                                                        */
2412 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2413 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2414 /*                                            resulting in version 6.1    */
2415 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
2416 /*                                            used new API/structs naming,*/
2417 /*                                            resulting in version 6.3.0  */
2418 /*                                                                        */
2419 /**************************************************************************/
nx_bsd_listen(INT sockID,INT backlog)2420 INT  nx_bsd_listen(INT sockID, INT backlog)
2421 {
2422 
2423 UINT                status;
2424 NX_BSD_SOCKET      *bsd_socket_ptr;
2425 NX_BSD_SOCKET      *bsd_secondary_socket;
2426 INT                 secondary_sockID;
2427 INT                 ret;
2428 
2429 
2430     /* Check whether supplied socket ID is valid.  */
2431     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
2432     {
2433 
2434         /* Set the socket error if extended socket options enabled. */
2435         nx_bsd_set_errno(EBADF);
2436 
2437         /* Return an error. */
2438         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2439         return(NX_SOC_ERROR);
2440     }
2441 
2442     /* Normalize the socket ID.  */
2443     sockID =  sockID - NX_BSD_SOCKFD_START;
2444 
2445     /* Get the protection mutex.  */
2446     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
2447 
2448     /* Check the status.  */
2449     if (status)
2450     {
2451 
2452         /* Set the socket error if extended socket options enabled. */
2453         nx_bsd_set_errno(EACCES);
2454 
2455         /* Return an error. */
2456         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
2457         return(NX_SOC_ERROR);
2458     }
2459 
2460     /* Set up a pointer to the BSD socket.  */
2461     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
2462 
2463     /* Determine if the socket is a UDP socket or raw  */
2464     if (bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
2465     {
2466 
2467         /* The underlying protocol is not TCP, therefore it does not support the listen operation. */
2468         nx_bsd_set_errno(EOPNOTSUPP);
2469 
2470         /* Release the protection mutex.  */
2471         tx_mutex_put(nx_bsd_protection_ptr);
2472 
2473         /* Return an error code.  */
2474         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2475         return(NX_SOC_ERROR);
2476     }
2477 
2478     /* Is the socket still in use?  */
2479     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
2480     {
2481 
2482         /* Set the socket error if extended socket options enabled. */
2483         nx_bsd_set_errno(EBADF);
2484 
2485         /* Release the protection mutex.  */
2486         tx_mutex_put(nx_bsd_protection_ptr);
2487 
2488         /* Return error code.  */
2489         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2490         return(NX_SOC_ERROR);
2491     }
2492 
2493     /* Check if the socket has an error */
2494     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
2495     {
2496         INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
2497 
2498         /* Now clear the error code. */
2499         bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
2500 
2501         /* Clear the error flag.  The application is expected to close the socket at this point.*/
2502         bsd_socket_ptr -> nx_bsd_socket_status_flags =
2503             bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
2504 
2505         nx_bsd_set_errno(errcode);
2506 
2507         /* Release the protection mutex.  */
2508         tx_mutex_put(nx_bsd_protection_ptr);
2509 
2510         /* Return an error.  */
2511         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2512 
2513         /* At this point the error flag is cleared.  Application should
2514            detect and handle the error codition. This socket is still bound
2515            to the port (either the application called bind(), or a bind
2516            operation was executed as part of the connect call) is able to
2517            handle another "connect" call, or be closed. */
2518         return(NX_SOC_ERROR);
2519     }
2520 
2521     /* Have we already started listening?  */
2522     if (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN)
2523     {
2524 
2525         /* Error, socket is already listening.  */
2526 
2527         /* Release the protection mutex.  */
2528         tx_mutex_put(nx_bsd_protection_ptr);
2529 
2530         /* Set the socket error if extended socket options enabled. */
2531         nx_bsd_set_errno(EINVAL);
2532 
2533         /* Return error code.  */
2534         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2535         return(NX_SOC_ERROR);
2536     }
2537 
2538     /* Check if this is a secondary server socket.  */
2539     if (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET)
2540     {
2541 
2542         /* Error, socket is a secondary server socket.  */
2543 
2544         /* Release the protection mutex.  */
2545         tx_mutex_put(nx_bsd_protection_ptr);
2546 
2547         /* Set the socket error if extended socket options enabled. */
2548         nx_bsd_set_errno(EOPNOTSUPP);
2549 
2550         /* Return error code.  */
2551         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2552         return(NX_SOC_ERROR);
2553     }
2554 
2555     /* Check if bound to a port.  */
2556     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND))
2557     {
2558 
2559        /* Release the protection mutex.  */
2560        tx_mutex_put(nx_bsd_protection_ptr);
2561 
2562        /* Set the socket error code. */
2563        nx_bsd_set_errno(EDESTADDRREQ);
2564 
2565        /* Return error code.  */
2566        NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2567        return(NX_SOC_ERROR);
2568     }
2569 
2570     /* Check if this master (listening) socket's secondary socket is not marked invalid.  If not, it means this socket will
2571        share the secondary socket with another master socket. */
2572     if((bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id != NX_BSD_MAX_SOCKETS)
2573     {
2574 
2575         /* It is set. */
2576 
2577         secondary_sockID = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id;
2578 
2579         bsd_secondary_socket = &nx_bsd_socket_array[secondary_sockID];
2580 
2581         /* Now check if the other master socket is in listen mode. */
2582         if(bsd_secondary_socket -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN)
2583         {
2584 
2585             /* It  is ready.. we are ready to listen on this socket. */
2586 
2587             bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ENABLE_LISTEN;
2588             bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET);
2589             bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_client_type =  NX_FALSE;
2590             bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_SERVER_MASTER_SOCKET;
2591 
2592             /* Release the protection mutex.  */
2593             tx_mutex_put(nx_bsd_protection_ptr);
2594 
2595             return(NX_SOC_OK);
2596         }
2597     }
2598 
2599     if(backlog < NX_BSD_TCP_LISTEN_MIN_BACKLOG)
2600     {
2601         backlog = NX_BSD_TCP_LISTEN_MIN_BACKLOG;
2602     }
2603 
2604     /* We need to set up this socket as a listen socket. */
2605     ret = nx_bsd_tcp_create_listen_socket(sockID, backlog);
2606 
2607     /* Release the mutex protection.  */
2608     tx_mutex_put(nx_bsd_protection_ptr);
2609 
2610     /* Return success.  */
2611     return(ret);
2612 }
2613 
2614 
2615 /**************************************************************************/
2616 /*                                                                        */
2617 /*  FUNCTION                                               RELEASE        */
2618 /*                                                                        */
2619 /*    accept                                              PORTABLE C      */
2620 /*                                                           6.3.0        */
2621 /*  AUTHOR                                                                */
2622 /*                                                                        */
2623 /*    Yuxin Zhou, Microsoft Corporation                                   */
2624 /*                                                                        */
2625 /*  DESCRIPTION                                                           */
2626 /*                                                                        */
2627 /*    This function blocks while waiting for connections addressed to the */
2628 /*    IP address and port to which this socket is bound. A listen() must  */
2629 /*    previously have been called on this given socket.                   */
2630 /*                                                                        */
2631 /*    When a connection arrives and the TCP handshake is successfully     */
2632 /*    completed, this function returns with a new socket with local and   */
2633 /*    remote address and port numbers filled in.                          */
2634 /*                                                                        */
2635 /*    For non blocking sockets, this function returns immediately.        */
2636 /*                                                                        */
2637 /*  INPUT                                                                 */
2638 /*                                                                        */
2639 /*     sockID                               socket descriptor             */
2640 /*     clientAddress                        Originating socket IP address */
2641 /*                                          and port.                     */
2642 /*     addressLength                        Length of sockaddr buffer (in)*/
2643 /*                                          returned address (out)        */
2644 /*                                                                        */
2645 /*  OUTPUT                                                                */
2646 /*                                                                        */
2647 /*    socket id                             Socket ID for new connection  */
2648 /*    NX_SOC_ERROR (-1)                     If failure                    */
2649 /*                                                                        */
2650 /*  CALLS                                                                 */
2651 /*                                                                        */
2652 /*    memset                                Clears memory                 */
2653 /*    socket                                Create a server socket        */
2654 /*    nx_tcp_server_socket_relisten         Relisten with a new TCP soc   */
2655 /*    nx_tcp_server_socket_accept           Accept a client connection    */
2656 /*    tx_mutex_get                          Get protection                */
2657 /*    tx_mutex_put                          Release protection            */
2658 /*    tx_thread_identify                    Gets the current thread       */
2659 /*                                                                        */
2660 /*  CALLED BY                                                             */
2661 /*                                                                        */
2662 /*    Application Code                                                    */
2663 /*                                                                        */
2664 /*  RELEASE HISTORY                                                       */
2665 /*                                                                        */
2666 /*    DATE              NAME                      DESCRIPTION             */
2667 /*                                                                        */
2668 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2669 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
2670 /*                                            verified memcpy use cases,  */
2671 /*                                            resulting in version 6.1    */
2672 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
2673 /*                                            used new API/structs naming,*/
2674 /*                                            resulting in version 6.3.0  */
2675 /*                                                                        */
2676 /**************************************************************************/
nx_bsd_accept(INT sockID,struct nx_bsd_sockaddr * ClientAddress,INT * addressLength)2677 INT  nx_bsd_accept(INT sockID, struct nx_bsd_sockaddr *ClientAddress, INT *addressLength)
2678 {
2679 /* Define the accept function if NetX BSD accept() is not set to asynchronous (on automatic callback). */
2680 
2681 UINT                status;
2682 NX_BSD_SOCKET       *bsd_socket_ptr;
2683 NX_BSD_SOCKET       *bsd_secondary_socket;
2684 INT                 sec_sock_id;
2685 INT                 ret = 0;
2686 INT                 connected = 0;
2687 ULONG               requested_events;
2688 INT                 secondary_socket_id = 0;
2689 #ifndef NX_DISABLE_IPV4
2690 struct nx_bsd_sockaddr_in
2691                     peer4_address;
2692 #endif /* NX_DISABLE_IPV4 */
2693 #ifdef FEATURE_NX_IPV6
2694 struct nx_bsd_sockaddr_in6
2695                     peer6_address;
2696 #endif
2697 
2698 
2699     /* Check for valid socket ID.  */
2700     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
2701     {
2702 
2703         /* Set the socket error if extended socket options enabled. */
2704         nx_bsd_set_errno(EBADF);
2705 
2706         /* Return an error.*/
2707         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2708         return(NX_SOC_ERROR);
2709     }
2710 
2711     /* Normalize the socket ID.  */
2712     sockID =  sockID - NX_BSD_SOCKFD_START;
2713 
2714     /* Setup pointer to the BSD socket.  */
2715     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
2716 
2717     /* Get the protection mutex.  */
2718     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
2719 
2720     /* Check the status.  */
2721     if (status != NX_SUCCESS)
2722     {
2723 
2724         /* Set the socket error if extended socket options enabled. */
2725         nx_bsd_set_errno(EACCES);
2726 
2727         /* Return an error.*/
2728         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
2729         return(NX_SOC_ERROR);
2730     }
2731 
2732     /* Is the socket still in use?  */
2733     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
2734     {
2735 
2736         /* Release the protection mutex.  */
2737         tx_mutex_put(nx_bsd_protection_ptr);
2738 
2739         /* Set the socket error if extended socket options enabled. */
2740         nx_bsd_set_errno(EBADF);
2741 
2742         /* Return an error.  */
2743         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2744         return(NX_SOC_ERROR);
2745     }
2746 
2747     /* If the socket has an error */
2748     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
2749     {
2750 
2751         INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
2752 
2753         /* Now clear the error code. */
2754         bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
2755 
2756         /* Clear the error flag.  The application is expected to close the socket at this point.*/
2757         bsd_socket_ptr -> nx_bsd_socket_status_flags =
2758             bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
2759 
2760         nx_bsd_set_errno(errcode);
2761 
2762         /* Release the protection mutex.  */
2763         tx_mutex_put(nx_bsd_protection_ptr);
2764 
2765         /* Return an error.  */
2766         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2767 
2768         /* At this point the error flag is cleared.  Application should
2769            detect and handle the error codition. This socket is still bound
2770            to the port (either the application called bind(), or a bind
2771            operation was executed as part of the connect call) is able to
2772 
2773            handle another "connect" call, or be closed. */
2774         return(NX_SOC_ERROR);
2775     }
2776 
2777     /* Determine if the socket is a UDP socket.  */
2778     if (bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
2779     {
2780 
2781         /* Error, UDP or raw sockets do not perform listen.  */
2782 
2783         /* Release the protection mutex.  */
2784         tx_mutex_put(nx_bsd_protection_ptr);
2785 
2786         /* Set the socket error if extended socket options enabled. */
2787         nx_bsd_set_errno(EOPNOTSUPP);
2788 
2789         /* Return error code.  */
2790         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2791         return(NX_SOC_ERROR);
2792     }
2793 
2794     /* Has listening been enabled on this socket?  */
2795     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN))
2796     {
2797 
2798         /* No, this socket is not ready to accept TCP connections. */
2799 
2800         /* Release the protection mutex.  */
2801         tx_mutex_put(nx_bsd_protection_ptr);
2802 
2803         /* Set the socket error if extended socket options enabled. */
2804         nx_bsd_set_errno(EINVAL);
2805 
2806         /* Return error code.  */
2807         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2808         return(NX_SOC_ERROR);
2809     }
2810 
2811     /* Make sure the accept call operates on the master socket. */
2812     if((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) == 0)
2813     {
2814         /* This is not a master socket.
2815            BSD accept is only allowed on the master socket.
2816            Return. */
2817 
2818         /* Release the protection mutex.  */
2819         tx_mutex_put(nx_bsd_protection_ptr);
2820 
2821         /* Set the socket error if extended socket options enabled. */
2822         nx_bsd_set_errno(EBADF);
2823 
2824         /* Return error code.  */
2825         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2826         return(NX_SOC_ERROR);
2827     }
2828 
2829     /* Validate the secondary server socket.  */
2830     if ((bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id >= NX_BSD_MAX_SOCKETS)
2831     {
2832 
2833         /* This secondary socket is not available yet.  This could happen if the
2834            previous accept call fails to allocate a new secondary socket. */
2835         ret = nx_bsd_tcp_create_listen_socket(sockID, 0);
2836 
2837         if(ret < 0)
2838         {
2839 
2840             /* Failed to allocate a secondary socket, release the protection mutex.  */
2841             tx_mutex_put(nx_bsd_protection_ptr);
2842 
2843             /* Errno is already set inside nx_bsd_tcp_create_listen_socket.  Therefore
2844                there is no need to set errno here. */
2845 
2846             /* Return an error. */
2847             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2848             return(NX_SOC_ERROR);
2849         }
2850     }
2851 
2852     /* At this point, we have found and marked a secondary server socket for the connection request.  */
2853 
2854     /* Set up a pointer to the secondary server socket.  */
2855     sec_sock_id = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id;
2856     bsd_secondary_socket =  &nx_bsd_socket_array[sec_sock_id];
2857 
2858     /* Mark this BSD socket as busy.  */
2859     bsd_socket_ptr -> nx_bsd_socket_busy = tx_thread_identify();
2860 
2861     /* If the master socket is marked as non-blocking, we just need to check if the
2862        secondary socket has a connection already. */
2863     while(!connected)
2864     {
2865 
2866         secondary_socket_id = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id;
2867 
2868         if((secondary_socket_id < NX_BSD_MAX_SOCKETS) &&
2869            (nx_bsd_socket_array[secondary_socket_id].nx_bsd_socket_union_id.nx_bsd_socket_master_socket_id == sockID) &&
2870            (nx_bsd_socket_array[secondary_socket_id].nx_bsd_socket_status_flags & (NX_BSD_SOCKET_CONNECTED | NX_BSD_SOCKET_ERROR)))
2871         {
2872 
2873             connected = 1;
2874             bsd_secondary_socket = &nx_bsd_socket_array[secondary_socket_id];
2875             bsd_secondary_socket -> nx_bsd_socket_family = bsd_socket_ptr -> nx_bsd_socket_family;
2876             bsd_secondary_socket -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
2877 
2878         }
2879         else
2880         {
2881 
2882             if(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING)
2883             {
2884 
2885                 /* No connection yet. Return EWOULDBLOCK */
2886 
2887                 tx_mutex_put(nx_bsd_protection_ptr);
2888 
2889                 /* Set the socket error if extended socket options enabled. */
2890                 nx_bsd_set_errno(EWOULDBLOCK);
2891 
2892                 /* Return an error. */
2893                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2894 
2895                 if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
2896                 {
2897                     bsd_socket_ptr -> nx_bsd_socket_busy = NX_NULL;
2898                 }
2899                 return(NX_SOC_ERROR);
2900             }
2901 
2902             tx_mutex_put(nx_bsd_protection_ptr);
2903             tx_event_flags_get(&nx_bsd_events, NX_BSD_RECEIVE_EVENT, TX_OR_CLEAR, &requested_events, TX_WAIT_FOREVER);
2904             tx_mutex_get(nx_bsd_protection_ptr, TX_WAIT_FOREVER);
2905 
2906             /* Verify the socket is still valid. */
2907             if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
2908             {
2909                 /* The socket is no longer in use. */
2910 
2911                 /* Set the socket error code. */
2912                 nx_bsd_set_errno(EBADF);
2913 
2914                 /* Release the protection mutex.  */
2915                 tx_mutex_put(nx_bsd_protection_ptr);
2916 
2917                 /* Return error code.  */
2918                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2919                 return(NX_SOC_ERROR);
2920             }
2921         }
2922     }
2923 
2924     /* If we get here, we should have a valid connection, or an error occured. */
2925     if(bsd_secondary_socket -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
2926     {
2927         INT errcode = bsd_secondary_socket -> nx_bsd_socket_error_code;
2928 
2929         /* Now clear the error code. */
2930         bsd_secondary_socket -> nx_bsd_socket_error_code = 0;
2931 
2932         /* Clear the error flag.  The application is expected to close the socket at this point.*/
2933         bsd_secondary_socket -> nx_bsd_socket_status_flags =
2934             bsd_secondary_socket -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
2935 
2936         nx_bsd_set_errno(errcode);
2937 
2938         /* Return an error.  */
2939         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2940 
2941         /* Release the protection mutex.  */
2942         tx_mutex_put(nx_bsd_protection_ptr);
2943 
2944         /* At this point the error flag is cleared.  Application should
2945            detect and handle the error codition. This socket is still bound
2946            to the port (either the application called bind(), or a bind
2947            operation was executed as part of the connect call) is able to
2948            handle another "connect" call, or be closed. */
2949         return(NX_SOC_ERROR);
2950     }
2951 
2952     /* Update the BSD socket source port and sender IP address. */
2953     status = nxd_tcp_socket_peer_info_get(bsd_secondary_socket -> nx_bsd_socket_tcp_socket,
2954                                           &bsd_secondary_socket -> nx_bsd_socket_source_ip_address,
2955                                           (ULONG *)(&bsd_secondary_socket -> nx_bsd_socket_source_port));
2956 
2957     memcpy(&bsd_secondary_socket -> nx_bsd_socket_peer_ip, &bsd_secondary_socket -> nx_bsd_socket_source_ip_address,  sizeof(NXD_ADDRESS)); /* Use case of memcpy is verified. */
2958 
2959     bsd_secondary_socket -> nx_bsd_socket_peer_port = (USHORT)(bsd_secondary_socket -> nx_bsd_socket_source_port);
2960 
2961     /* Record the peer information. */
2962 #ifndef NX_DISABLE_IPV4
2963     if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
2964     {
2965 
2966         bsd_secondary_socket -> nx_bsd_socket_source_ip_address.nxd_ip_address.v4 =
2967                 bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v4;
2968     }
2969 #endif /* NX_DISABLE_IPV4 */
2970 #ifdef FEATURE_NX_IPV6
2971     if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
2972     {
2973 
2974         bsd_secondary_socket -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[0] = bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[0];
2975         bsd_secondary_socket -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[1] = bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[1];
2976         bsd_secondary_socket -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[2] = bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[2];
2977         bsd_secondary_socket -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[3] = bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[3];
2978     }
2979 #endif
2980 
2981     /* Attempt to obtain peer address if ClientAddress is not NULL. */
2982     if(ClientAddress && addressLength != 0)
2983     {
2984 
2985 #ifndef NX_DISABLE_IPV4
2986         /* Handle the IPv4 socket type. */
2987         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
2988         {
2989 
2990             /* Update the Client address with socket family, remote host IPv4 address and port.  */
2991             peer4_address.sin_family =      AF_INET;
2992             peer4_address.sin_addr.s_addr = ntohl(bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v4);
2993             peer4_address.sin_port =        ntohs((USHORT)bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_port);
2994 
2995             /* Copy the peer address/port info to the ClientAddress.  Truncate if
2996                addressLength is smaller than the size of struct sockaddr_in */
2997             if(*addressLength > (INT)sizeof(struct nx_bsd_sockaddr_in))
2998             {
2999 
3000                 memcpy(ClientAddress, &peer4_address, sizeof(struct nx_bsd_sockaddr_in)); /* Use case of memcpy is verified. */
3001                 *addressLength = sizeof(struct nx_bsd_sockaddr_in);
3002             }
3003             else
3004             {
3005                 memcpy(ClientAddress, &peer4_address, (UINT)(*addressLength)); /* Use case of memcpy is verified. */
3006             }
3007         }
3008         else
3009 #endif /* NX_DISABLE_IPV4 */
3010 
3011 #ifdef FEATURE_NX_IPV6
3012         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
3013         {
3014 
3015             /* Update the Client address with socket family, remote host IPv6 address and port.  */
3016             peer6_address.sin6_family = AF_INET6;
3017 
3018             peer6_address.sin6_addr._S6_un._S6_u32[0] = ntohl(bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[0]);
3019             peer6_address.sin6_addr._S6_un._S6_u32[1] = ntohl(bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[1]);
3020             peer6_address.sin6_addr._S6_un._S6_u32[2] = ntohl(bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[2]);
3021             peer6_address.sin6_addr._S6_un._S6_u32[3] = ntohl(bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[3]);
3022 
3023             peer6_address.sin6_port = ntohs((USHORT)bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_port);
3024 
3025             if((*addressLength) > (INT)sizeof(peer6_address))
3026             {
3027 
3028                 memcpy(ClientAddress, &peer6_address, sizeof(peer6_address)); /* Use case of memcpy is verified. */
3029                 *addressLength = sizeof(peer6_address);
3030             }
3031             else
3032             {
3033                 memcpy(ClientAddress, &peer6_address, (UINT)(*addressLength)); /* Use case of memcpy is verified. */
3034             }
3035         }
3036         else
3037 #endif /* !FEATURE_NX_IPV6 */
3038         {
3039 
3040             /* Release the protection mutex.  */
3041             tx_mutex_put(nx_bsd_protection_ptr);
3042 
3043             /* Set the socket error if extended socket options enabled. */
3044             nx_bsd_set_errno(EINVAL);
3045 
3046             /* Make sure this thread is still the owner.  */
3047             if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
3048             {
3049 
3050                 /* Clear the busy flag.  */
3051                 bsd_socket_ptr -> nx_bsd_socket_busy =  TX_NULL;
3052             }
3053 
3054             /* Error, IPv6 support is not enabled.  */
3055             NX_BSD_ERROR(ERROR, __LINE__);
3056             return(ERROR);
3057         }
3058     }
3059 
3060     /* Mark the sock_id field in both the master and secondary socket invalid. */
3061     (bsd_secondary_socket -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id = NX_BSD_MAX_SOCKETS;
3062 
3063     /* Clear the master socket connect flags. */
3064     bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTED);
3065     bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_REQUEST);
3066 
3067     /* Reset the master_socket_id */
3068     ret = nx_bsd_tcp_create_listen_socket(sockID, 0);
3069 
3070     if(ret < 0)
3071     {
3072         (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = NX_BSD_MAX_SOCKETS;
3073     }
3074 
3075     /* Make sure this thread is still the owner.  */
3076     if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
3077     {
3078 
3079         /* Clear the busy flag.  */
3080         bsd_socket_ptr -> nx_bsd_socket_busy =  TX_NULL;
3081     }
3082 
3083     /* Release the protection mutex.  */
3084     tx_mutex_put(nx_bsd_protection_ptr);
3085 
3086     return(secondary_socket_id + NX_BSD_SOCKFD_START);
3087 
3088 }
3089 
3090 /**************************************************************************/
3091 /*                                                                        */
3092 /*  FUNCTION                                               RELEASE        */
3093 /*                                                                        */
3094 /*    nx_bsd_send_internal                                PORTABLE C      */
3095 /*                                                           6.3.0        */
3096 /*  AUTHOR                                                                */
3097 /*                                                                        */
3098 /*    Yuxin Zhou, Microsoft Corporation                                   */
3099 /*                                                                        */
3100 /*  DESCRIPTION                                                           */
3101 /*                                                                        */
3102 /*    This is sends a message to a given destination address/port         */
3103 /*                                                                        */
3104 /*  INPUT                                                                 */
3105 /*                                                                        */
3106 /*    sockID                                BSD Socket ID                 */
3107 /*    msg                                   Pointer to the outgoing       */
3108 /*                                            message                     */
3109 /*    msgLength                             The Size of the message       */
3110 /*    flags                                 Control flags, support        */
3111 /*                                            MSG_DONTWAIT                */
3112 /*    dst_address                           The Destination Address       */
3113 /*    dst_port                              The Destination Port          */
3114 /*    local_inteterface_index               The local outgoing interface  */
3115 /*                                            to use                      */
3116 /*                                                                        */
3117 /*  OUTPUT                                                                */
3118 /*                                                                        */
3119 /*    data_sent                                                           */
3120 /*                                                                        */
3121 /*  CALLS                                                                 */
3122 /*                                                                        */
3123 /*    set_errno                             Sets the BSD errno            */
3124 /*    nx_packet_allocate                    Allocate a packet             */
3125 /*    nx_packet_data_append                 Append data to the packet     */
3126 /*    tx_mutex_get                          Get Mutex protection          */
3127 /*    tx_mutex_put                          Release Mutex protection      */
3128 /*    nx_packet_release                     Release the packet on error   */
3129 /*    nx_udp_socket_send                    UDP packet send               */
3130 /*    nx_udp_socket_interface_send          UDP packet send via a         */
3131 /*                                            specific interface          */
3132 /*    nx_tcp_socket_send                    TCP packet send               */
3133 /*    _nxd_bsd_ipv4_packet_send             Raw IPv4 packet with header   */
3134 /*                                            included                    */
3135 /*    _nxd_bsd_ipv6_packet_send             Raw IPv6 packet with header   */
3136 /*                                            included                    */
3137 /*    nxd_ip_raw_packet_interface_send      Raw packet send via a         */
3138 /*                                            specific interface          */
3139 /*  CALLED BY                                                             */
3140 /*                                                                        */
3141 /*    send                                                                */
3142 /*    sendto                                                              */
3143 /*                                                                        */
3144 /*  RELEASE HISTORY                                                       */
3145 /*                                                                        */
3146 /*    DATE              NAME                      DESCRIPTION             */
3147 /*                                                                        */
3148 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3149 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3150 /*                                            resulting in version 6.1    */
3151 /*  10-31-2023     Tiejun Zhou              Modified comment(s),          */
3152 /*                                            supported random IP id,     */
3153 /*                                            resulting in version 6.3.0  */
3154 /*                                                                        */
3155 /**************************************************************************/
nx_bsd_send_internal(INT sockID,const CHAR * msg,INT msgLength,INT flags,NXD_ADDRESS * dst_address,USHORT dst_port,UINT local_interface_index)3156 static INT nx_bsd_send_internal(INT sockID, const CHAR *msg, INT msgLength, INT flags,
3157                                 NXD_ADDRESS *dst_address, USHORT dst_port, UINT local_interface_index)
3158 {
3159 UINT                status;
3160 NX_PACKET           *packet_ptr;
3161 NX_TCP_SOCKET       *tcp_socket_ptr;
3162 NX_UDP_SOCKET       *udp_socket_ptr;
3163 NX_BSD_SOCKET       *bsd_socket_ptr;
3164 UINT                packet_type = 0;
3165 UINT                wait_option;
3166 ULONG               data_sent = (ULONG)msgLength;
3167 
3168     bsd_socket_ptr = &nx_bsd_socket_array[sockID];
3169 
3170 #ifndef NX_DISABLE_IPV4
3171     /* Determine the socket family for allocating a packet. */
3172     if (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
3173     {
3174 
3175         /* This is for an IPv4 socket.   */
3176         if (bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
3177         {
3178 
3179             /* Allocate an IPv4 UDP packet.   */
3180             packet_type = NX_IPv4_UDP_PACKET;
3181         }
3182         else if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
3183         {
3184 
3185             /* Allocate an IPv4 TCP packet.   */
3186             packet_type = NX_IPv4_TCP_PACKET;
3187         }
3188         else if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE)
3189         {
3190 
3191             packet_type = NX_PHYSICAL_HEADER;
3192         }
3193         else
3194         {
3195 
3196             /* Raw socket. */
3197             packet_type = NX_IPv4_PACKET;
3198         }
3199     }
3200 #endif /* NX_DISABLE_IPV4 */
3201     if (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
3202     {
3203 
3204         /* This is for an IPv6 socket.   */
3205         if (bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
3206         {
3207 
3208             /* Allocate an IPv4 UDP packet.   */
3209             packet_type = NX_IPv6_UDP_PACKET;
3210         }
3211         else if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
3212         {
3213             /* Allocate an IPv4 TCP packet.   */
3214             packet_type = NX_IPv6_TCP_PACKET;
3215         }
3216         else if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE)
3217         {
3218             packet_type = NX_PHYSICAL_HEADER;
3219         }
3220         else
3221         {
3222             /* Raw socket. */
3223             packet_type = NX_IPv6_PACKET;
3224         }
3225     }
3226 
3227     /* Allocate the packet for sending.  */
3228     if(packet_type == 0)
3229     {
3230         /* Set the socket error.  */
3231         nx_bsd_set_errno(EINVAL);
3232 
3233         /* Return an error status.*/
3234         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3235         return(NX_SOC_ERROR);
3236     }
3237 
3238     /* Is this a non blocking socket? */
3239     if ((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING) ||
3240         (flags & MSG_DONTWAIT))
3241     {
3242 
3243         /* Yes, set to wait to zero on the NetX call. */
3244         wait_option = 0 ;
3245     }
3246     /* Does this socket have a send timeout option set? */
3247     else if (bsd_socket_ptr -> nx_bsd_option_send_timeout)
3248     {
3249 
3250         /* Yes, this is our wait option. */
3251         wait_option = bsd_socket_ptr -> nx_bsd_option_send_timeout;
3252     }
3253     else
3254         wait_option = TX_WAIT_FOREVER;
3255 
3256     status =  nx_packet_allocate(nx_bsd_default_packet_pool, &packet_ptr, packet_type, wait_option);
3257 
3258     /* Check for errors.   */
3259     if (status != NX_SUCCESS)
3260     {
3261 
3262         /* Set the socket error.  */
3263         nx_bsd_set_errno(ENOBUFS);
3264 
3265         /* Return an error status.*/
3266         NX_BSD_ERROR(status, __LINE__);
3267         return(NX_SOC_ERROR);
3268     }
3269 
3270     /* Now copy the data into the NetX packet.  */
3271     status =  nx_packet_data_append(packet_ptr, (VOID *) msg, (ULONG)msgLength, nx_bsd_default_packet_pool, wait_option);
3272 
3273     /* Was the data copy successful?  */
3274     if (status != NX_SUCCESS)
3275     {
3276 
3277         nx_packet_release(packet_ptr);
3278 
3279         /* Set the socket error.  */
3280         nx_bsd_set_errno(ENOBUFS);
3281 
3282         /* Return an error status.*/
3283         NX_BSD_ERROR(status, __LINE__);
3284         return(NX_SOC_ERROR);
3285     }
3286 
3287 
3288     /* Get the protection mutex.  */
3289     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
3290 
3291     /* Check the status.  */
3292     if (status != NX_SUCCESS)
3293     {
3294 
3295         /* Release the packet.  */
3296         nx_packet_release(packet_ptr);
3297 
3298         /* Set the socket error if extended socket options enabled. */
3299         nx_bsd_set_errno(EACCES);
3300 
3301         /* Return an error status.*/
3302         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
3303         return(NX_SOC_ERROR);
3304     }
3305 
3306 
3307     /* Is the socket still in use?  */
3308     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
3309     {
3310 
3311         nx_packet_release(packet_ptr);
3312 
3313         /* Set the socket error if extended options enabled. */
3314         nx_bsd_set_errno(EBADF);
3315 
3316         /* Release the protection mutex.  */
3317         tx_mutex_put(nx_bsd_protection_ptr);
3318 
3319         /* Return an error status.*/
3320         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3321         return(NX_SOC_ERROR);
3322     }
3323 
3324 
3325     /* Determine if the socket is a UDP socket.  */
3326     if (bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
3327     {
3328 
3329          /* Pickup the NetX UDP socket.  */
3330          udp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_udp_socket;
3331 
3332          /* Send the UDP packet.  */
3333          if(local_interface_index == NX_BSD_LOCAL_IF_INADDR_ANY)
3334              status =  nxd_udp_socket_send(udp_socket_ptr, packet_ptr, dst_address, dst_port);
3335          else
3336              status =  nxd_udp_socket_interface_send(udp_socket_ptr, packet_ptr, dst_address, dst_port, local_interface_index);
3337     }
3338     else if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
3339     {
3340 
3341         /* We have a TCP socket and a packet ready to send.  */
3342 
3343         /* Set a pointer to the TCP BSD socket.  */
3344         tcp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
3345 
3346         if(wait_option != TX_NO_WAIT)
3347         {
3348             /* Release the protection mutex.  */
3349             tx_mutex_put(nx_bsd_protection_ptr);
3350         }
3351 
3352         /* Send the TCP packet.  */
3353         status =  nx_tcp_socket_send(tcp_socket_ptr, packet_ptr, wait_option);
3354 
3355         /* Check partial data sent. */
3356         if (status)
3357         {
3358 
3359             /* Get length of data sent. */
3360             data_sent -= packet_ptr -> nx_packet_length;
3361 
3362             if (data_sent)
3363             {
3364 
3365                 /* Partial data sent. Mark as success. */
3366                 status = NX_SUCCESS;
3367 
3368                 /* Release the packet.  */
3369                 nx_packet_release(packet_ptr);
3370             }
3371         }
3372 
3373         if(wait_option != TX_NO_WAIT)
3374         {
3375             /* Obtain the protection mutex.  */
3376             tx_mutex_get(nx_bsd_protection_ptr, TX_WAIT_FOREVER);
3377         }
3378     }
3379     else
3380     {
3381         /* Is this BSD socket configured to append the IP header? */
3382         if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE)
3383         {
3384 
3385         /* Yes it is. Make sure the packet source and destination interface are set. */
3386         ULONG *ip_addr_ptr;
3387         UINT   src_interface;
3388 
3389 #ifndef NX_DISABLE_IPV4
3390             if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
3391             {
3392 
3393                 ip_addr_ptr = (ULONG*)(packet_ptr -> nx_packet_prepend_ptr + 12);
3394 
3395                 src_interface = (UINT)nx_bsd_find_interface_by_source_addr(AF_INET, ip_addr_ptr);
3396 
3397                 if(src_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
3398                     src_interface = 0;
3399 
3400                 packet_ptr -> nx_packet_address.nx_packet_interface_ptr = &(nx_bsd_default_ip -> nx_ip_interface[src_interface]);
3401 
3402                 /* If the IP ID field is non-zero, the current nx_ip_packet_id
3403                    value is modified */
3404                 if((*(packet_ptr -> nx_packet_prepend_ptr + 4) == 0) &&
3405                    (*(packet_ptr -> nx_packet_prepend_ptr + 5) == 0))
3406                 {
3407 
3408 #ifdef NX_ENABLE_IP_ID_RANDOMIZATION
3409                     ULONG rand_id = (ULONG)NX_RAND();
3410                     *(packet_ptr -> nx_packet_prepend_ptr + 4) = (UCHAR)((rand_id & 0xFFFF) >> 8);
3411                     *(packet_ptr -> nx_packet_prepend_ptr + 5) = (UCHAR)(rand_id & 0xFF);
3412 #else
3413                     *(packet_ptr -> nx_packet_prepend_ptr + 4) = (UCHAR)(((nx_bsd_default_ip -> nx_ip_packet_id) & 0xFFFF) >> 8);
3414                     *(packet_ptr -> nx_packet_prepend_ptr + 5) = (UCHAR)((nx_bsd_default_ip -> nx_ip_packet_id) & 0xFF);
3415 #endif /* NX_ENABLE_IP_ID_RANDOMIZATION */
3416                 }
3417 
3418                 /* Clear the checksum field. */
3419                 *(packet_ptr -> nx_packet_prepend_ptr + 10) = 0;
3420                 *(packet_ptr -> nx_packet_prepend_ptr + 11) = 0;
3421 
3422                 _nxd_bsd_ipv4_packet_send(packet_ptr);
3423 
3424                 status = NX_SUCCESS;
3425             }
3426 #endif /* NX_DISABLE_IPV4 */
3427 #ifdef FEATURE_NX_IPV6
3428             if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
3429             {
3430 
3431                 ip_addr_ptr = (ULONG*)(packet_ptr -> nx_packet_prepend_ptr + 8);
3432                 src_interface = (UINT)nx_bsd_find_interface_by_source_addr(AF_INET6, ip_addr_ptr);
3433 
3434                 if(src_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
3435                 {
3436                     status = NX_NOT_SUCCESSFUL;
3437                 }
3438 
3439                 else
3440                 {
3441 
3442                     NX_IPV6_HEADER *ipv6_header;
3443                     ULONG src_addr[4], dest_addr[4];
3444 
3445                     packet_ptr -> nx_packet_ip_header = packet_ptr -> nx_packet_prepend_ptr;
3446 
3447                     packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr = &nx_bsd_default_ip -> nx_ipv6_address[src_interface];
3448 
3449                     ipv6_header = (NX_IPV6_HEADER*)packet_ptr -> nx_packet_ip_header;
3450 
3451                     /* Set up source / Destination IP */
3452                     COPY_IPV6_ADDRESS(ipv6_header -> nx_ip_header_destination_ip, dest_addr);
3453                     COPY_IPV6_ADDRESS(ipv6_header -> nx_ip_header_source_ip, src_addr);
3454                     NX_IPV6_ADDRESS_CHANGE_ENDIAN(dest_addr);
3455                     NX_IPV6_ADDRESS_CHANGE_ENDIAN(src_addr);
3456 
3457 
3458                     _nxd_bsd_ipv6_packet_send(packet_ptr, src_addr, dest_addr);
3459 
3460                     status = NX_SUCCESS;
3461                 }
3462             }
3463 #endif
3464         }
3465         else
3466         {
3467 
3468             /* Raw socket without any IP header appended yet. We can send this directly to the NetX Duo IP packet handler.  */
3469             if(local_interface_index == NX_BSD_LOCAL_IF_INADDR_ANY)
3470                 local_interface_index = 0;
3471 
3472             status = nxd_ip_raw_packet_interface_send(nx_bsd_default_ip, packet_ptr, dst_address,
3473                                                       local_interface_index, bsd_socket_ptr -> nx_bsd_socket_protocol,
3474                                                       NX_IP_TIME_TO_LIVE, NX_IP_NORMAL);
3475         }
3476     }
3477 
3478     /* Was the packet send successful?  */
3479     if (status != NX_SUCCESS)
3480     {
3481 
3482         /* No, release the packet.  */
3483         nx_packet_release(packet_ptr);
3484 
3485         /* Set the socket error.  */
3486 
3487         /* Set the socket error according to the NetX error status returned.  */
3488         switch (status)
3489         {
3490 
3491             case NX_IP_ADDRESS_ERROR:
3492                 nx_bsd_set_errno(EDESTADDRREQ);
3493                 break;
3494 
3495             case NX_NOT_ENABLED:
3496                 nx_bsd_set_errno(EPROTONOSUPPORT);
3497                 break;
3498 
3499             case NX_NOT_CONNECTED:
3500                 nx_bsd_set_errno(ENOTCONN);
3501                 break;
3502 
3503             case NX_NO_PACKET:
3504             case NX_UNDERFLOW:
3505                 nx_bsd_set_errno(ENOBUFS);
3506                 break;
3507 
3508             case NX_WINDOW_OVERFLOW:
3509             case NX_WAIT_ABORTED:
3510             case NX_TX_QUEUE_DEPTH:
3511                 if ((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING) ||
3512                     (flags & MSG_DONTWAIT))
3513                     nx_bsd_set_errno( EWOULDBLOCK);
3514                 else
3515                     nx_bsd_set_errno(ETIMEDOUT);
3516                 break;
3517 
3518             default:
3519                 /* NX_NOT_BOUND */
3520                 /* NX_PTR_ERROR */
3521                 /* NX_INVALID_PACKET */
3522                 nx_bsd_set_errno(EINVAL);
3523                 break;
3524         }
3525 
3526         /* Return an error status. */
3527         NX_BSD_ERROR(status, __LINE__);
3528 
3529         /* Release the protection mutex.  */
3530         tx_mutex_put(nx_bsd_protection_ptr);
3531 
3532         return(NX_SOC_ERROR);
3533     }
3534 
3535     /* Release the protection mutex.  */
3536     tx_mutex_put(nx_bsd_protection_ptr);
3537 
3538     return((INT)data_sent);
3539 }
3540 
3541 /**************************************************************************/
3542 /*                                                                        */
3543 /*  FUNCTION                                               RELEASE        */
3544 /*                                                                        */
3545 /*    send                                                PORTABLE C      */
3546 /*                                                           6.3.0        */
3547 /*  AUTHOR                                                                */
3548 /*                                                                        */
3549 /*    Yuxin Zhou, Microsoft Corporation                                   */
3550 /*                                                                        */
3551 /*  DESCRIPTION                                                           */
3552 /*                                                                        */
3553 /*    This function sends a packet out the given  socket.                 */
3554 /*    When the call returns, the data has been queued for transmission    */
3555 /*    over the connection. The return value indicates the number of byes  */
3556 /*    actually transmitted.                                               */
3557 /*                                                                        */
3558 /*    The flags argument is provided for consistency with the BSD send    */
3559 /*    service. It allows various protocol features, such as out-of-bound  */
3560 /*    out-of-bound data, to be accessed. However, none of these features  */
3561 /*    are implemented.                                                    */
3562 /*                                                                        */
3563 /*    If packets are being sent out a UDP socket which is not bound to a  */
3564 /*    local port, this function find an available free port to bind to the*/
3565 /*    socket. For TCP sockets, the socket must already by connected (so   */
3566 /*    also bound to port)                                                 */
3567 /*                                                                        */
3568 /*    Note: send() does not support raw sockets. Use the sendto() service */
3569 /*    to transmit raw packets.                                            */
3570 /*                                                                        */
3571 /*  INPUT                                                                 */
3572 /*                                                                        */
3573 /*    sockID                                Socket                        */
3574 /*    msg                                   Data to be transmitted        */
3575 /*    msgLength                             Number of bytes to be sent    */
3576 /*    flags                                 Control flags, support        */
3577 /*                                            MSG_DONTWAIT                */
3578 /*                                                                        */
3579 /*  OUTPUT                                                                */
3580 /*                                                                        */
3581 /*     number of bytes sent                 If successful                 */
3582 /*     NX_SOC_ERROR (-1)                    If failure                    */
3583 /*                                                                        */
3584 /*  CALLS                                                                 */
3585 /*                                                                        */
3586 /*   nx_tcp_socket_send                     Send a packet                 */
3587 /*   nx_packet_allocate                     Get a free packet             */
3588 /*   nx_packet_data_append                  Copy data into packet         */
3589 /*   nx_packet_release                      Free a packet used to send    */
3590 /*   tx_mutex_get                           Get protection                */
3591 /*   tx_mutex_put                           Release protection            */
3592 /*                                                                        */
3593 /*  CALLED BY                                                             */
3594 /*                                                                        */
3595 /*    Application Code                                                    */
3596 /*                                                                        */
3597 /*  RELEASE HISTORY                                                       */
3598 /*                                                                        */
3599 /*    DATE              NAME                      DESCRIPTION             */
3600 /*                                                                        */
3601 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3602 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3603 /*                                            resulting in version 6.1    */
3604 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
3605 /*                                            used new API/structs naming,*/
3606 /*                                            resulting in version 6.3.0  */
3607 /*                                                                        */
3608 /**************************************************************************/
nx_bsd_send(INT sockID,const CHAR * msg,INT msgLength,INT flags)3609 INT  nx_bsd_send(INT sockID, const CHAR *msg, INT msgLength, INT flags)
3610 {
3611 
3612 NX_BSD_SOCKET *bsd_socket_ptr;
3613 
3614 
3615     /* Check for invalid socket IDd.  */
3616     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
3617     {
3618 
3619         /* Set the socket error if extended options enabled. */
3620         nx_bsd_set_errno(EBADF);
3621 
3622         /* Return an error status.*/
3623         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3624         return(NX_SOC_ERROR);
3625     }
3626 
3627     /* Normalize the socket ID.  */
3628     sockID =  sockID - NX_BSD_SOCKFD_START;
3629 
3630     /* Set up a pointer to the BSD socket.  */
3631     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
3632 
3633     /* If the socket has an error */
3634     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
3635     {
3636         INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
3637 
3638         /* Now clear the error code. */
3639         bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
3640 
3641         /* Clear the error flag.  The application is expected to close the socket at this point.*/
3642         bsd_socket_ptr -> nx_bsd_socket_status_flags =
3643             bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
3644 
3645         nx_bsd_set_errno(errcode);
3646 
3647         /* Return an error.  */
3648         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3649 
3650         /* At this point the error flag is cleared.  Application should
3651            detect and handle the error codition. This socket is still bound
3652            to the port (either the application called bind(), or a bind
3653            operation was executed as part of the connect call) is able to
3654            handle another "connect" call, or be closed. */
3655         return(NX_SOC_ERROR);
3656     }
3657 
3658     /* Send() requires the socket be connected. A connected socket implies the socket is bound.*/
3659     if((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED) == 0)
3660     {
3661 
3662         /* For AF_PACKET family, user shall use the sendto call. */
3663 #if defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)
3664         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
3665         {
3666             /* Set the socket error */
3667             nx_bsd_set_errno(ENOTCONN);
3668 
3669             /* Return an error status.*/
3670             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3671             return(NX_SOC_ERROR);
3672         }
3673 
3674 #endif /* defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT) */
3675 
3676         /* However if the socket is raw socket and HDR_INCLUDE is set, it is OK. */
3677         if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE))
3678         {
3679             /* Set the socket error */
3680             nx_bsd_set_errno(ENOTCONN);
3681 
3682             /* Return an error status.*/
3683             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3684             return(NX_SOC_ERROR);
3685         }
3686     }
3687 
3688     return nx_bsd_send_internal(sockID, msg, msgLength, flags,
3689                                 &bsd_socket_ptr -> nx_bsd_socket_peer_ip,
3690                                 bsd_socket_ptr -> nx_bsd_socket_peer_port,
3691                                 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index);
3692 
3693 }
3694 
3695 
3696 /**************************************************************************/
3697 /*                                                                        */
3698 /*  FUNCTION                                               RELEASE        */
3699 /*                                                                        */
3700 /*    sendto                                              PORTABLE C      */
3701 /*                                                           6.3.0        */
3702 /*  AUTHOR                                                                */
3703 /*                                                                        */
3704 /*    Yuxin Zhou, Microsoft Corporation                                   */
3705 /*                                                                        */
3706 /*  DESCRIPTION                                                           */
3707 /*                                                                        */
3708 /*    This function sends a packet out the given socket.                  */
3709 /*    When the call returns, the data has been queued for transmission    */
3710 /*    over the connection. To use sendto on a TCP BSD socket, the         */
3711 /*    socket must already be in connected state.                          */
3712 /*                                                                        */
3713 /*    The flags argument is provided for consistency with the BSD send    */
3714 /*    service. It allows various protocol features, such as out-of-bound  */
3715 /*    out-of-bound data, to be accessed. However, none of these features  */
3716 /*    are implemented.                                                    */
3717 /*                                                                        */
3718 /*  INPUT                                                                 */
3719 /*                                                                        */
3720 /*    sockID                                Socket (must be connected).   */
3721 /*    msg                                   Data to transmit.             */
3722 /*    msgLength                             Number of bytes to send       */
3723 /*    flags                                 Control flags, support        */
3724 /*                                            MSG_DONTWAIT                */
3725 /*    sockaddr                              Destination address           */
3726 /*    destAddrLen                           Length of destination address */
3727 /*                                                                        */
3728 /*  OUTPUT                                                                */
3729 /*                                                                        */
3730 /*    Number of bytes sent                  If no error occurs            */
3731 /*    NX_SOC_ERROR (-1)                     In case of socket error       */
3732 /*                                                                        */
3733 /*  CALLS                                                                 */
3734 /*                                                                        */
3735 /*    bind                                 Bind NetX UDP sockets          */
3736 /*    nx_packet_allocate                   Get a free packet              */
3737 /*    nx_packet_data_append                Copy data into packet          */
3738 /*    nx_packet_release                    Free the nx_packet used        */
3739 /*    nx_tcp_socket_send                   Send packet over a TCP Socket  */
3740 /*    nx_udp_socket_send                   Send packet over a UDP Socket  */
3741 /*    tx_mutex_get                         Get protection                 */
3742 /*    tx_mutex_put                         Release protection             */
3743 /*                                                                        */
3744 /*  CALLED BY                                                             */
3745 /*                                                                        */
3746 /*    Application Code                                                    */
3747 /*                                                                        */
3748 /*  RELEASE HISTORY                                                       */
3749 /*                                                                        */
3750 /*    DATE              NAME                      DESCRIPTION             */
3751 /*                                                                        */
3752 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3753 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3754 /*                                            resulting in version 6.1    */
3755 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
3756 /*                                            used new API/structs naming,*/
3757 /*                                            resulting in version 6.3.0  */
3758 /*                                                                        */
3759 /**************************************************************************/
nx_bsd_sendto(INT sockID,CHAR * msg,INT msgLength,INT flags,struct nx_bsd_sockaddr * destAddr,INT destAddrLen)3760 INT  nx_bsd_sendto(INT sockID, CHAR *msg, INT msgLength, INT flags,  struct nx_bsd_sockaddr *destAddr, INT destAddrLen)
3761 {
3762 UINT                 status;
3763 NX_BSD_SOCKET       *bsd_socket_ptr;
3764 NXD_ADDRESS          peer_ip_address;
3765 USHORT               peer_port = 0;
3766 
3767     /* Check for a valid socket ID.  */
3768     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
3769     {
3770 
3771         /* Set the socket error if extended options enabled. */
3772         nx_bsd_set_errno(EBADF);
3773 
3774         /* Return an error status. */
3775         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3776         return(NX_SOC_ERROR);
3777     }
3778 
3779     /* Set up a socket pointer to the BSD socket.  */
3780     bsd_socket_ptr =  &nx_bsd_socket_array[sockID - NX_BSD_SOCKFD_START];
3781 
3782     /* If the socket has an error */
3783     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
3784     {
3785         INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
3786 
3787         /* Now clear the error code. */
3788         bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
3789 
3790         /* Clear the error flag.  The application is expected to close the socket at this point.*/
3791         bsd_socket_ptr -> nx_bsd_socket_status_flags =
3792             bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
3793 
3794         nx_bsd_set_errno(errcode);
3795 
3796         /* Return an error.  */
3797         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3798 
3799         /* At this point the error flag is cleared.  Application should
3800            detect and handle the error codition. This socket is still bound
3801            to the port (either the application called bind(), or a bind
3802            operation was executed as part of the connect call) is able to
3803            handle another "connect" call, or be closed. */
3804         return(NX_SOC_ERROR);
3805     }
3806     /* For TCP, make sure the socket is already connected. */
3807     if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
3808     {
3809         if((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED) == 0)
3810         {
3811             nx_bsd_set_errno(ENOTCONN);
3812 
3813             /* Return an error.  */
3814             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3815 
3816             return(NX_SOC_ERROR);
3817         }
3818         return nx_bsd_send_internal((sockID - NX_BSD_SOCKFD_START), msg, msgLength, flags, NX_NULL, 0,
3819                                     bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index);
3820     }
3821     else
3822     {
3823 
3824         /* This is a UDP or raw socket.  */
3825 
3826         /* Check whther or not the socket is AF_PACKET family. */
3827         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
3828         {
3829 
3830 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
3831             /* nx_bsd_pppoe_internal_sendto shall returns */
3832             status = (UINT)nx_bsd_pppoe_internal_sendto(bsd_socket_ptr, msg, msgLength, flags,  destAddr, destAddrLen);
3833 #elif defined(NX_BSD_RAW_SUPPORT)
3834             /* _nx_bsd_hardware_internal_sendto shall returns */
3835             status = (UINT)_nx_bsd_hardware_internal_sendto(bsd_socket_ptr, msg, msgLength, flags,  destAddr, destAddrLen);
3836 #else
3837             NX_PARAMETER_NOT_USED(destAddrLen);
3838             status = (UINT)NX_SOC_ERROR;
3839 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
3840             return((INT)status);
3841 
3842         }
3843 
3844         /* Perform error checkings on the remote address if the socket is
3845            not raw socket, or HDRINCL is not set for the raw socket. */
3846         if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE))
3847         {
3848 
3849             /* Check for an invalid destination. */
3850             if (destAddr == NX_NULL)
3851             {
3852 
3853                 /* Set the socket error if extended socket options enabled. */
3854                 nx_bsd_set_errno(EINVAL);
3855 
3856                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3857                 return(NX_SOC_ERROR);
3858             }
3859 
3860             /* Validate the destination address. */
3861             if(bsd_socket_ptr -> nx_bsd_socket_family != destAddr -> sa_family)
3862             {
3863                 nx_bsd_set_errno(EAFNOSUPPORT);
3864 
3865                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3866 
3867                 return(NX_SOC_ERROR);
3868             }
3869         }
3870 
3871         /* For UDP socket, make sure the socket is bound. */
3872         if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
3873         {
3874             if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND))
3875             {
3876                 status = nx_udp_socket_bind(bsd_socket_ptr -> nx_bsd_socket_udp_socket, NX_ANY_PORT, NX_NO_WAIT);
3877                 if((status != NX_SUCCESS) && (status != NX_ALREADY_BOUND))
3878                 {
3879                     nx_bsd_set_errno(EINVAL);
3880 
3881                     NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3882 
3883                     return(NX_SOC_ERROR);
3884                 }
3885 
3886                 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
3887                 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
3888                 bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)(bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_port);
3889                 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
3890             }
3891 
3892         }
3893 
3894 
3895 
3896         if(destAddr)
3897         {
3898             /* Get the destination IP and port for this UDP socket.  */
3899 #ifndef NX_DISABLE_IPV4
3900             if (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
3901             {
3902 
3903                 /* This is for an IPv4 packet. */
3904                 peer_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
3905                 peer_ip_address.nxd_ip_address.v4 = htonl(((struct nx_bsd_sockaddr_in *) destAddr) -> sin_addr.s_addr);
3906                 peer_port = htons(((struct nx_bsd_sockaddr_in *) destAddr) -> sin_port);
3907 
3908                 /* Local interface ID is set to invalid value, so the send routine needs to
3909                    find the best interface to send the packet based on destination IP address. */
3910 
3911             }
3912 #endif /* NX_DISABLE_IPV4 */
3913 #ifdef FEATURE_NX_IPV6
3914             if (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
3915             {
3916 
3917                 /* This is for an IPv6 packet. Set the NetX Duo IP address version. */
3918                 peer_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
3919 
3920                 peer_ip_address.nxd_ip_address.v6[0] = ntohl(((struct nx_bsd_sockaddr_in6*)destAddr) -> sin6_addr._S6_un._S6_u32[0]);
3921                 peer_ip_address.nxd_ip_address.v6[1] = ntohl(((struct nx_bsd_sockaddr_in6*)destAddr) -> sin6_addr._S6_un._S6_u32[1]);
3922                 peer_ip_address.nxd_ip_address.v6[2] = ntohl(((struct nx_bsd_sockaddr_in6*)destAddr) -> sin6_addr._S6_un._S6_u32[2]);
3923                 peer_ip_address.nxd_ip_address.v6[3] = ntohl(((struct nx_bsd_sockaddr_in6*)destAddr) -> sin6_addr._S6_un._S6_u32[3]);
3924 
3925                 peer_port = htons(((struct nx_bsd_sockaddr_in6 *) destAddr) -> sin6_port);
3926 
3927             }
3928 #endif
3929         }
3930 
3931         /* Call the internal send routine to finish the send process. */
3932         /* Local interface ID is set to a special marker, so the send routine needs to
3933            find the best interface to send the packet based on destination IP address. */
3934         return nx_bsd_send_internal((sockID - NX_BSD_SOCKFD_START), msg, msgLength, flags,
3935                                     &peer_ip_address, peer_port,
3936                                     bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index);
3937 
3938     }
3939 }
3940 
3941 
3942 /**************************************************************************/
3943 /*                                                                        */
3944 /*  FUNCTION                                               RELEASE        */
3945 /*                                                                        */
3946 /*    recv                                                PORTABLE C      */
3947 /*                                                           6.3.0        */
3948 /*  AUTHOR                                                                */
3949 /*                                                                        */
3950 /*    Yuxin Zhou, Microsoft Corporation                                   */
3951 /*                                                                        */
3952 /*  DESCRIPTION                                                           */
3953 /*                                                                        */
3954 /*    This function copies up to a specified number of bytes received on  */
3955 /*    the socket into specified location. The given socket must be in the */
3956 /*    connected state. Normally, the call blocks until either at least one*/
3957 /*    byte is returned or the connection closes.The return value indicates*/
3958 /*    the number of bytes actually copied into the buffer starting at the */
3959 /*    specified location.                                                 */
3960 /*                                                                        */
3961 /*    For a stream socket, the bytes are delivered in the same order as   */
3962 /*    they were transmitted, without omissions. For a datagram socket,    */
3963 /*    each recv() returns the data from at most one send(), and order is  */
3964 /*    not necessarily preserved.                                          */
3965 /*                                                                        */
3966 /*    For non blocking sockets, a receive status of NX_NO_PACKET from NetX*/
3967 /*    results in an error status returned from BSD, and the socket error  */
3968 /*    set to EWOULDBLOCK (if BSD extended socket features are enabled.    */
3969 /*                                                                        */
3970 /*    Likewise, an event flag status of TX_NO_EVENTS returned from ThreadX*/
3971 /*    on a non blocking socket sets the socket error to EWOULDBLOCK.      */
3972 /*                                                                        */
3973 /*  INPUT                                                                 */
3974 /*                                                                        */
3975 /*    sockID                                Socket (must be connected).   */
3976 /*    rcvBuffer                             Pointer to put data received. */
3977 /*    bufferLength                          Maximum bytes in buffer       */
3978 /*    flags                                 Control flags, support        */
3979 /*                                            MSG_PEEK and MSG_DONTWAIT   */
3980 /*                                                                        */
3981 /*  OUTPUT                                                                */
3982 /*                                                                        */
3983 /*    Number of bytes received              If success                    */
3984 /*    NX_SOC_ERROR (-1)                     If failure                    */
3985 /*    0                                     socket disconnected           */
3986 /*                                                                        */
3987 /*  CALLS                                                                 */
3988 /*                                                                        */
3989 /*    nx_tcp_socket_receive                 Receive a Packet              */
3990 /*    nx_packet_allocate                    Allocate packet for receive   */
3991 /*    nx_packet_release                     Free the nx_packet after use  */
3992 /*    nx_packet_data_extract_offset         Retrieve packet data          */
3993 /*    tx_event_flags_get                    Wait for data to arrive       */
3994 /*    tx_mutex_get                          Get protection                */
3995 /*    tx_mutex_put                          Release protection            */
3996 /*                                                                        */
3997 /*  CALLED BY                                                             */
3998 /*                                                                        */
3999 /*    Application Code                                                    */
4000 /*                                                                        */
4001 /*  RELEASE HISTORY                                                       */
4002 /*                                                                        */
4003 /*    DATE              NAME                      DESCRIPTION             */
4004 /*                                                                        */
4005 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4006 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
4007 /*                                            verified memcpy use cases,  */
4008 /*                                            resulting in version 6.1    */
4009 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
4010 /*                                            used new API/structs naming,*/
4011 /*                                            resulting in version 6.3.0  */
4012 /*                                                                        */
4013 /**************************************************************************/
nx_bsd_recv(INT sockID,VOID * rcvBuffer,INT bufferLength,INT flags)4014 INT  nx_bsd_recv(INT sockID, VOID *rcvBuffer, INT bufferLength, INT flags)
4015 {
4016 
4017 UINT                status;
4018 NX_PACKET           *packet_ptr;
4019 NX_BSD_SOCKET       *bsd_socket_ptr;
4020 NX_TCP_SOCKET       *tcp_socket_ptr;
4021 ULONG               requested_events;
4022 ULONG               bytes_received;
4023 UINT                wait_option;
4024 UINT                remaining_wait_option;
4025 ULONG               offset;
4026 INT                 header_size = 0;
4027 ULONG               start_time = nx_bsd_system_clock;
4028 
4029 
4030     /* Check for a valid socket ID.  */
4031     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
4032     {
4033 
4034         /* Set the socket error if extended options enabled. */
4035         nx_bsd_set_errno(EBADF);
4036 
4037         /* Return an error.  */
4038         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4039 
4040         return(NX_SOC_ERROR);
4041     }
4042 
4043     /* Normalize the socket ID.  */
4044     sockID =  sockID - NX_BSD_SOCKFD_START;
4045 
4046     /* Set up a pointer to the socket.  */
4047     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
4048 
4049     /* Set the receive wait time to FOREVER for blocking sockets. */
4050     wait_option = NX_WAIT_FOREVER;
4051 
4052     /* Is this a nonblocking socket?:  */
4053     if ((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING) ||
4054         (flags & MSG_DONTWAIT))
4055     {
4056 
4057         /* Yes, set to receive wait option to no wait (zero). */
4058         wait_option = 0;
4059     }
4060     /* Does this socket have a receive timeout option set? */
4061     else if (bsd_socket_ptr -> nx_bsd_option_receive_timeout)
4062     {
4063 
4064         /* Yes, this is our wait option. */
4065         wait_option = bsd_socket_ptr -> nx_bsd_option_receive_timeout;
4066     }
4067 
4068     /* Get the protection mutex.  */
4069     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
4070 
4071     /* Check the status.  */
4072     if (status)
4073     {
4074 
4075         /* Set the socket error if extended socket options enabled. */
4076         nx_bsd_set_errno(EACCES);
4077 
4078         /* Return an error. */
4079         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
4080         return(NX_SOC_ERROR);
4081     }
4082 
4083     /* If the socket has an error */
4084     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
4085     {
4086 
4087         INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
4088 
4089         /* Now clear the error code. */
4090         bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
4091 
4092         /* Clear the error flag.  The application is expected to close the socket at this point.*/
4093         bsd_socket_ptr -> nx_bsd_socket_status_flags =
4094             bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
4095 
4096         nx_bsd_set_errno(errcode);
4097 
4098         /* Release the protection mutex.  */
4099         tx_mutex_put(nx_bsd_protection_ptr);
4100 
4101         /* Return an error.  */
4102         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4103 
4104         /* At this point the error flag is cleared.  The application should
4105            detect and handle the error codition. This socket is still bound
4106            to the port (either the application called bind(), or a bind
4107            operation was executed as part of the connect call) and is able to
4108            handle another "connect" call, or be closed. */
4109         return(NX_SOC_ERROR);
4110     }
4111 
4112     /* Set pointers to the BSD NetX Duo sockets.  */
4113     tcp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
4114 
4115     /* Loop to check for a received packet.  */
4116     do
4117     {
4118 
4119         /* Is the socket still in use?  */
4120         if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
4121         {
4122 
4123             /* Set the socket error if extended options enabled. */
4124             nx_bsd_set_errno(EBADF);
4125 
4126             /* Release the protection mutex.  */
4127             tx_mutex_put(nx_bsd_protection_ptr);
4128 
4129             /* Return an error.  */
4130             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4131             return(NX_SOC_ERROR);
4132         }
4133 
4134         /* Check if the BSD socket already has received a packet.  */
4135         packet_ptr =  bsd_socket_ptr -> nx_bsd_socket_received_packet;
4136 
4137         if (packet_ptr)
4138         {
4139 
4140             /* Got one. Break out of the loop.  */
4141             break;
4142         }
4143 
4144         /* Check if there is an incoming packet on this socket.  */
4145         else
4146         {
4147 
4148             /* Determine if this is a TCP BSD socket.  */
4149             if (tcp_socket_ptr)
4150             {
4151 
4152                 /* It is, check the socket TCP receive queue with a zero wait option (no suspension).  */
4153                 status =  nx_tcp_socket_receive(tcp_socket_ptr, &packet_ptr, TX_NO_WAIT);
4154 
4155                 /* Check for no packet on the queue.  */
4156                 if (status == NX_NOT_CONNECTED)
4157                 {
4158 
4159                     /* Release the protection mutex.  */
4160                     tx_mutex_put(nx_bsd_protection_ptr);
4161 
4162                     /* Is peer shutdown orderly? */
4163                     if ((tcp_socket_ptr -> nx_tcp_socket_state == NX_TCP_CLOSE_WAIT) ||
4164                         (tcp_socket_ptr -> nx_tcp_socket_state >= NX_TCP_CLOSING))
4165                     {
4166 
4167                         /* Yes. Return 0. */
4168                         return(NX_SUCCESS);
4169                     }
4170 
4171                     /* Set the socket status (not really an error).  */
4172                     nx_bsd_set_errno(ENOTCONN);
4173 
4174                     /* Return an error.  */
4175                     NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4176                     return(NX_SOC_ERROR);
4177                 }
4178 
4179                 if (status == NX_SUCCESS)
4180                 {
4181 
4182                     /* Increase the received count. */
4183                     bsd_socket_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
4184                     bsd_socket_ptr -> nx_bsd_socket_received_packet_count++;
4185                 }
4186             }
4187 
4188             /* Have we found a new packet?  */
4189             if ((status == NX_SUCCESS) && (packet_ptr))
4190             {
4191 
4192                 /* Setup the bsd socket with the packet information.  */
4193                 bsd_socket_ptr -> nx_bsd_socket_received_packet =         packet_ptr;
4194                 bsd_socket_ptr -> nx_bsd_socket_received_packet_offset =  0;
4195 
4196                 /* Get out of the loop.  */
4197                 break;
4198             }
4199         }
4200 
4201         /* No packet is available.  */
4202 
4203         /* Release the protection mutex.  */
4204         tx_mutex_put(nx_bsd_protection_ptr);
4205 
4206         /* Calculate remaining wait option. */
4207         remaining_wait_option = (UINT)(wait_option - (nx_bsd_system_clock - start_time));
4208         if (remaining_wait_option > wait_option)
4209         {
4210 
4211             /* Wait option expired. */
4212             status = TX_NO_EVENTS;
4213         }
4214         else
4215         {
4216 
4217             /* Suspend this socket on a RECEIVE event (incoming packet) for the specified wait time.  */
4218             status =  tx_event_flags_get(&nx_bsd_events, NX_BSD_RECEIVE_EVENT, TX_OR_CLEAR, &requested_events, remaining_wait_option);
4219         }
4220 
4221         /* Check for any events. */
4222         if (status == TX_NO_EVENTS)
4223         {
4224 
4225             /* No packets received. */
4226 
4227             /* Set the socket error depending if this is a non blocking socket. */
4228             if ((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING) ||
4229                 (wait_option == NX_WAIT_FOREVER) ||
4230                 (flags & MSG_DONTWAIT))
4231                 nx_bsd_set_errno(EWOULDBLOCK);
4232             else
4233                 nx_bsd_set_errno(EAGAIN);
4234 
4235             /* Return an error.  */
4236             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4237             return(NX_SOC_ERROR);
4238         }
4239         else if (status != TX_SUCCESS)
4240         {
4241 
4242             /* Set the socket error if extended socket options enabled. */
4243             nx_bsd_set_errno(EINVAL);
4244 
4245             /* Return an error.  */
4246             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4247             return(NX_SOC_ERROR);
4248         }
4249 
4250         /* Re-obtain the protection mutex.  */
4251         status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
4252 
4253         /* Check the status.  */
4254         if (status)
4255         {
4256 
4257             /* Set the socket error if extended socket options enabled. */
4258             nx_bsd_set_errno(EACCES);
4259 
4260             /* Return an error.  */
4261             NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
4262             return(NX_SOC_ERROR);
4263         }
4264 
4265         if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
4266         {
4267             /* The socket is no longer in use. */
4268 
4269             /* Set the socket error code. */
4270             nx_bsd_set_errno(EBADF);
4271 
4272             /* Release the protection mutex.  */
4273             tx_mutex_put(nx_bsd_protection_ptr);
4274 
4275             /* Return error code.  */
4276             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4277             return(NX_SOC_ERROR);
4278         }
4279 
4280     } while (1);
4281 
4282     /* At this point, the socket has received a packet.  */
4283 
4284 
4285     /* Obtain sender information for UDP socket. */
4286     if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
4287     {
4288 
4289         /* Get the sender and port from the UDP packet.  */
4290         nxd_udp_source_extract(packet_ptr, &bsd_socket_ptr -> nx_bsd_socket_source_ip_address, (UINT *)&bsd_socket_ptr -> nx_bsd_socket_source_port);
4291     }
4292 
4293 #if defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)
4294     else if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
4295     {
4296 
4297         /* Validate the packet length.  */
4298         if (packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr < 14)
4299         {
4300 
4301             /* Set the socket error if extended socket options enabled. */
4302             nx_bsd_set_errno(EINVAL);
4303 
4304             /* Release the protection mutex.  */
4305             tx_mutex_put(nx_bsd_protection_ptr);
4306 
4307             /* Release the packet.  */
4308             nx_packet_release(packet_ptr);
4309 
4310             /* Return an error.  */
4311             NX_BSD_ERROR(status, __LINE__);
4312             return(NX_SOC_ERROR);
4313         }
4314 
4315         /* Pick up the sender's MAC address. */
4316         bsd_socket_ptr -> nx_bsd_socket_sll_addr[0] = packet_ptr -> nx_packet_prepend_ptr[6];
4317         bsd_socket_ptr -> nx_bsd_socket_sll_addr[1] = packet_ptr -> nx_packet_prepend_ptr[7];
4318         bsd_socket_ptr -> nx_bsd_socket_sll_addr[2] = packet_ptr -> nx_packet_prepend_ptr[8];
4319         bsd_socket_ptr -> nx_bsd_socket_sll_addr[3] = packet_ptr -> nx_packet_prepend_ptr[9];
4320         bsd_socket_ptr -> nx_bsd_socket_sll_addr[4] = packet_ptr -> nx_packet_prepend_ptr[10];
4321         bsd_socket_ptr -> nx_bsd_socket_sll_addr[5] = packet_ptr -> nx_packet_prepend_ptr[11];
4322 
4323         /* Pick up the sender's protocol */
4324         bsd_socket_ptr -> nx_bsd_socket_sll_protocol = (USHORT)((packet_ptr -> nx_packet_prepend_ptr[12] << 8) |
4325                                                                 (packet_ptr -> nx_packet_prepend_ptr[13]));
4326         if (bsd_socket_ptr -> nx_bsd_socket_sll_protocol == 0x8100)
4327         {
4328 
4329             /* Skip VLAN tag. */
4330             bsd_socket_ptr -> nx_bsd_socket_sll_protocol = (USHORT)((packet_ptr -> nx_packet_prepend_ptr[16] << 8) |
4331                                                                     (packet_ptr -> nx_packet_prepend_ptr[17]));
4332         }
4333 
4334         /* Find the IF Index */
4335         bsd_socket_ptr -> nx_bsd_socket_sll_ifindex = packet_ptr -> nx_packet_ip_interface -> nx_interface_index;
4336 
4337     }
4338 #endif /* defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT) */
4339 
4340 
4341 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4342     /* For raw socket, make sure the source address is extracted. */
4343     else if(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET)
4344     {
4345 
4346         /* Get the sender IP address from the raw packet.  */
4347         status = nx_bsd_raw_packet_info_extract(packet_ptr, &(bsd_socket_ptr -> nx_bsd_socket_source_ip_address), NX_NULL);
4348     }
4349 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
4350 
4351     /* Pickup the current offset.  */
4352     offset =  bsd_socket_ptr -> nx_bsd_socket_received_packet_offset;
4353 
4354 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4355     /* Perform extra processing on this packet if it processed as a raw packet. */
4356     if((bsd_socket_ptr -> nx_bsd_socket_family != AF_PACKET) &&
4357        (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET))
4358     {
4359 
4360         if(bsd_socket_ptr -> nx_bsd_socket_status_flags & (NX_BSD_SOCKET_RX_NO_HDR))
4361         {
4362             header_size = 0;
4363         }
4364         else
4365         {
4366 #ifndef NX_DISABLE_IPV4
4367             if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
4368             {
4369 
4370 
4371                 header_size = packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_ip_header;
4372 
4373                 /* Byte-Swap the basic IPv4 header.  The NetX Duo IP receive process does not
4374                    examine the extension header.  Therefore it does not perform byte swap
4375                    on extension headers. */
4376                 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_word_0));
4377                 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_word_1));
4378                 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_word_2));
4379                 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_source_ip));
4380                 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_destination_ip));
4381 
4382                 if(bufferLength < header_size)
4383                 {
4384                     header_size = bufferLength;
4385                 }
4386             }
4387 #endif /* NX_DISABLE_IPV4 */
4388 #ifdef FEATURE_NX_IPV6
4389             if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
4390             {
4391 
4392                 NX_IPV6_HEADER *ipv6_header_ptr;
4393                 UCHAR           next_header_type;
4394 
4395                 header_size = (INT)(packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_ip_header);
4396 
4397                 if(bufferLength < header_size)
4398                 {
4399 
4400                     header_size = bufferLength;
4401                 }
4402 
4403                 ipv6_header_ptr = (NX_IPV6_HEADER*)packet_ptr -> nx_packet_ip_header;
4404 
4405                 /* Pick up the next header. */
4406                 next_header_type = (ipv6_header_ptr -> nx_ip_header_word_1 >> 8) & 0xFF;
4407 
4408                 NX_CHANGE_ULONG_ENDIAN(ipv6_header_ptr -> nx_ip_header_word_0);
4409                 NX_CHANGE_ULONG_ENDIAN(ipv6_header_ptr -> nx_ip_header_word_1);
4410                 NX_IPV6_ADDRESS_CHANGE_ENDIAN(ipv6_header_ptr -> nx_ip_header_destination_ip);
4411                 NX_IPV6_ADDRESS_CHANGE_ENDIAN(ipv6_header_ptr -> nx_ip_header_source_ip);
4412 
4413                 /* Go through the rest of the IPv6 extension headers. */
4414                 _nxd_bsd_swap_ipv6_extension_headers(packet_ptr, next_header_type);
4415             }
4416 #endif
4417 
4418             memcpy(rcvBuffer, packet_ptr -> nx_packet_ip_header, (UINT)header_size); /* Use case of memcpy is verified. */
4419         }
4420     }
4421 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
4422 
4423 
4424     /* Copy the packet data into the supplied buffer.  */
4425     status =  nx_packet_data_extract_offset(packet_ptr, offset, (VOID*)((INT)rcvBuffer + header_size), (ULONG) (bufferLength - header_size), &bytes_received);
4426 
4427     /* Check for an error.  */
4428     if (status)
4429     {
4430 
4431         /* Set the socket error if extended socket options enabled. */
4432         nx_bsd_set_errno(EINVAL);
4433 
4434         /* Release the protection mutex.  */
4435         tx_mutex_put(nx_bsd_protection_ptr);
4436 
4437         /* Release the packet.  */
4438         nx_packet_release(packet_ptr);
4439 
4440         /* Return an error.  */
4441         NX_BSD_ERROR( status, __LINE__);
4442         return(NX_SOC_ERROR);
4443     }
4444 
4445     if((flags & MSG_PEEK) == 0)
4446     {
4447 
4448         /* Calculate the new offset.  */
4449         offset =  offset + bytes_received;
4450 
4451         /* Determine if all the packet data was consumed.  */
4452         if(packet_ptr -> nx_packet_length <= offset)
4453         {
4454 
4455             bsd_socket_ptr -> nx_bsd_socket_received_packet =  packet_ptr -> nx_packet_queue_next;
4456 
4457             /* Release the packet.  */
4458             nx_packet_release(packet_ptr);
4459 
4460             /* Clear the offset.  */
4461             bsd_socket_ptr -> nx_bsd_socket_received_packet_offset =  0;
4462         }
4463         else if((bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
4464 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
4465                         || (bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
4466 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
4467                )
4468         {
4469 
4470             /* For UDP or raw socket, We extracted as much as can fit in the caller's buffer.
4471                We will discard the remaining bytes. */
4472             bsd_socket_ptr -> nx_bsd_socket_received_packet =  packet_ptr -> nx_packet_queue_next;
4473 
4474             bytes_received = packet_ptr -> nx_packet_length;
4475 
4476             /* No need to retain the packet.  */
4477             nx_packet_release(packet_ptr);
4478 
4479             /* Clear the offset.  */
4480             bsd_socket_ptr -> nx_bsd_socket_received_packet_offset =  0;
4481         }
4482         else
4483         {
4484 
4485             /* For TCP, the remaining data is saved for the next recv call.
4486                Just update the offset.  */
4487             bsd_socket_ptr -> nx_bsd_socket_received_packet_offset =  offset;
4488         }
4489         bsd_socket_ptr -> nx_bsd_socket_received_byte_count -= bytes_received;
4490         bsd_socket_ptr -> nx_bsd_socket_received_packet_count--;
4491     }
4492 
4493     /* Release the protection mutex.  */
4494     tx_mutex_put(nx_bsd_protection_ptr);
4495 
4496     /* Successful received a packet. Return the number of bytes copied to buffer.  */
4497     return((INT)bytes_received + (INT)header_size);
4498 }
4499 
4500 
4501 /**************************************************************************/
4502 /*                                                                        */
4503 /*  FUNCTION                                               RELEASE        */
4504 /*                                                                        */
4505 /*    recvfrom                                            PORTABLE C      */
4506 /*                                                           6.3.0        */
4507 /*  AUTHOR                                                                */
4508 /*                                                                        */
4509 /*    Yuxin Zhou, Microsoft Corporation                                   */
4510 /*                                                                        */
4511 /*  DESCRIPTION                                                           */
4512 /*                                                                        */
4513 /*    This function copies up to a specified number of bytes, received on */
4514 /*    the socket into a specified location. To use recvfrom() on a TCP    */
4515 /*    socket requires the socket to be in the connected state.            */
4516 /*                                                                        */
4517 /*    This function is identical to recv() except for returning the sender*/
4518 /*    address and length if non null arguments are supplied.              */
4519 /*                                                                        */
4520 /*  INPUT                                                                 */
4521 /*                                                                        */
4522 /*    sockID                                Socket(must be connected)     */
4523 /*    buffer                                Pointer to hold data received */
4524 /*    bufferSize                            Maximum number of bytes       */
4525 /*    flags                                 Control flags, support        */
4526 /*                                            MSG_PEEK and MSG_DONTWAIT   */
4527 /*    fromAddr                              Address data of sender        */
4528 /*    fromAddrLen                           Length of address structure   */
4529 /*                                                                        */
4530 /*  OUTPUT                                                                */
4531 /*                                                                        */
4532 /*    number of bytes received              If no error occurs            */
4533 /*    NX_SOC_ERROR (-1)                     In case of any error          */
4534 /*                                                                        */
4535 /*  CALLS                                                                 */
4536 /*                                                                        */
4537 /*    memset                                Clear memory                  */
4538 /*    nx_packet_allocate                    Allocate a packet             */
4539 /*    nx_packet_data_extract_offset         Extract packet data           */
4540 /*    nx_packet_release                     Free the packet used          */
4541 /*    tx_mutex_get                          Get protection                */
4542 /*    tx_mutex_put                          Release protection            */
4543 /*    tx_event_flags_get                    Wait for data to arrive       */
4544 /*                                                                        */
4545 /*  CALLED BY                                                             */
4546 /*                                                                        */
4547 /*    Application Code                                                    */
4548 /*                                                                        */
4549 /*  RELEASE HISTORY                                                       */
4550 /*                                                                        */
4551 /*    DATE              NAME                      DESCRIPTION             */
4552 /*                                                                        */
4553 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4554 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
4555 /*                                            verified memcpy use cases,  */
4556 /*                                            resulting in version 6.1    */
4557 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
4558 /*                                            used new API/structs naming,*/
4559 /*                                            resulting in version 6.3.0  */
4560 /*                                                                        */
4561 /**************************************************************************/
nx_bsd_recvfrom(INT sockID,CHAR * rcvBuffer,INT bufferLength,INT flags,struct nx_bsd_sockaddr * fromAddr,INT * fromAddrLen)4562 INT  nx_bsd_recvfrom(INT sockID, CHAR *rcvBuffer, INT bufferLength, INT flags, struct nx_bsd_sockaddr *fromAddr, INT *fromAddrLen)
4563 {
4564 
4565 INT                  bytes_received;
4566 NX_BSD_SOCKET       *bsd_socket_ptr;
4567 #ifndef NX_DISABLE_IPV4
4568 struct nx_bsd_sockaddr_in
4569                      peer4_address;
4570 #endif /* NX_DISABLE_IPV4 */
4571 #ifdef FEATURE_NX_IPV6
4572 struct nx_bsd_sockaddr_in6
4573                      peer6_address;
4574 #endif
4575 
4576     /* Check for a valid socket ID. */
4577     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
4578     {
4579 
4580         /* Set the socket error if extended options enabled. */
4581         nx_bsd_set_errno(EBADF);
4582         /* Return an error.  */
4583         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4584         return(NX_SOC_ERROR);
4585     }
4586 
4587     /* Set up a pointer to the socket.  */
4588     bsd_socket_ptr =  &nx_bsd_socket_array[sockID - NX_BSD_SOCKFD_START];
4589 
4590     /* Socket error checking is done inside recv() call. */
4591 
4592     /* Call the equivalent recv() function. */
4593     bytes_received = nx_bsd_recv(sockID, rcvBuffer, bufferLength, flags);
4594 
4595     /* Check for error. */
4596     if (bytes_received < 0)
4597     {
4598 
4599         /* Return an error status. */
4600         return NX_SOC_ERROR;
4601     }
4602     /* If no bytes are received do not handle as an error. */
4603     else if (bytes_received == 0)
4604     {
4605         return NX_SOC_OK;
4606     }
4607 
4608     /* At this point we did receive a packet. */
4609     /* Supply the sender address if valid pointer is supplied. */
4610     if(fromAddr && (*fromAddrLen != 0))
4611     {
4612 
4613 #ifndef NX_DISABLE_IPV4
4614         /* Handle the IPv4 socket type. */
4615         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
4616         {
4617             /* Update the Client address with socket family, remote host IPv4 address and port.  */
4618             peer4_address.sin_family =      AF_INET;
4619             if(bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
4620             {
4621                 peer4_address.sin_addr.s_addr = htonl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v4);
4622                 peer4_address.sin_port = htons(bsd_socket_ptr -> nx_bsd_socket_peer_port);
4623             }
4624             else
4625             {
4626                 peer4_address.sin_addr.s_addr = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v4);
4627 
4628 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4629                 if(!(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET))
4630 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
4631                     peer4_address.sin_port =    ntohs((USHORT)bsd_socket_ptr -> nx_bsd_socket_source_port);
4632             }
4633             /* Copy the peer address/port info to the ClientAddress.  Truncate if
4634                addressLength is smaller than the size of struct sockaddr_in */
4635             if(*fromAddrLen > (INT)sizeof(struct nx_bsd_sockaddr_in))
4636             {
4637                 *fromAddrLen = sizeof(struct nx_bsd_sockaddr_in);
4638             }
4639             memcpy(fromAddr, &peer4_address, (UINT)(*fromAddrLen)); /* Use case of memcpy is verified. */
4640         }
4641         else
4642 #endif /* NX_DISABLE_IPV4 */
4643 
4644 #ifdef FEATURE_NX_IPV6
4645         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
4646         {
4647             /* Update the Client address with socket family, remote host IPv6 address and port.  */
4648             peer6_address.sin6_family = AF_INET6;
4649 
4650             if(bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
4651             {
4652                 peer6_address.sin6_addr._S6_un._S6_u32[0] = ntohl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[0]);
4653                 peer6_address.sin6_addr._S6_un._S6_u32[1] = ntohl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[1]);
4654                 peer6_address.sin6_addr._S6_un._S6_u32[2] = ntohl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[2]);
4655                 peer6_address.sin6_addr._S6_un._S6_u32[3] = ntohl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[3]);
4656                 peer6_address.sin6_port = ntohs(bsd_socket_ptr -> nx_bsd_socket_peer_port);
4657             }
4658             else
4659             {
4660                 peer6_address.sin6_addr._S6_un._S6_u32[0] = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[0]);
4661                 peer6_address.sin6_addr._S6_un._S6_u32[1] = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[1]);
4662                 peer6_address.sin6_addr._S6_un._S6_u32[2] = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[2]);
4663                 peer6_address.sin6_addr._S6_un._S6_u32[3] = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[3]);
4664 
4665             /* Skip the port data for raw sockets. They do not use them. */
4666 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4667                 if(!(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET))
4668 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
4669                     peer6_address.sin6_port = ntohs((USHORT)bsd_socket_ptr -> nx_bsd_socket_source_port);
4670             }
4671 
4672             if((*fromAddrLen) > (INT)sizeof(peer6_address))
4673             {
4674                 *fromAddrLen = sizeof(peer6_address);
4675             }
4676             memcpy(fromAddr, &peer6_address, (UINT)(*fromAddrLen)); /* Use case of memcpy is verified. */
4677 
4678         }
4679         else
4680 #endif /* !FEATURE_NX_IPV6 */
4681 #if defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT)
4682         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
4683         {
4684             if(*fromAddrLen >= (INT)sizeof(struct nx_bsd_sockaddr_ll))
4685             {
4686                 struct nx_bsd_sockaddr_ll *sockaddr = (struct nx_bsd_sockaddr_ll*)fromAddr;
4687                 INT i;
4688                 sockaddr -> sll_family = AF_PACKET;
4689                 sockaddr -> sll_protocol = bsd_socket_ptr -> nx_bsd_socket_sll_protocol;
4690                 sockaddr -> sll_ifindex = bsd_socket_ptr -> nx_bsd_socket_sll_ifindex;
4691                 sockaddr -> sll_hatype = 0;
4692                 sockaddr -> sll_pkttype = 0;
4693                 sockaddr -> sll_halen = 6;
4694                 for(i = 0; i < 6; i++)
4695                     sockaddr -> sll_addr[i] = bsd_socket_ptr -> nx_bsd_socket_sll_addr[i];
4696                 *fromAddrLen = sizeof(struct nx_bsd_sockaddr_ll);
4697             }
4698 
4699         }
4700         else
4701 #endif
4702         {
4703 
4704             /* Release the protection mutex.  */
4705             tx_mutex_put(nx_bsd_protection_ptr);
4706 
4707             /* Set the socket error if extended socket options enabled. */
4708             nx_bsd_set_errno(EINVAL);
4709 
4710             /* Error, IPv6 support is not enabled.  */
4711             NX_BSD_ERROR(ERROR, __LINE__);
4712             return(ERROR);
4713         }
4714     }
4715 
4716     /* Successfully received a packet. Return bytes received. */
4717     return (INT)(bytes_received);
4718 }
4719 
4720 
4721 /**************************************************************************/
4722 /*                                                                        */
4723 /*  FUNCTION                                               RELEASE        */
4724 /*                                                                        */
4725 /*    soc_close                                           PORTABLE C      */
4726 /*                                                           6.3.0        */
4727 /*  AUTHOR                                                                */
4728 /*                                                                        */
4729 /*    Yuxin Zhou, Microsoft Corporation                                   */
4730 /*                                                                        */
4731 /*  DESCRIPTION                                                           */
4732 /*                                                                        */
4733 /*    This function terminates communications on the supplied BSD socket. */
4734 /*    The socket is disallowed for further sends and receives. Socket     */
4735 /*    resources such as socket memory are returned to the system.         */
4736 /*                                                                        */
4737 /*    If a socket is enabled with the linger option, that will be used in */
4738 /*    place of the default NX_BSD TIMEOUT for blocking sockets.  Sockets  */
4739 /*    enabled for non blocking have their timeout set for zero. Note that */
4740 /*    a zero wait option results in an immediate shutdown (e.g. send RST) */
4741 /*    unless the NX_DISABLE_RESET_DISCONNECT is not enabled.              */
4742 /*                                                                        */
4743 /*    For BSD applications enabled for disconnect complete notification   */
4744 /*    for TCP sockets, the socket will remain open until NetX notifies us */
4745 /*    that the disconnect is complete.  This allows the host BSD          */
4746 /*    application to perform asynchronous disconnects without having to   */
4747 /*    wait for the disconnect to complete.                                */
4748 /*                                                                        */
4749 /*  INPUT                                                                 */
4750 /*                                                                        */
4751 /*    socketID                                                            */
4752 /*                                                                        */
4753 /*  OUTPUT                                                                */
4754 /*                                                                        */
4755 /*    NX_SOC_OK (0)                         On success                    */
4756 /*    NX_SOC_ERROR (-1)                     On failure                    */
4757 /*                                                                        */
4758 /*  CALLS                                                                 */
4759 /*                                                                        */
4760 /*    memset                                Clear memory                  */
4761 /*    nx_tcp_socket_disconnect              Disconnect a TCP Socket       */
4762 /*    nx_tcp_client_socket_unbind           Unbind the socket             */
4763 /*    nx_tcp_server_socket_unaccept         Unaccept the socket           */
4764 /*    nx_tcp_server_socket_unlisten         Unlisten on a port            */
4765 /*    nx_tcp_socket_delete                  Deletes a TCP Socket          */
4766 /*    nx_udp_socket_unbind                  Unbind a UDP Socket           */
4767 /*    nx_udp_socket_delete                  Deletes a UDP Socket          */
4768 /*    tx_block_release                      Release block for socket      */
4769 /*    tx_mutex_get                          Get protection                */
4770 /*    tx_mutex_put                          Release protection            */
4771 /*                                                                        */
4772 /*  CALLED BY                                                             */
4773 /*                                                                        */
4774 /*    Application Code                                                    */
4775 /*                                                                        */
4776 /*  RELEASE HISTORY                                                       */
4777 /*                                                                        */
4778 /*    DATE              NAME                      DESCRIPTION             */
4779 /*                                                                        */
4780 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4781 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4782 /*                                            resulting in version 6.1    */
4783 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
4784 /*                                            used new API/structs naming,*/
4785 /*                                            resulting in version 6.3.0  */
4786 /*                                                                        */
4787 /**************************************************************************/
nx_bsd_soc_close(INT sockID)4788 INT  nx_bsd_soc_close(INT sockID)
4789 {
4790 
4791 NX_BSD_SOCKET       *bsd_socket_ptr;
4792 NX_TCP_SOCKET       *tcp_socket_ptr;
4793 NX_UDP_SOCKET       *udp_socket_ptr;
4794 NX_PACKET           *packet_ptr;
4795 NX_PACKET           *next_packet_ptr;
4796 ULONG                timeout;
4797 INT                  i;
4798 UINT                 counter;
4799 INT                  delete_socket;
4800 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4801 INT                  protocol;
4802 UINT                 index;
4803 #endif
4804 
4805     /* Check for a valid socket ID.  */
4806     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
4807     {
4808 
4809         /* Set the socket error. */
4810         nx_bsd_set_errno(EBADF);
4811 
4812         /* Error, invalid socket ID.  */
4813         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4814         return(NX_SOC_ERROR);
4815     }
4816 
4817     /* Normalize the socket ID.  */
4818     sockID =  sockID - NX_BSD_SOCKFD_START;
4819 
4820     /* Set up a pointer to the BSD socket.  */
4821     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
4822 
4823     /* Get the protection mutex.  */
4824     tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
4825 
4826     /* Is the socket already in use?  */
4827     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
4828     {
4829 
4830         /* No; If the NetX socket associated with this BSD socket been deleted, this is ok. */
4831         if (!bsd_socket_ptr -> nx_bsd_socket_tcp_socket && !bsd_socket_ptr -> nx_bsd_socket_udp_socket)
4832         {
4833 
4834             /* Yes, no further action possible. Release the protection mutex.  */
4835             tx_mutex_put(nx_bsd_protection_ptr);
4836 
4837             return NX_SOC_OK;
4838         }
4839 
4840         /* Otherwise, it is an error if socket not in use anymore.  */
4841 
4842         /* Release the protection mutex.  */
4843         tx_mutex_put(nx_bsd_protection_ptr);
4844 
4845         /* Set the socket error if extended socket options enabled. */
4846         nx_bsd_set_errno(EACCES);
4847 
4848         /* Return error.  */
4849         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4850         return(NX_SOC_ERROR);
4851     }
4852 
4853     /* Set NetX socket pointers.  */
4854     tcp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
4855     udp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_udp_socket;
4856 
4857     /* There is. Flush the queue of all packets. */
4858     packet_ptr = bsd_socket_ptr -> nx_bsd_socket_received_packet;
4859     /* Setup packet pointer to the beginning of the queue.  */
4860     while(packet_ptr)
4861     {
4862         next_packet_ptr = packet_ptr -> nx_packet_queue_next;
4863 
4864         /* Mark it as allocated so it will be released.  */
4865         packet_ptr -> nx_packet_queue_next =  (NX_PACKET *) NX_PACKET_ALLOCATED;
4866 
4867         nx_packet_release(packet_ptr);
4868 
4869         /* Move to the next packet */
4870         packet_ptr = next_packet_ptr;
4871     }
4872 
4873     bsd_socket_ptr -> nx_bsd_socket_received_packet = NX_NULL;
4874     bsd_socket_ptr -> nx_bsd_socket_received_packet_tail = NX_NULL;
4875     bsd_socket_ptr -> nx_bsd_socket_received_byte_count = 0;
4876     bsd_socket_ptr -> nx_bsd_socket_received_packet_count = 0;
4877     bsd_socket_ptr -> nx_bsd_socket_received_packet_count_max = 0;
4878 
4879     /* Now delete the underlying TCP or UDP socket. */
4880 
4881     /* Is this a TCP socket? */
4882     if (tcp_socket_ptr)
4883     {
4884 
4885         /* If the socket has not been closed, disconnect it. This would be the case
4886            if NetX already closed the socket e.g. a RST packet received before the
4887            host application called this function. */
4888         if (tcp_socket_ptr -> nx_tcp_socket_state != NX_TCP_CLOSED)
4889         {
4890 
4891             /* Disconnect the socket. */
4892 
4893             /* If the disconnect takes more than the timeout option, NetX marks the socket as "closed"
4894                or puts it back to "listen" state. The default value is 1 to emulate an immediate
4895                socket closure without sending a RST packet.  */
4896             timeout = NX_BSD_TCP_SOCKET_DISCONNECT_TIMEOUT;
4897 
4898             /* Release the mutex while disconnecting. */
4899             tx_mutex_put(nx_bsd_protection_ptr);
4900 
4901             nx_tcp_socket_disconnect(tcp_socket_ptr, timeout);
4902 
4903             tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
4904 
4905             /* Verify that the socket is still valid. */
4906             if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
4907             {
4908                 /* The socket is no longer in use. */
4909 
4910                 /* Set the socket error code. */
4911                 nx_bsd_set_errno(EBADF);
4912 
4913                 /* Release the protection mutex.  */
4914                 tx_mutex_put(nx_bsd_protection_ptr);
4915 
4916                 /* Return error code.  */
4917                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4918                 return(NX_SOC_ERROR);
4919             }
4920         }
4921         /* Make sure the socket is unbound, not accepting connections and not bound to a listening port. */
4922         if(tcp_socket_ptr -> nx_tcp_socket_port)
4923         {
4924 
4925             if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CLIENT)
4926             {
4927                 nx_tcp_client_socket_unbind(tcp_socket_ptr);
4928             }
4929             else
4930             {
4931                 nx_tcp_server_socket_unaccept(tcp_socket_ptr);
4932             }
4933 
4934         }
4935 
4936         /* Now we can delete the NetX TCP socket.  */
4937         nx_tcp_socket_delete(tcp_socket_ptr);
4938 
4939         /* Clear the TCP socket structure.  */
4940         memset((VOID *) tcp_socket_ptr, 0, sizeof(NX_TCP_SOCKET));
4941 
4942         /* Release the NetX TCP socket.  */
4943         tx_block_release((VOID *) tcp_socket_ptr);
4944 
4945         /* If this is the master server socket, we need to unaccept the
4946            associated secondary socket. */
4947         if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET)
4948         {
4949 
4950             INT sec_soc_id = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id;
4951 
4952             if(sec_soc_id < NX_BSD_MAX_SOCKETS)
4953             {
4954 
4955                 /* Find whether or not this is the only master socket that is connected to this
4956                    secondary socket. */
4957                 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
4958                 {
4959 
4960                     if(i == sockID)
4961                         continue;
4962 
4963                     if((nx_bsd_socket_array[i].nx_bsd_socket_protocol == NX_PROTOCOL_TCP) &&
4964                        (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) &&
4965                        (nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id == sec_soc_id))
4966                     {
4967                         break;
4968                     }
4969                 }
4970 
4971                 if(i == NX_BSD_MAX_SOCKETS)
4972                 {
4973 
4974                     /* Unaccept and unlisten on the socket/port */
4975                     /* nx_tcp_server_socket_unaccept(tcp_socket_ptr); */
4976                     /* nx_tcp_server_socket_unlisten(nx_bsd_default_ip, tcp_socket_ptr -> nx_tcp_socket_port); */
4977 
4978                     /* Release the secondary socket if there are no more master sockets associated
4979                        with this secondary socket. */
4980 
4981                     tcp_socket_ptr = nx_bsd_socket_array[sec_soc_id].nx_bsd_socket_tcp_socket;
4982 
4983                     /* If the secondary socket has not been closed, disconnect it. This would be the case
4984                        if NetX already closed the master socket. */
4985                     if (tcp_socket_ptr -> nx_tcp_socket_state != NX_TCP_CLOSED)
4986                     {
4987 
4988                         /* Disconnect the socket. */
4989 
4990                         /* If the disconnect takes more than the timeout option, NetX marks the socket as "closed"
4991                            or puts it back to "listen" state. The default value is 1 to emulate an immediate
4992                            socket closure without sending a RST packet.  */
4993                         timeout = NX_BSD_TCP_SOCKET_DISCONNECT_TIMEOUT;
4994 
4995                         /* Release the mutex while disconnecting. */
4996                         tx_mutex_put(nx_bsd_protection_ptr);
4997 
4998                         nx_tcp_socket_disconnect(tcp_socket_ptr, timeout);
4999 
5000                         tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
5001 
5002                         /* Verify that the socket is still valid. */
5003                         if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
5004                         {
5005                             /* The socket is no longer in use. */
5006 
5007                             /* Set the socket error code. */
5008                             nx_bsd_set_errno(EBADF);
5009 
5010                             /* Release the protection mutex.  */
5011                             tx_mutex_put(nx_bsd_protection_ptr);
5012 
5013                             /* Return error code.  */
5014                             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5015                             return(NX_SOC_ERROR);
5016                         }
5017                     }
5018 
5019                     /* Unaccept on the secondary socket. */
5020                     nx_tcp_server_socket_unaccept(tcp_socket_ptr);
5021                     nx_tcp_server_socket_unlisten(nx_bsd_default_ip, tcp_socket_ptr -> nx_tcp_socket_port);
5022                     nx_tcp_socket_delete(tcp_socket_ptr);
5023 
5024                     memset((VOID*)tcp_socket_ptr, 0, sizeof(NX_TCP_SOCKET));
5025                     tx_block_release((VOID*)tcp_socket_ptr);
5026                     memset((VOID*)&(nx_bsd_socket_array[sec_soc_id]), 0, sizeof(NX_BSD_SOCKET));
5027                 }
5028             }
5029         }
5030 
5031         /* Finally Clear the BSD socket structure.  */
5032         memset((VOID *) bsd_socket_ptr, 0, sizeof(NX_BSD_SOCKET));
5033 
5034         tx_mutex_put(nx_bsd_protection_ptr);
5035 
5036         /* Return */
5037         return(NX_SOC_OK);
5038 
5039     }
5040     else if (udp_socket_ptr)
5041     {
5042 
5043         /* A UDP socket needs to be closed.  */
5044 
5045         /* Check whether this is the last BSD socket attached to the NX_UDP_SOCKET */
5046         counter = (UINT)udp_socket_ptr -> nx_udp_socket_reserved_ptr;
5047 
5048         delete_socket = NX_TRUE;
5049         /* Decrease the counter value. */
5050         if(counter & 0xFFFF0000)
5051         {
5052 
5053             counter = ((counter & 0xFFFF0000) - 0x00010000 + (counter & 0x0000FFFF)) & 0xFFFFFFFF;
5054 
5055             udp_socket_ptr -> nx_udp_socket_reserved_ptr = (VOID*)counter;
5056 
5057             if(counter & 0xFFFF0000)
5058             {
5059 
5060                 /* Do not delete this socket. */
5061                 delete_socket = NX_FALSE;
5062 
5063                 /* If the underlying NX_UDP_SOCKET points to this UDP socket, we need to
5064                    reassign a BSD socket to the NX UDP socket. */
5065                 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
5066                 {
5067 
5068                     if((nx_bsd_socket_array[i].nx_bsd_socket_udp_socket == udp_socket_ptr) &&
5069                        (i != sockID))
5070                     {
5071 
5072                         counter = (counter & 0xFFFF0000) + (UINT)i;
5073                         udp_socket_ptr -> nx_udp_socket_reserved_ptr = (VOID*)counter;
5074                         break;
5075                     }
5076                 }
5077 
5078                 if(i == NX_BSD_MAX_SOCKETS)
5079                 {
5080                     delete_socket = NX_TRUE;
5081                 }
5082             }
5083         }
5084 
5085         if(delete_socket == NX_TRUE)
5086         {
5087 
5088             if(udp_socket_ptr -> nx_udp_socket_bound_next)
5089             {
5090                 nx_udp_socket_unbind(udp_socket_ptr);
5091             }
5092 
5093             /* Socket successfully unbound. Now delete the UDP socket.  */
5094             nx_udp_socket_delete(udp_socket_ptr);
5095 
5096             /* Clear the UDP socket block.  */
5097             memset((VOID *) udp_socket_ptr, 0, sizeof(NX_UDP_SOCKET));
5098 
5099             /* Release the NetX UDP socket memory.  */
5100             tx_block_release((VOID *) udp_socket_ptr);
5101         }
5102         else
5103         {
5104             /* Remove this bsd udp socket from the list. */
5105             (bsd_socket_ptr -> nx_bsd_socket_next) -> nx_bsd_socket_previous = bsd_socket_ptr -> nx_bsd_socket_previous;
5106             (bsd_socket_ptr -> nx_bsd_socket_previous) -> nx_bsd_socket_next = bsd_socket_ptr -> nx_bsd_socket_next;
5107         }
5108 
5109         /* Clear the BSD socket block.  */
5110         memset((VOID *) bsd_socket_ptr, 0, sizeof(NX_BSD_SOCKET));
5111 
5112         /* Release the protection mutex.  */
5113         tx_mutex_put(nx_bsd_protection_ptr);
5114 
5115         return(NX_SOC_OK);
5116     }
5117 
5118 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
5119     else if (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET)
5120     {
5121 
5122         /* There is no native NetX Duo raw socket to delete or
5123            port to unbind. So just release the BSD socket memory.  */
5124 
5125         /* Remove this socket from the list. */
5126         protocol = bsd_socket_ptr -> nx_bsd_socket_protocol;
5127 
5128         /* Calculate the hash index in the raw socket protocol table. */
5129         index = (UINT) ((protocol + (protocol >> 8)) & NX_BSD_SOCKET_RAW_PROTOCOL_TABLE_MASK);
5130 
5131         /* Determine if this is the only socket on this list. */
5132         if(bsd_socket_ptr -> nx_bsd_socket_next == bsd_socket_ptr)
5133         {
5134             /* Yes, this is the only socket on the list. */
5135 
5136             /* Clear the list head pointer. */
5137             nx_bsd_socket_raw_protocol_table[index] = NX_NULL;
5138         }
5139         else
5140         {
5141             /* Remove this bsd udp socket from the list. */
5142              (bsd_socket_ptr -> nx_bsd_socket_next) -> nx_bsd_socket_previous = bsd_socket_ptr -> nx_bsd_socket_previous;
5143              (bsd_socket_ptr -> nx_bsd_socket_previous) -> nx_bsd_socket_next = bsd_socket_ptr -> nx_bsd_socket_next;
5144 
5145              /* Determine if the head of the list points to the socket being removed.
5146                 If so, we need to move the head pointer. */
5147              if(nx_bsd_socket_raw_protocol_table[index] == bsd_socket_ptr)
5148              {
5149                  /* Yes, we need to move the list head pointer. */
5150                  nx_bsd_socket_raw_protocol_table[index] = bsd_socket_ptr -> nx_bsd_socket_next;
5151              }
5152         }
5153 
5154         /* Clear the BSD socket block.  */
5155         memset((VOID *) bsd_socket_ptr, 0, sizeof(NX_BSD_SOCKET));
5156 
5157         /* Release the protection mutex.  */
5158         tx_mutex_put(nx_bsd_protection_ptr);
5159 
5160         return(NX_SOC_OK);
5161 
5162     }
5163 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
5164 #if defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT)
5165     else if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
5166     {
5167         /* There is no native NetX Duo raw socket to delete or
5168            port to unbind. So just release the BSD socket memory.  */
5169 
5170         /* Clear the BSD socket block.  */
5171         memset((VOID *) bsd_socket_ptr, 0, sizeof(NX_BSD_SOCKET));
5172 
5173         /* Release the protection mutex.  */
5174         tx_mutex_put(nx_bsd_protection_ptr);
5175 
5176         return(NX_SOC_OK);
5177     }
5178 
5179 #endif /* defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT) */
5180 
5181 
5182 
5183 
5184     /* Unknown socket type or invalid socket. */
5185 
5186     /* Release the protection mutex.  */
5187     tx_mutex_put(nx_bsd_protection_ptr);
5188 
5189     /* Set the socket error if extended socket options enabled. */
5190     nx_bsd_set_errno(EINVAL);
5191 
5192     /* Return error.  */
5193     NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5194     return(NX_SOC_ERROR);
5195 
5196 
5197 
5198 }
5199 
5200 /**************************************************************************/
5201 /*                                                                        */
5202 /*  FUNCTION                                               RELEASE        */
5203 /*                                                                        */
5204 /*    fcntl                                               PORTABLE C      */
5205 /*                                                           6.3.0        */
5206 /*  AUTHOR                                                                */
5207 /*                                                                        */
5208 /*    Yuxin Zhou, Microsoft Corporation                                   */
5209 /*                                                                        */
5210 /*  DESCRIPTION                                                           */
5211 /*                                                                        */
5212 /*    This function performs the requested operation on the file (e.g.    */
5213 /*    socket) descriptor set.  This implementation supports only the set  */
5214 /*    or get flag, and only sets (or clears) the non blocking option.     */
5215 /*                                                                        */
5216 /*  INPUT                                                                 */
5217 /*                                                                        */
5218 /*    sockID                                socket descriptor             */
5219 /*    flag_type                             File description request      */
5220 /*    f_options                             Option(s) to set on the       */
5221 /*                                              specified file (socket)   */
5222 /*                                                                        */
5223 /*  OUTPUT                                                                */
5224 /*                                                                        */
5225 /*    NX_SOC_ERROR                          Errors with request           */
5226 /*    (file descriptor flags)               File descriptor flags         */
5227 /*                                                                        */
5228 /*  CALLS                                                                 */
5229 /*                                                                        */
5230 /*    tx_mutex_get                          Get protection                */
5231 /*    tx_mutex_put                          Release protection            */
5232 /*                                                                        */
5233 /*  CALLED BY                                                             */
5234 /*                                                                        */
5235 /*    Application Code                                                    */
5236 /*                                                                        */
5237 /*  RELEASE HISTORY                                                       */
5238 /*                                                                        */
5239 /*    DATE              NAME                      DESCRIPTION             */
5240 /*                                                                        */
5241 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5242 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5243 /*                                            resulting in version 6.1    */
5244 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
5245 /*                                            used new API/structs naming,*/
5246 /*                                            resulting in version 6.3.0  */
5247 /*                                                                        */
5248 /**************************************************************************/
nx_bsd_fcntl(INT sockID,UINT flag_type,UINT f_options)5249 INT nx_bsd_fcntl(INT sockID, UINT flag_type, UINT f_options)
5250 {
5251 
5252 NX_BSD_SOCKET   *bsd_socket_ptr;
5253 
5254     /* Check for invalid socket ID. */
5255     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
5256     {
5257 
5258         /* Set the socket error if extended options enabled. */
5259         nx_bsd_set_errno(EBADF);
5260 
5261         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5262 
5263         /* Return error status. */
5264         return NX_SOC_ERROR;
5265     }
5266 
5267     /* Normalize the socket ID to our array. */
5268     sockID =  sockID - NX_BSD_SOCKFD_START;
5269 
5270     /* Build pointer to BSD socket structure.  */
5271     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
5272 
5273     if(flag_type == F_SETFL)
5274     {
5275         /* Set the FD flag. */
5276         bsd_socket_ptr -> nx_bsd_file_descriptor_flags = (INT)f_options;
5277 
5278 
5279         /* Are there flags to clear? */
5280         if ((f_options & O_NONBLOCK) == 0)
5281         {
5282             /* Disable the socket for non blocking. */
5283             bsd_socket_ptr -> nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING);
5284         }
5285         else
5286         {
5287             /* Enable the socket for non blocking. */
5288             bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING;
5289         }
5290 
5291         /* All done. Return 0 */
5292         return(0);
5293     }
5294     else if(flag_type == F_GETFL)
5295     {
5296         return(bsd_socket_ptr -> nx_bsd_file_descriptor_flags);
5297     }
5298     /* Flag_type is not the one we support */
5299 
5300     /* Set the socket error if extended socket options enabled. */
5301     nx_bsd_set_errno(EINVAL);
5302 
5303     NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5304 
5305     /* Return error status. */
5306     return NX_SOC_ERROR;
5307 
5308 
5309 
5310 }
5311 
5312 
5313 /**************************************************************************/
5314 /*                                                                        */
5315 /*  FUNCTION                                               RELEASE        */
5316 /*                                                                        */
5317 /*    ioctl                                               PORTABLE C      */
5318 /*                                                           6.3.0        */
5319 /*  AUTHOR                                                                */
5320 /*                                                                        */
5321 /*    Yuxin Zhou, Microsoft Corporation                                   */
5322 /*                                                                        */
5323 /*  DESCRIPTION                                                           */
5324 /*                                                                        */
5325 /*    This function carries out a socket IO service specified by the      */
5326 /*    command.                                                            */
5327 /*                                                                        */
5328 /*  INPUT                                                                 */
5329 /*                                                                        */
5330 /*    sockID                                Socket (must be connected).   */
5331 /*    command                               IO command for ioctl function */
5332 /*    result                                data returned (value)         */
5333 /*                                                                        */
5334 /*  OUTPUT                                                                */
5335 /*                                                                        */
5336 /*    Number of bytes received              If success                    */
5337 /*    NX_SOC_ERROR (-1)                     Error during socket opration  */
5338 /*    NX_SOC_OK (0)                         Successful completion         */
5339 /*                                                                        */
5340 /*  CALLS                                                                 */
5341 /*                                                                        */
5342 /*    nx_tcp_socket_bytes_available         Retreive number of bytes on   */
5343 /*                                               the specified TCP socket */
5344 /*    nx_udp_socket_bytes_available         Retreive number of bytes on   */
5345 /*                                               the specified UDP socket */
5346 /*    tx_mutex_get                          Get protection                */
5347 /*    tx_mutex_put                          Release protection            */
5348 /*                                                                        */
5349 /*  CALLED BY                                                             */
5350 /*                                                                        */
5351 /*    Application Code                                                    */
5352 /*                                                                        */
5353 /*  RELEASE HISTORY                                                       */
5354 /*                                                                        */
5355 /*    DATE              NAME                      DESCRIPTION             */
5356 /*                                                                        */
5357 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5358 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5359 /*                                            resulting in version 6.1    */
5360 /*  03-08-2023     Wenhui Xie               Modified comment(s), corrected*/
5361 /*                                            the result of FIONREAD,     */
5362 /*                                            resulting in version 6.2.1  */
5363 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
5364 /*                                            used new API/structs naming,*/
5365 /*                                            resulting in version 6.3.0  */
5366 /*                                                                        */
5367 /**************************************************************************/
nx_bsd_ioctl(INT sockID,INT command,INT * result)5368 INT  nx_bsd_ioctl(INT sockID,  INT command, INT *result)
5369 {
5370 
5371 NX_BSD_SOCKET       *bsd_socket_ptr;
5372 NX_TCP_SOCKET       *tcp_socket_ptr;
5373 NX_UDP_SOCKET       *udp_socket_ptr;
5374 UINT                status;
5375 
5376 
5377     /* Check that the supplied socket ID is valid.  */
5378     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
5379     {
5380 
5381         /* Error, invalid socket ID.  */
5382         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5383         return(NX_SOC_ERROR);
5384     }
5385 
5386     /* Normalize the socket ID.  */
5387     sockID =  sockID - NX_BSD_SOCKFD_START;
5388 
5389     /* Get the protection mutex.  */
5390     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
5391 
5392     /* Check the status.  */
5393     if (status)
5394     {
5395 
5396         /* Error getting the protection mutex.  */
5397         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
5398         return(NX_SOC_ERROR);
5399     }
5400 
5401     /* Set a pointer to the BSD socket.  */
5402     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
5403 
5404     /* Pick up the associated NetX socket pointers.  */
5405     tcp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
5406     udp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_udp_socket;
5407 
5408     /* Handle the command. */
5409     switch (command)
5410     {
5411 
5412         case FIONREAD:
5413         {
5414 
5415             /* Check NULL pointer. */
5416             if(result == NX_NULL)
5417             {
5418                 tx_mutex_put(nx_bsd_protection_ptr);
5419 
5420                 nx_bsd_set_errno(EFAULT);
5421 
5422                 /* Error, invalid address. */
5423                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5424 
5425                 return(NX_SOC_ERROR);
5426             }
5427 
5428             /* Determine which socket pointer to use.  */
5429             if (tcp_socket_ptr)
5430             {
5431 
5432                 /* Extract the number of bytes on the TCP receive queue. */
5433                 status = nx_tcp_socket_bytes_available(tcp_socket_ptr, (ULONG *)result);
5434 
5435                 if (status != NX_SUCCESS)
5436                 {
5437 
5438                     tx_mutex_put(nx_bsd_protection_ptr);
5439 
5440                     /* Error in the native NetX call.  */
5441                     NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
5442                     return(NX_SOC_ERROR);
5443                 }
5444                 else
5445                 {
5446                     *result += (INT)(bsd_socket_ptr -> nx_bsd_socket_received_byte_count);
5447             }
5448             }
5449             else if (udp_socket_ptr)
5450             {
5451 
5452                 /* Extract the number of bytes on the UDP receive queue. */
5453                 *result = (INT)(bsd_socket_ptr ->  nx_bsd_socket_received_byte_count);
5454             }
5455 
5456             break;
5457         }
5458 
5459         case FIONBIO:
5460         {
5461 
5462             /* Check NULL pointer. */
5463             if(result == NX_NULL)
5464             {
5465                 tx_mutex_put(nx_bsd_protection_ptr);
5466 
5467                 nx_bsd_set_errno(EFAULT);
5468 
5469                 /* Error, invalid address. */
5470                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5471 
5472                 return(NX_SOC_ERROR);
5473             }
5474 
5475             if(*result == NX_FALSE)
5476             {
5477 
5478                 /* Disable the socket for non blocking. */
5479                 bsd_socket_ptr -> nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING);
5480 
5481                 /* Update the file descriptor with the non blocking bit. */
5482                 bsd_socket_ptr -> nx_bsd_file_descriptor_flags  &= ~O_NONBLOCK;
5483             }
5484             else
5485             {
5486 
5487                 /* Enable the socket for non blocking. */
5488                 bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING;
5489 
5490                 /* Update the file descriptor with the non blocking bit. */
5491                 bsd_socket_ptr -> nx_bsd_file_descriptor_flags  |= O_NONBLOCK;
5492             }
5493 
5494             break;
5495         }
5496 
5497         default:
5498 
5499             /* Unhandled command; ignore  */
5500             break;
5501     }
5502 
5503     tx_mutex_put(nx_bsd_protection_ptr);
5504 
5505     return NX_SOC_OK;
5506 }
5507 
5508 /**************************************************************************/
5509 /*                                                                        */
5510 /*  FUNCTION                                               RELEASE        */
5511 /*                                                                        */
5512 /*    inet_ntoa                                           PORTABLE C      */
5513 /*                                                           6.3.0        */
5514 /*  AUTHOR                                                                */
5515 /*                                                                        */
5516 /*    Yuxin Zhou, Microsoft Corporation                                   */
5517 /*                                                                        */
5518 /*  DESCRIPTION                                                           */
5519 /*                                                                        */
5520 /*    This function converts an IP address to a string and returns a      */
5521 /*    pointer to the string.  The caller is recommended to copy the       */
5522 /*    contents of the buffer to local memory since this function and      */
5523 /*    internal buffer can be reused.                                      */
5524 /*                                                                        */
5525 /*  INPUT                                                                 */
5526 /*                                                                        */
5527 /*    address_to_convert                    Struct holding IP address.    */
5528 /*                                                                        */
5529 /*  OUTPUT                                                                */
5530 /*                                                                        */
5531 /*    char *                                Pointer to converted string   */
5532 /*    0x0                                   Error during conversion       */
5533 /*                                                                        */
5534 /*  CALLS                                                                 */
5535 /*                                                                        */
5536 /*    tx_mutex_get                          Get mutex protection          */
5537 /*    bsd_number_convert                    Convert integer to ascii      */
5538 /*                                                                        */
5539 /*  CALLED BY                                                             */
5540 /*                                                                        */
5541 /*    Application Code                                                    */
5542 /*                                                                        */
5543 /*  RELEASE HISTORY                                                       */
5544 /*                                                                        */
5545 /*    DATE              NAME                      DESCRIPTION             */
5546 /*                                                                        */
5547 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5548 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5549 /*                                            resulting in version 6.1    */
5550 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
5551 /*                                            used new API/structs naming,*/
5552 /*                                            resulting in version 6.3.0  */
5553 /*                                                                        */
5554 /**************************************************************************/
nx_bsd_inet_ntoa(struct nx_bsd_in_addr address_to_convert)5555 CHAR *nx_bsd_inet_ntoa(struct nx_bsd_in_addr address_to_convert)
5556 {
5557 UINT status;
5558 
5559     /* Because we are using global buffer space to write out the string, get the protection mutex.  */
5560     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
5561 
5562     if (status != NX_SUCCESS)
5563     {
5564         return NX_NULL;
5565     }
5566 
5567     inet_ntoa_internal(&address_to_convert, nx_bsd_url_buffer, NX_BSD_URL_BUFSIZE);
5568 
5569     tx_mutex_put(nx_bsd_protection_ptr);
5570 
5571     /* Return the start of the string buffer. */
5572     return nx_bsd_url_buffer;
5573 
5574 }
5575 
5576 /**************************************************************************/
5577 /*                                                                        */
5578 /*  FUNCTION                                               RELEASE        */
5579 /*                                                                        */
5580 /*    bsd_number_convert                                  PORTABLE C      */
5581 /*                                                           6.1          */
5582 /*  AUTHOR                                                                */
5583 /*                                                                        */
5584 /*    Yuxin Zhou, Microsoft Corporation                                   */
5585 /*                                                                        */
5586 /*  DESCRIPTION                                                           */
5587 /*                                                                        */
5588 /*    This function converts an integer to a string.                      */
5589 /*                                                                        */
5590 /*  INPUT                                                                 */
5591 /*                                                                        */
5592 /*    number                                Number to convert             */
5593 /*    string                                Pointer to string buffer      */
5594 /*    buffer_len                            Size of the string buffer     */
5595 /*    base                                  the base of the number,       */
5596 /*                                          2,8,10,16                     */
5597 /*                                                                        */
5598 /*  OUTPUT                                                                */
5599 /*                                                                        */
5600 /*    size                                  Size of string buffer         */
5601 /*                                                                        */
5602 /*  CALLS                                                                 */
5603 /*                                                                        */
5604 /*    None                                                                */
5605 /*                                                                        */
5606 /*  CALLED BY                                                             */
5607 /*                                                                        */
5608 /*    Application Code                                                    */
5609 /*                                                                        */
5610 /*  RELEASE HISTORY                                                       */
5611 /*                                                                        */
5612 /*    DATE              NAME                      DESCRIPTION             */
5613 /*                                                                        */
5614 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5615 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5616 /*                                            resulting in version 6.1    */
5617 /*                                                                        */
5618 /**************************************************************************/
bsd_number_convert(UINT number,CHAR * string,ULONG buffer_len,UINT base)5619 UINT  bsd_number_convert(UINT number, CHAR *string, ULONG buffer_len, UINT base)
5620 {
5621 
5622 UINT    j;
5623 UINT    digit;
5624 UINT    size;
5625 
5626 
5627     /* Initialize counters.  */
5628     size =  0;
5629 
5630     /* Loop to convert the number to ASCII.  */
5631     while (size < buffer_len)
5632     {
5633 
5634         /* Shift the current digits over one.  */
5635         for (j = size; j != 0; j--)
5636         {
5637 
5638             /* Move each digit over one place.  */
5639             string[j] =  string[j-1];
5640         }
5641 
5642         /* Compute the next decimal digit.  */
5643         digit =  number % base;
5644 
5645         /* Update the input number.  */
5646         number =  number / base;
5647 
5648         /* Store the new digit in ASCII form.  */
5649         if(digit < 10)
5650             string[0] =  (CHAR) (digit + 0x30);
5651         else
5652             string[0] =  (CHAR) (digit + 0x57);
5653 
5654         /* Increment the size.  */
5655         size++;
5656 
5657         /* Determine if the number is now zero.  */
5658         if (number == 0)
5659             break;
5660     }
5661 
5662     /* Make the string NULL terminated.  */
5663     string[size] =  (CHAR) NX_NULL;
5664 
5665     /* Determine if there is an overflow error.  */
5666     if (number)
5667     {
5668 
5669         /* Error, return bad values to user.  */
5670         size =  0;
5671         string[0] = '0';
5672     }
5673 
5674     /* Return size to caller.  */
5675     return(size);
5676 }
5677 
5678 /**************************************************************************/
5679 /*                                                                        */
5680 /*  FUNCTION                                               RELEASE        */
5681 /*                                                                        */
5682 /*    inet_aton                                           PORTABLE C      */
5683 /*                                                           6.3.0        */
5684 /*  AUTHOR                                                                */
5685 /*                                                                        */
5686 /*    Yuxin Zhou, Microsoft Corporation                                   */
5687 /*                                                                        */
5688 /*  DESCRIPTION                                                           */
5689 /*                                                                        */
5690 /*    This function converts hexadecimal characters into an ASCII IP      */
5691 /*    address representation.                                             */
5692 /*                                                                        */
5693 /*  INPUT                                                                 */
5694 /*                                                                        */
5695 /*    address_buffer_ptr                    String holding the IP address */
5696 /*    addr                                  Struct to store the IP address*/
5697 /*                                                                        */
5698 /*  OUTPUT                                                                */
5699 /*                                                                        */
5700 /*    NX_SUCCESS                            Successful conversion         */
5701 /*    NX_SOC_ERROR                          Error during conversion       */
5702 /*                                                                        */
5703 /*  CALLS                                                                 */
5704 /*                                                                        */
5705 /*    nx_bsd_isdigit                        Indicate char is a number     */
5706 /*    isspace                               Indicate char is a space      */
5707 /*    islower                               Indicate char is lowercase    */
5708 /*    htonl                                 Convert to network byte order */
5709 /*                                                                        */
5710 /*  CALLED BY                                                             */
5711 /*                                                                        */
5712 /*    Application Code                                                    */
5713 /*                                                                        */
5714 /*  RELEASE HISTORY                                                       */
5715 /*                                                                        */
5716 /*    DATE              NAME                      DESCRIPTION             */
5717 /*                                                                        */
5718 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5719 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5720 /*                                            resulting in version 6.1    */
5721 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
5722 /*                                            used new API/structs naming,*/
5723 /*                                            resulting in version 6.3.0  */
5724 /*                                                                        */
5725 /**************************************************************************/
nx_bsd_inet_aton(const CHAR * address_buffer_ptr,struct nx_bsd_in_addr * addr)5726 INT nx_bsd_inet_aton(const CHAR *address_buffer_ptr, struct nx_bsd_in_addr *addr)
5727 {
5728 ULONG value;
5729 INT   base = 10, ip_address_index;
5730 UCHAR tempchar;
5731 const UCHAR *buffer_ptr;
5732 UINT  ip_address_number[4];  /* Four discreet numbers in IP address representation. */
5733 UINT *ip_number_ptr;         /* IP address as equivalent ULONG value. */
5734 UINT  dot_flag;
5735 
5736     /* Set local variables. */
5737     buffer_ptr = (const UCHAR *) address_buffer_ptr;
5738     ip_number_ptr = ip_address_number;
5739 
5740     tempchar = *buffer_ptr;
5741 
5742     /* Check for an invalid first character. */
5743     if (nx_bsd_isdigit(tempchar)== NX_FALSE)
5744     {
5745         return (0);
5746     }
5747 
5748     dot_flag = 1;
5749 
5750     /* Parse the rest of the characters from the input number. */
5751     do
5752     {
5753 
5754         /* Initialize the (next) extracted IP address number to zero. */
5755         value = 0;
5756 
5757         if(dot_flag== 1)
5758         {
5759             /* Initialize the numeric base to decimal unless we determine hex or octal. */
5760             base = 10;
5761 
5762             /* Determine which number base the input number buffer is. */
5763             if (*buffer_ptr == '0')
5764             {
5765                 /* Get the next character. */
5766                 buffer_ptr++;
5767 
5768                 /* A leading 0 followed by an 'x' indicates this is hexidecimal. */
5769                 if ((*buffer_ptr== 'x') || (*buffer_ptr == 'X'))
5770                 {
5771                     base = 16;
5772 
5773                     /* Move ahead one character past the leading '0x' */
5774                     buffer_ptr++;
5775                 }
5776                 else
5777                 {
5778                     /* This is octal. */
5779                     base = 8;
5780                     buffer_ptr--;
5781                 }
5782             }
5783         }
5784 
5785         tempchar = *buffer_ptr;
5786 
5787         /* Parse characters making up the next word. */
5788         while (*buffer_ptr != '\0')
5789         {
5790             /* Check if the next character is a decimal or octal digit. */
5791             if (nx_bsd_isdigit(tempchar))
5792             {
5793 
5794                 dot_flag = 0;
5795 
5796                 /* Convert the tempchar character to a number.  Multiply the existing
5797                    number by the base (8 or 10) and this digit to the sum. */
5798                 value = (value * (ULONG)base) + (ULONG)(tempchar - '0');
5799 
5800                 /* Advance the IP address pointer to the next character. */
5801                 buffer_ptr++;
5802 
5803                 /* Get the next character. */
5804                 tempchar = *buffer_ptr;
5805             }
5806             /* Else check if we are expecting a hexidecimal number. */
5807             else if (nx_bsd_isxdigit(tempchar))
5808             {
5809                 /* We are; Verify the base is 16. */
5810                 if(base == 16)
5811                 {
5812 
5813                     /* It is.  handle upper or lower case hex digit. */
5814                     CHAR c = (CHAR)(nx_bsd_islower(tempchar) ? 'a' : 'A');
5815 
5816                     dot_flag = 0;
5817 
5818                     /* Convert the hex character to a hex digit, multiply the existing word by shifting the bits,
5819                        and add this hex digit to the sum. */
5820                     value = (value << 4) + (ULONG)(tempchar + 10 - c);
5821 
5822                     buffer_ptr++;
5823 
5824                     /* Get the next character. */
5825                     tempchar = *buffer_ptr;
5826                 }
5827                 else
5828                 {
5829                     /* Not a valid hex character. */
5830                     return (0);
5831                 }
5832             }
5833             else
5834             {
5835                 /* We have reached a number separator or possibly end of the string.  */
5836                 break;
5837             }
5838         }
5839 
5840         /* At the end of the current word. Is this a separator character? */
5841         if (*buffer_ptr == '.')
5842         {
5843 
5844             dot_flag = 1;
5845 
5846             /* Yes, check for an invalid number (cannot exceed 255 or 0xFF. */
5847             if (value > 0xff)
5848             {
5849                 return (0);
5850             }
5851 
5852             /* Check that the pointer to the last extracted number does not exceed the array holding the IP address numbers. */
5853             if (ip_number_ptr >= (ip_address_number + 3))
5854             {
5855                 return (0);
5856             }
5857 
5858             /* Copy the computed value into the IP address number buffer. */
5859             *ip_number_ptr = value;
5860 
5861             /* Move the pointer to where we will store the next number extracted. */
5862             ip_number_ptr++;
5863 
5864             /* Move to the next character in the IP address string. */
5865             buffer_ptr++;
5866         }
5867         /* Check for non digit or seperator character indicating (maybe) end of the buffer. */
5868         else
5869             break;
5870 
5871     } while (1);
5872 
5873     /* If this is not a null terminating character, check for invalid trailing characters. */
5874     if (*buffer_ptr)
5875     {
5876 
5877         if((*buffer_ptr != '\0') && (!nx_bsd_isspace(*buffer_ptr)))
5878         {
5879 
5880             return (0);
5881         }
5882     }
5883 
5884     /* IP addresses are grouped as A, B, C, or D types.  Determine which
5885        type address we have by comparing the IP address value against...*/
5886 
5887     /* Determine this by substracting the pointer to beginning of the whole
5888        IP address number ip_number_ptr[4] against the pointer to the last extracted word, ip_address_number. */
5889     ip_address_index = ip_number_ptr - ip_address_number + 1;
5890 
5891     /* Check for an invalid array index (assume 'the array' is indexed 1-4). */
5892     if ((ip_address_index == 0) || (ip_address_index > 4))
5893     {
5894         return (0);
5895     }
5896 
5897     /* Sum each of the individual IP address numbers depending how many there were extracted. */
5898 
5899     /* Most common input... */
5900     if (ip_address_index == 4)
5901     {
5902         INT i;
5903 
5904         /* Three separators parsed, so the format is a.b.c.d where c is 8 bits */
5905 
5906         /* Check for a computed sum greater than can be contained in 8 bits. */
5907        if (value > 0xff)
5908            return (0);
5909 
5910        /* 'Add' the last extracted number by prepending the three other bytes onto the total value. */
5911        for (i = 0; i<=2; i++)
5912        {
5913            value |= ip_address_number[i] << (24 - (i*8));
5914        }
5915     }
5916     /* Most common input... */
5917     else if (ip_address_index == 1)
5918     {
5919 
5920         /* We are done, this address contained one 32 bit word (no separators).  */
5921     }
5922     /* Less common input... */
5923     else if (ip_address_index ==  2)
5924     {
5925         /* One separator, so the format is a.b where b is 24 bits */
5926 
5927         /* Check for a computed sum greater than can be contained in 24 bits. */
5928         if (value > 0xffffff)
5929             return (0);
5930 
5931         /* 'Add' the last extracted number by prepending the most significant byte onto the total value. */
5932         value |= (ip_address_number[0] << 24);
5933      }
5934      else if (ip_address_index ==  3)
5935      {
5936         /* Two separators parsed, so the format is a.b.c where c is 16 bits */
5937          INT i;
5938 
5939          /* Check for a computed sum greater than can be contained in 16 bits. */
5940         if (value > 0xffff)
5941             return (0);
5942 
5943         /* 'Add' the last extracted number by prepending the two most significant bytes onto the total value. */
5944         for (i = 0; i<=1; i++)
5945         {
5946             value |= ip_address_number[i] << (24 - (i*8));
5947         }
5948      }
5949 
5950     /* Check if a return pointer for the address data is supplied. */
5951     if (addr)
5952     {
5953 
5954         /* Convert the IP address data to network byte order and return the data. */
5955         addr->s_addr = htonl(value);
5956     }
5957 
5958     return (1);
5959 }
5960 
5961 
5962 /**************************************************************************/
5963 /*                                                                        */
5964 /*  FUNCTION                                               RELEASE        */
5965 /*                                                                        */
5966 /*    inet_addr                                           PORTABLE C      */
5967 /*                                                           6.3.0        */
5968 /*  AUTHOR                                                                */
5969 /*                                                                        */
5970 /*    Yuxin Zhou, Microsoft Corporation                                   */
5971 /*                                                                        */
5972 /*  DESCRIPTION                                                           */
5973 /*                                                                        */
5974 /*    This function converts an IP address string to a number. If it      */
5975 /*    detects an error in the conversion it returns a zero address.       */
5976 /*                                                                        */
5977 /*  INPUT                                                                 */
5978 /*                                                                        */
5979 /*    buffer                                IP address text buffer        */
5980 /*    address                               Converted address number      */
5981 /*                                                                        */
5982 /*  OUTPUT                                                                */
5983 /*                                                                        */
5984 /*    NX_SUCCESS                            Successful conversion         */
5985 /*    NX_SOC_ERROR                          Error during conversion       */
5986 /*                                                                        */
5987 /*  CALLS                                                                 */
5988 /*                                                                        */
5989 /*    inet_aton                             Indicate char is a space      */
5990 /*                                                                        */
5991 /*  CALLED BY                                                             */
5992 /*                                                                        */
5993 /*    Application Code                                                    */
5994 /*                                                                        */
5995 /*  RELEASE HISTORY                                                       */
5996 /*                                                                        */
5997 /*    DATE              NAME                      DESCRIPTION             */
5998 /*                                                                        */
5999 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6000 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6001 /*                                            resulting in version 6.1    */
6002 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
6003 /*                                            used new API/structs naming,*/
6004 /*                                            resulting in version 6.3.0  */
6005 /*                                                                        */
6006 /**************************************************************************/
nx_bsd_inet_addr(const CHAR * buffer)6007 nx_bsd_in_addr_t nx_bsd_inet_addr(const CHAR *buffer)
6008 {
6009 
6010 struct  nx_bsd_in_addr ip_address;
6011 UINT    status;
6012 
6013     status = (UINT)nx_bsd_inet_aton(buffer, &ip_address);
6014 
6015     if (status == 0)
6016     {
6017         return (0xFFFFFFFF);
6018     }
6019 
6020     return(ip_address.s_addr);
6021 }
6022 
6023 
6024 /**************************************************************************/
6025 /*                                                                        */
6026 /*  FUNCTION                                               RELEASE        */
6027 /*                                                                        */
6028 /*    getsockopt                                          PORTABLE C      */
6029 /*                                                           6.3.0        */
6030 /*  AUTHOR                                                                */
6031 /*                                                                        */
6032 /*    Yuxin Zhou, Microsoft Corporation                                   */
6033 /*                                                                        */
6034 /*  DESCRIPTION                                                           */
6035 /*                                                                        */
6036 /*    This function returns the status of the specified socket option in  */
6037 /*    the current BSD socket session.                                     */
6038 /*                                                                        */
6039 /*  INPUT                                                                 */
6040 /*                                                                        */
6041 /*    sockID                                socket descriptor             */
6042 /*    option_level                          Category of option (SOCKET)   */
6043 /*    option_name                           Socket option ID              */
6044 /*    option_value                          Pointer to option value       */
6045 /*    option_value                          Pointer to size of value      */
6046 /*                                                                        */
6047 /*  OUTPUT                                                                */
6048 /*                                                                        */
6049 /*    tx_mutex_get                          Get protection                */
6050 /*    tx_mutex_put                          Release protection            */
6051 /*                                                                        */
6052 /*  CALLS                                                                 */
6053 /*                                                                        */
6054 /*    NX_SOC_OK                             Request processed successfully*/
6055 /*    NX_SOC_ERROR                          Errors with request           */
6056 /*    (option data)                         Pointer to requested data     */
6057 /*                                                                        */
6058 /*  CALLED BY                                                             */
6059 /*                                                                        */
6060 /*    Application Code                                                    */
6061 /*                                                                        */
6062 /*  RELEASE HISTORY                                                       */
6063 /*                                                                        */
6064 /*    DATE              NAME                      DESCRIPTION             */
6065 /*                                                                        */
6066 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6067 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6068 /*                                            resulting in version 6.1    */
6069 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
6070 /*                                            used new API/structs naming,*/
6071 /*                                            resulting in version 6.3.0  */
6072 /*                                                                        */
6073 /**************************************************************************/
nx_bsd_getsockopt(INT sockID,INT option_level,INT option_name,VOID * option_value,INT * option_length)6074 INT  nx_bsd_getsockopt(INT sockID, INT option_level, INT option_name, VOID *option_value, INT *option_length)
6075 {
6076 
6077 TX_INTERRUPT_SAVE_AREA
6078 
6079 INT                                     status;
6080 NX_BSD_SOCKET                           *bsd_socket_ptr;
6081 struct          nx_bsd_sock_errno       *so_errno;
6082 struct          nx_bsd_sock_keepalive   *so_keepalive;
6083 struct          nx_bsd_sock_reuseaddr   *so_reuseaddr;
6084 struct          nx_bsd_timeval          *so_rcvtimeval;
6085 struct          nx_bsd_sock_winsize     *soc_window_size;
6086 ULONG                                   ticks;
6087 
6088 
6089     /* Check for valid socket ID/descriptor. */
6090     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
6091     {
6092 
6093         /* Set the socket error if extended options enabled. */
6094         nx_bsd_set_errno(EBADF);
6095 
6096         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6097         return(NX_SOC_ERROR);
6098     }
6099 
6100     /* Check for invalid input. */
6101     if((option_value == NX_NULL) || (option_length == NX_NULL))
6102     {
6103 
6104         /* Set the socket error if extended socket options enabled. */
6105         nx_bsd_set_errno(EINVAL);
6106 
6107         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6108         return NX_SOC_ERROR;
6109     }
6110 
6111     if (option_level == IPPROTO_IP)
6112     {
6113 
6114         if((option_name <= SO_MAX) ||  (option_name > IP_OPTION_MAX))
6115         {
6116 
6117             /* Error, one or more invalid arguments.  */
6118 
6119             /* Set the socket error if extended socket options enabled. */
6120             nx_bsd_set_errno(ENOPROTOOPT);
6121 
6122             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6123             return NX_SOC_ERROR;
6124         }
6125     }
6126     else if(option_level == SOL_SOCKET)
6127     {
6128 
6129         if((option_name > SO_MAX) || (option_name < SO_MIN))
6130         {
6131 
6132             /* Error, one or more invalid arguments.  */
6133 
6134             /* Set the socket error if extended socket options enabled. */
6135             nx_bsd_set_errno(ENOPROTOOPT);
6136 
6137             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6138             return NX_SOC_ERROR;
6139         }
6140     }
6141     else
6142     {
6143 
6144         /* Error, one or more invalid arguments.  */
6145 
6146         /* Set the socket error if extended socket options enabled. */
6147         nx_bsd_set_errno(EINVAL);
6148 
6149         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6150         return NX_SOC_ERROR;
6151     }
6152 
6153     /* Normalize the socket ID.  */
6154     sockID =  sockID - NX_BSD_SOCKFD_START;
6155 
6156     /* Get the protection mutex.  */
6157     status =  (INT)tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
6158 
6159     /* Check the status.  */
6160     if (status)
6161     {
6162 
6163         /* Set the socket error if extended socket options enabled. */
6164         nx_bsd_set_errno(EACCES);
6165 
6166         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
6167         return(NX_SOC_ERROR);
6168     }
6169 
6170     /* Setup pointer to socket.  */
6171     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
6172 
6173     status = NX_SOC_OK;
6174     switch (option_name)
6175     {
6176 
6177         case SO_ERROR:
6178         {
6179 
6180            /* If a valid option pointer was supplied, verify it points to a valid data size. */
6181            if (*option_length < (INT)sizeof(so_errno -> error))
6182            {
6183 
6184                tx_mutex_put(nx_bsd_protection_ptr);
6185 
6186                /* Set the socket error if extended socket options enabled. */
6187                nx_bsd_set_errno(EINVAL);
6188 
6189                NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6190                return(NX_SOC_ERROR);
6191            }
6192 
6193            so_errno = (struct nx_bsd_sock_errno *)option_value;
6194 
6195            TX_DISABLE
6196            if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
6197            {
6198                so_errno -> error = bsd_socket_ptr -> nx_bsd_socket_error_code;
6199 
6200                /* Now clear the error code. */
6201                bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
6202 
6203                /* Clear the error flag.  The application is expected to close the socket at this point.*/
6204                bsd_socket_ptr -> nx_bsd_socket_status_flags = bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
6205            }
6206            else
6207                so_errno -> error = 0;
6208            TX_RESTORE
6209 
6210            /* Set the actual size of the data returned. */
6211            *option_length = sizeof(struct nx_bsd_sock_errno);
6212 
6213         }
6214 
6215         break;
6216 
6217         case SO_KEEPALIVE:
6218 
6219             /* Determine if NetX Duo supports keepalive. */
6220 
6221             /* Check to make sure the size arguement is sufficient if supplied. */
6222             if (*option_length < (INT)sizeof(so_keepalive -> keepalive_enabled))
6223             {
6224 
6225                 tx_mutex_put(nx_bsd_protection_ptr);
6226 
6227                 /* Set the socket error if extended socket options enabled. */
6228                 nx_bsd_set_errno(EINVAL);
6229 
6230                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6231                 return(NX_SOC_ERROR);
6232             }
6233 
6234             so_keepalive = (struct nx_bsd_sock_keepalive *)option_value;
6235 #ifndef NX_ENABLE_TCP_KEEPALIVE
6236             so_keepalive -> keepalive_enabled = NX_FALSE;
6237 #else
6238             so_keepalive -> keepalive_enabled = (INT)(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled);
6239 #endif /* NX_ENABLE_TCP_KEEPALIVE */
6240             *option_length = sizeof(struct nx_bsd_sock_keepalive);
6241 
6242         break;
6243 
6244         case SO_RCVTIMEO:
6245 
6246             /* Check if the receive time out is set. */
6247             if (bsd_socket_ptr -> nx_bsd_option_receive_timeout == 0)
6248             {
6249                 tx_mutex_put(nx_bsd_protection_ptr);
6250 
6251                 /* Set the socket error if extended socket options enabled. */
6252                 nx_bsd_set_errno(EINVAL);
6253 
6254                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6255                 return(NX_SOC_ERROR);
6256 
6257             }
6258 
6259             so_rcvtimeval = (struct nx_bsd_timeval *)option_value;
6260 
6261             ticks = bsd_socket_ptr -> nx_bsd_option_receive_timeout;
6262 
6263 
6264             so_rcvtimeval -> tv_usec = (nx_bsd_suseconds_t)(ticks * NX_MICROSECOND_PER_CPU_TICK) % 1000000;
6265             so_rcvtimeval -> tv_sec = (nx_bsd_time_t)((ticks * NX_MICROSECOND_PER_CPU_TICK) / 1000000);
6266             *option_length = sizeof(so_rcvtimeval);
6267 
6268         break;
6269 
6270         case SO_RCVBUF:
6271 
6272             soc_window_size = (struct nx_bsd_sock_winsize *)option_value;
6273             soc_window_size -> winsize = (INT)(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_default);
6274             *option_length = sizeof(soc_window_size);
6275 
6276         break;
6277 
6278         case SO_REUSEADDR:
6279 
6280             /* Check to make sure the size arguement is sufficient if supplied. */
6281             if (*option_length < (INT)sizeof(so_reuseaddr -> reuseaddr_enabled))
6282             {
6283 
6284                 tx_mutex_put(nx_bsd_protection_ptr);
6285 
6286                 /* Set the socket error if extended socket options enabled. */
6287                 nx_bsd_set_errno(EINVAL);
6288 
6289                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6290                 return(NX_SOC_ERROR);
6291             }
6292 
6293             so_reuseaddr= (struct nx_bsd_sock_reuseaddr *)option_value;
6294             so_reuseaddr -> reuseaddr_enabled = bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR;
6295             *option_length = sizeof(struct nx_bsd_sock_reuseaddr);
6296 
6297         break;
6298 
6299         case IP_MULTICAST_TTL:
6300 
6301             /* Validate the option length. */
6302             if(*option_length != sizeof(UCHAR))
6303             {
6304 
6305                 tx_mutex_put(nx_bsd_protection_ptr);
6306 
6307                 /* Set the socket error if extended socket options enabled. */
6308                 nx_bsd_set_errno(EINVAL);
6309 
6310                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6311                 return NX_SOC_ERROR;
6312             }
6313 
6314             /* Verify that the socket is still valid. */
6315             if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
6316             {
6317 
6318                 tx_mutex_put(nx_bsd_protection_ptr);
6319 
6320                 /* Set the socket error if extended socket options enabled. */
6321                 nx_bsd_set_errno(EBADF);
6322 
6323                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6324                 return NX_SOC_ERROR;
6325             }
6326 
6327             /* Make sure socket is UDP type. */
6328             if(bsd_socket_ptr -> nx_bsd_socket_udp_socket == NX_NULL)
6329             {
6330 
6331                 tx_mutex_put(nx_bsd_protection_ptr);
6332 
6333                 /* Set the socket error if extended socket options enabled. */
6334                 nx_bsd_set_errno(ENOPROTOOPT);
6335 
6336                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6337                 return NX_SOC_ERROR;
6338             }
6339 
6340             /* Set the TTL value. */
6341             *(UCHAR*)option_value = (UCHAR)(bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_time_to_live);
6342             break;
6343 
6344         default:
6345 
6346             tx_mutex_put(nx_bsd_protection_ptr);
6347 
6348             /* Set the socket error if extended socket options enabled. */
6349             nx_bsd_set_errno(ENOPROTOOPT);
6350 
6351             /* Unsupported or unknown option. */
6352             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6353             return(NX_SOC_ERROR);
6354     }
6355 
6356     /* Release the protection mutex.  */
6357     tx_mutex_put(nx_bsd_protection_ptr);
6358 
6359     return status;
6360 }
6361 
6362 /**************************************************************************/
6363 /*                                                                        */
6364 /*  FUNCTION                                               RELEASE        */
6365 /*                                                                        */
6366 /*    setsockopt                                          PORTABLE C      */
6367 /*                                                           6.3.0        */
6368 /*  AUTHOR                                                                */
6369 /*                                                                        */
6370 /*    Yuxin Zhou, Microsoft Corporation                                   */
6371 /*                                                                        */
6372 /*  DESCRIPTION                                                           */
6373 /*                                                                        */
6374 /*    This function enables the specified socket option in the current BSD*/
6375 /*    socket session to the specified setting.                            */
6376 /*                                                                        */
6377 /*  INPUT                                                                 */
6378 /*                                                                        */
6379 /*    sockID                                socket descriptor             */
6380 /*    option_level                          Category of option (SOCKET)   */
6381 /*    option_name                           Socket option ID              */
6382 /*    option_value                          Pointer to option value       */
6383 /*    option_length                         Size of option value data     */
6384 /*                                                                        */
6385 /*  OUTPUT                                                                */
6386 /*                                                                        */
6387 /*    NX_SOC_OK                             Request processed successfully*/
6388 /*    NX_SOC_ERROR                          Errors with request           */
6389 /*                                                                        */
6390 /*  CALLS                                                                 */
6391 /*                                                                        */
6392 /*    tx_mutex_get                          Get protection                */
6393 /*    tx_mutex_put                          Release protection            */
6394 /*                                                                        */
6395 /*  CALLED BY                                                             */
6396 /*                                                                        */
6397 /*    Application Code                                                    */
6398 /*                                                                        */
6399 /*  RELEASE HISTORY                                                       */
6400 /*                                                                        */
6401 /*    DATE              NAME                      DESCRIPTION             */
6402 /*                                                                        */
6403 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6404 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6405 /*                                            resulting in version 6.1    */
6406 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
6407 /*                                            used new API/structs naming,*/
6408 /*                                            resulting in version 6.3.0  */
6409 /*                                                                        */
6410 /**************************************************************************/
nx_bsd_setsockopt(INT sockID,INT option_level,INT option_name,const VOID * option_value,INT option_length)6411 INT  nx_bsd_setsockopt(INT sockID, INT option_level, INT option_name, const VOID *option_value, INT option_length)
6412 {
6413 UINT                    reuse_enabled;
6414 NX_BSD_SOCKET           *bsd_socket_ptr;
6415 ULONG                   window_size;
6416 ULONG                   timer_ticks;
6417 struct nx_bsd_timeval   *time_val;
6418 #if defined(NX_ENABLE_IP_RAW_PACKET_FILTER) || !defined(NX_DISABLE_IPV4)
6419 INT             i;
6420 #endif /* defined(NX_ENABLE_IP_RAW_PACKET_FILTER) || !defined(NX_DISABLE_IPV4) */
6421 #ifndef NX_DISABLE_IPV4
6422 struct nx_bsd_ip_mreq
6423                *mreq;
6424 UINT            mcast_interface;
6425 UINT            status;
6426 #endif /* NX_DISABLE_IPV4 */
6427 
6428 
6429     /* Check for valid socket ID. */
6430     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
6431     {
6432 
6433         /* Error, invalid socket ID.  */
6434 
6435         /* Set the socket error if extended options enabled. */
6436         nx_bsd_set_errno(EBADF);
6437 
6438         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6439         return(NX_SOC_ERROR);
6440     }
6441 
6442     /* Check for invalid paremters. */
6443     if((option_value == NX_NULL) || (option_length == 0))
6444     {
6445 
6446         /* Error, one or more invalid arguments.  */
6447 
6448         /* Set the socket error if extended socket options enabled. */
6449         nx_bsd_set_errno(EINVAL);
6450 
6451         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6452         return NX_SOC_ERROR;
6453     }
6454 
6455     if (option_level == IPPROTO_IP)
6456     {
6457 
6458         if((option_name <= SO_MAX) ||  (option_name > IP_OPTION_MAX))
6459         {
6460 
6461             /* Error, one or more invalid arguments.  */
6462 
6463             /* Set the socket error if extended socket options enabled. */
6464             nx_bsd_set_errno(ENOPROTOOPT);
6465 
6466             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6467             return NX_SOC_ERROR;
6468         }
6469     }
6470     else if(option_level == SOL_SOCKET)
6471     {
6472 
6473         if((option_name > SO_MAX) ||
6474            (option_name < SO_MIN))
6475         {
6476             /* Error, one or more invalid arguments.  */
6477 
6478             /* Set the socket error if extended socket options enabled. */
6479             nx_bsd_set_errno(ENOPROTOOPT);
6480 
6481             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6482             return NX_SOC_ERROR;
6483         }
6484     }
6485     else if (option_level == IPPROTO_TCP)
6486     {
6487 
6488         if ((option_name > TCP_NOOPT) ||
6489             (option_name < TCP_NODELAY))
6490         {
6491             /* Error, one or more invalid arguments.  */
6492 
6493             /* Set the socket error if extended socket options enabled. */
6494             nx_bsd_set_errno(ENOPROTOOPT);
6495 
6496             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6497             return NX_SOC_ERROR;
6498         }
6499     }
6500     else
6501     {
6502         /* Error, one or more invalid arguments.  */
6503 
6504         /* Set the socket error if extended socket options enabled. */
6505         nx_bsd_set_errno(EINVAL);
6506 
6507         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6508         return NX_SOC_ERROR;
6509     }
6510     /* Normalize the socket ID.  */
6511     sockID =  sockID - NX_BSD_SOCKFD_START;
6512 
6513     /* Set up pointer to the BSD socket.  */
6514     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
6515 
6516     /* Set the socket option status. */
6517     switch (option_name)
6518     {
6519 
6520         case SO_BROADCAST:
6521 
6522             /* This is the default behavior of NetX. All sockets have this capability. */
6523         break;
6524 
6525         case SO_KEEPALIVE:
6526 
6527             /* Only available to TCP BSD sockets. */
6528             if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
6529             {
6530 
6531                 /* Verify TCP keep alive is built into the NetX library or return an error. */
6532 #ifndef NX_ENABLE_TCP_KEEPALIVE
6533 
6534                 /* Set the socket error if extended socket options enabled. */
6535                 nx_bsd_set_errno(ENOPROTOOPT);
6536 
6537                 /* Return an error status. */
6538                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6539                 return NX_SOC_ERROR;
6540 #else
6541                 /* Determine if NetX Duo supports keepalive. */
6542 
6543                 /* Update the BSD socket with this attribute. */
6544                 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled =
6545                                         (UINT)(((struct nx_bsd_sock_keepalive *)option_value) -> keepalive_enabled);
6546 
6547                 if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled == NX_TRUE)
6548                 {
6549 
6550                     /* Set the keep alive timeout for this socket with the NetX configurable keep alive timeout. */
6551                     bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_timeout =  NX_TCP_KEEPALIVE_INITIAL;
6552                 }
6553                 else
6554                 {
6555 
6556                     /* Clear the socket keep alive timeout. */
6557                     bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_timeout =  0;
6558                 }
6559 #endif /* NX_ENABLE_TCP_KEEPALIVE */
6560             }
6561             else
6562             {
6563                 /* Not a TCP socket. */
6564 
6565                 /* Set the socket error if extended socket options enabled. */
6566                 nx_bsd_set_errno(ENOPROTOOPT);
6567 
6568                 /* Return an error status. */
6569                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6570                 return NX_SOC_ERROR;
6571             }
6572 
6573         break;
6574 
6575         case SO_LINGER:
6576 
6577             /* The Linger socket option is not supported in NetX Duo BSD. */
6578 
6579             return NX_NOT_ENABLED;
6580 
6581         case SO_SNDTIMEO:
6582 
6583             time_val =  (struct nx_bsd_timeval *)option_value;
6584 
6585             /* Calculate ticks for the ThreadX Timer.  */
6586             timer_ticks = (ULONG)(time_val -> tv_usec)/NX_MICROSECOND_PER_CPU_TICK  + (ULONG)(time_val -> tv_sec) * NX_IP_PERIODIC_RATE;
6587 
6588             bsd_socket_ptr -> nx_bsd_option_send_timeout = timer_ticks;
6589 
6590         break;
6591 
6592         case SO_RCVTIMEO:
6593 
6594             time_val =  (struct nx_bsd_timeval *)option_value;
6595 
6596             /* Calculate ticks for the ThreadX Timer.  */
6597             timer_ticks = (ULONG)(time_val -> tv_usec)/NX_MICROSECOND_PER_CPU_TICK  + (ULONG)(time_val -> tv_sec) * NX_IP_PERIODIC_RATE;
6598 
6599             bsd_socket_ptr -> nx_bsd_option_receive_timeout = timer_ticks;
6600 
6601         break;
6602 
6603         case SO_RCVBUF:
6604 
6605             /* Only available to TCP sockets. */
6606             if (!bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
6607             {
6608 
6609                 /* Set the socket error if extended socket options enabled. */
6610                 nx_bsd_set_errno(ENOPROTOOPT);
6611 
6612                 /* Return an error status. */
6613                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6614                 return NX_SOC_ERROR;
6615             }
6616 
6617 
6618             window_size = (ULONG)(((struct nx_bsd_sock_winsize *)option_value) -> winsize);
6619 
6620 #ifdef NX_ENABLE_TCP_WINDOW_SCALING
6621 
6622 
6623             /* If Window scaling feature is enabled, record this user-specified window size. */
6624             bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_maximum = window_size;
6625 #else
6626             /* Otherwise the windows size limit is applied. */
6627             if(window_size > 65535)
6628                 window_size = 65535;
6629 
6630 #endif /* NX_ENABLE_TCP_WINDOW_SCALING */
6631 
6632             /* Setup the sliding window information.  */
6633             bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_default =   window_size;
6634             bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_current =   window_size;
6635 
6636         break;
6637 
6638         case SO_REUSEADDR:
6639 
6640             reuse_enabled = (UINT)(((struct nx_bsd_sock_reuseaddr *)option_value) -> reuseaddr_enabled);
6641 
6642             if(reuse_enabled)
6643                 bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR;
6644             else
6645                 bsd_socket_ptr -> nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR);
6646 
6647         break;
6648 
6649 
6650         case TCP_NODELAY:
6651 
6652             /* This is the default behavior of NetX. All sockets have this attribute. */
6653 
6654         break;
6655 
6656         case IP_MULTICAST_TTL:
6657 
6658             /* Validate the option length. */
6659             if(option_length != sizeof(UCHAR) && option_length != sizeof(INT))
6660             {
6661 
6662                 /* Set the socket error if extended socket options enabled. */
6663                 nx_bsd_set_errno(EINVAL);
6664 
6665                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6666                 return NX_SOC_ERROR;
6667             }
6668 
6669             /* Verify that the socket is still valid. */
6670             if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
6671             {
6672 
6673                 /* Set the socket error if extended socket options enabled. */
6674                 nx_bsd_set_errno(EBADF);
6675 
6676                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6677                 return NX_SOC_ERROR;
6678             }
6679 
6680             /* Make sure socket is UDP type. */
6681             if(bsd_socket_ptr -> nx_bsd_socket_udp_socket == NX_NULL)
6682             {
6683                 /* Set the socket error if extended socket options enabled. */
6684                 nx_bsd_set_errno(ENOPROTOOPT);
6685 
6686                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6687                 return NX_SOC_ERROR;
6688             }
6689 
6690             /* Set the TTL value. */
6691             if (option_length == sizeof(UCHAR))
6692             {
6693                 bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_time_to_live = *(UCHAR*)option_value;
6694             }
6695             else
6696             {
6697                 bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_time_to_live = (UCHAR)(*(INT*)option_value);
6698             }
6699         break;
6700 
6701         case IP_MULTICAST_LOOP:
6702 
6703             /* This is not supported yet. */
6704 
6705         break;
6706 
6707         case IP_MULTICAST_IF:
6708 
6709             /* This is not supported yet. */
6710 
6711         break;
6712 
6713 
6714         case IP_RAW_RX_NO_HEADER:
6715 
6716 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
6717             i = *(INT*)option_value;
6718 
6719             if((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET) &&
6720                ((bsd_socket_ptr -> nx_bsd_socket_family == AF_INET) || (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)))
6721             {
6722 
6723                 if(i)
6724                 {
6725 
6726                     bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_RX_NO_HDR;
6727                 }
6728                 else
6729                 {
6730 
6731                     bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_RX_NO_HDR);
6732                 }
6733             }
6734             else
6735 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
6736             {
6737 
6738                 nx_bsd_set_errno(EINVAL);
6739 
6740                 /* Return an error status. */
6741                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6742 
6743                 return NX_SOC_ERROR;
6744             }
6745 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
6746             break;
6747 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
6748 
6749         case IP_RAW_IPV6_HDRINCL:
6750 
6751 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
6752             i = *(INT*)option_value;
6753 
6754             /* Is this an IPv6 socket? */
6755             if((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET) &&
6756                (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6))
6757             {
6758 
6759                 /* Should the No Header feature be enabled (NX_TRUE)? */
6760                 if(i)
6761                 {
6762 
6763                     /* Yes, set the flag for no header. */
6764                     bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_TX_HDR_INCLUDE;
6765                 }
6766                 else
6767                 {
6768 
6769                     /* No, clear the flag for no header. */
6770                     bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_TX_HDR_INCLUDE);
6771                 }
6772             }
6773             else
6774 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
6775             {
6776 
6777                 nx_bsd_set_errno(EINVAL);
6778 
6779                 /* Return an error status. */
6780                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6781 
6782                 return NX_SOC_ERROR;
6783             }
6784 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
6785             break;
6786 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
6787 
6788 
6789 #ifndef NX_DISABLE_IPV4
6790         case IP_ADD_MEMBERSHIP:
6791         case IP_DROP_MEMBERSHIP:
6792 
6793             /* Validate the option length */
6794             if(option_length != sizeof(struct nx_bsd_ip_mreq))
6795             {
6796 
6797                 /* Set the socket error if extended socket options enabled. */
6798                 nx_bsd_set_errno(EINVAL);
6799 
6800                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6801                 return NX_SOC_ERROR;
6802             }
6803 
6804             mreq = (struct nx_bsd_ip_mreq*)option_value;
6805 
6806             /* Make sure the multicast group address is valid. */
6807             if((mreq -> imr_multiaddr.s_addr & ntohl(NX_IP_CLASS_D_TYPE)) != ntohl(NX_IP_CLASS_D_TYPE))
6808             {
6809                 /* Set the socket error if extended socket options enabled. */
6810                 nx_bsd_set_errno(EINVAL);
6811 
6812                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6813                 return NX_SOC_ERROR;
6814             }
6815 
6816             /* Verify that the socket is still valid. */
6817             if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
6818             {
6819                 /* Set the socket error if extended socket options enabled. */
6820                 nx_bsd_set_errno(EBADF);
6821 
6822                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6823                 return NX_SOC_ERROR;
6824             }
6825 
6826             /* Make sure socket is UDP type. */
6827             if(bsd_socket_ptr -> nx_bsd_socket_udp_socket == NX_NULL)
6828             {
6829                 /* Set the socket error if extended socket options enabled. */
6830                 nx_bsd_set_errno(ENOPROTOOPT);
6831 
6832                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6833                 return NX_SOC_ERROR;
6834             }
6835 
6836             /* Validate that the interface is one of the local IPv4 interfaces. */
6837             /* We allow imr_interface being zero to indicate the primary interface. */
6838             mcast_interface = NX_MAX_IP_INTERFACES;
6839 
6840             if(mreq -> imr_interface.s_addr == INADDR_ANY)
6841             {
6842                 mcast_interface = 0;
6843             }
6844             else
6845             {
6846 
6847                 /* Set the socket error if extended socket options enabled. */
6848                 UINT addr;
6849 
6850                 /* Convert the local interface value to host byte order. */
6851                 addr = ntohl(mreq -> imr_interface.s_addr);
6852 
6853                 /* Search through the interface table for a matching one. */
6854                 for(i = 0; i < NX_MAX_IP_INTERFACES; i++)
6855                 {
6856 
6857                     if(addr == nx_bsd_default_ip -> nx_ip_interface[i].nx_interface_ip_address)
6858                     {
6859 
6860                         mcast_interface = (UINT)i;
6861                         break;
6862                     }
6863                 }
6864             }
6865 
6866             if(mcast_interface == NX_MAX_IP_INTERFACES)
6867             {
6868 
6869                 /* Did not find a matching interface. */
6870                 nx_bsd_set_errno(EINVAL);
6871 
6872                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6873                 return NX_SOC_ERROR;
6874             }
6875 
6876             if(option_name == IP_ADD_MEMBERSHIP)
6877             {
6878 
6879                 /* Make sure the IGMP feature is enabled. */
6880                 if(nx_bsd_default_ip -> nx_ip_igmp_packet_receive == NX_NULL)
6881                 {
6882                     nx_igmp_enable(nx_bsd_default_ip);
6883                 }
6884 
6885                 /* Join the group. */
6886                 status = nx_igmp_multicast_interface_join(nx_bsd_default_ip, ntohl(mreq -> imr_multiaddr.s_addr), mcast_interface);
6887             }
6888             else
6889             {
6890 
6891                 /* Leave group */
6892                 status = nx_igmp_multicast_leave(nx_bsd_default_ip, ntohl(mreq -> imr_multiaddr.s_addr));
6893             }
6894 
6895             if(status != NX_SUCCESS)
6896             {
6897 
6898                 nx_bsd_set_errno(EINVAL);
6899 
6900                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6901                 return NX_SOC_ERROR;
6902             }
6903 
6904             break;
6905 #endif /* NX_DISABLE_IPV4 */
6906 
6907         case IP_HDRINCL:
6908 
6909 #if defined(NX_ENABLE_IP_RAW_PACKET_FILTER) && !defined(NX_DISABLE_IPV4)
6910             i = *(INT*)option_value;
6911             /* First verify that raw socket processing is enabled on the IP instance and that this is
6912                an IPv4 thread. */
6913             if((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET) &&
6914                (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET))
6915             {
6916 
6917                 /* Is the option being enabled (NX_TRUE)? */
6918                 if(i)
6919                 {
6920 
6921                     /* Yes, set the flag bit indicating BSD will append the IP header. */
6922                     bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_TX_HDR_INCLUDE;
6923                 }
6924                 else
6925                 {
6926 
6927                     /* No, clear the flag bit indicating IP task will append the IP header. */
6928                     bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_TX_HDR_INCLUDE);
6929                 }
6930             }
6931             else
6932 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
6933             {
6934 
6935                 nx_bsd_set_errno(EINVAL);
6936 
6937                 /* Return an error status. */
6938                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6939 
6940                 return NX_SOC_ERROR;
6941             }
6942 
6943 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
6944             break;
6945 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
6946 
6947         default:
6948 
6949             /* Set the socket error if extended socket options enabled. */
6950             nx_bsd_set_errno(EINVAL);
6951 
6952             /* Return an error status. */
6953             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6954             return NX_SOC_ERROR;
6955     }
6956 
6957     /* Socket option successfully updated. */
6958     return NX_SUCCESS;
6959 }
6960 
6961 
6962 /**************************************************************************/
6963 /*                                                                        */
6964 /*  FUNCTION                                               RELEASE        */
6965 /*                                                                        */
6966 /*    getsockname                                         PORTABLE C      */
6967 /*                                                           6.3.0        */
6968 /*  AUTHOR                                                                */
6969 /*                                                                        */
6970 /*    Yuxin Zhou, Microsoft Corporation                                   */
6971 /*                                                                        */
6972 /*  DESCRIPTION                                                           */
6973 /*                                                                        */
6974 /*    This function returns the socket's primary interface address and    */
6975 /*    port. For NetX Duo environments, it returns the address at address  */
6976 /*    index 1 into the IP address table; this is where the primary        */
6977 /*    interface global IP address is normally located.                    */
6978 /*                                                                        */
6979 /*  INPUT                                                                 */
6980 /*                                                                        */
6981 /*    sockID                                socket descriptor             */
6982 /*    localAddress                          sockaddr struct to return     */
6983 /*                                          the local address             */
6984 /*    addressLength                         Number of bytes in sockAddr   */
6985 /*                                                                        */
6986 /*  OUTPUT                                                                */
6987 /*                                                                        */
6988 /*    NX_SOC_OK (0)                         On success                    */
6989 /*    NX_SOC_ERROR (-1)                     On failure                    */
6990 /*                                                                        */
6991 /*  CALLS                                                                 */
6992 /*                                                                        */
6993 /*    tx_mutex_get                          Get protection                */
6994 /*    tx_mutex_put                          Release protection            */
6995 /*                                                                        */
6996 /*  CALLED BY                                                             */
6997 /*                                                                        */
6998 /*    Application Code                                                    */
6999 /*                                                                        */
7000 /*  RELEASE HISTORY                                                       */
7001 /*                                                                        */
7002 /*    DATE              NAME                      DESCRIPTION             */
7003 /*                                                                        */
7004 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7005 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
7006 /*                                            verified memcpy use cases,  */
7007 /*                                            resulting in version 6.1    */
7008 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
7009 /*                                            used new API/structs naming,*/
7010 /*                                            resulting in version 6.3.0  */
7011 /*                                                                        */
7012 /**************************************************************************/
nx_bsd_getsockname(INT sockID,struct nx_bsd_sockaddr * localAddress,INT * addressLength)7013 INT  nx_bsd_getsockname(INT sockID, struct nx_bsd_sockaddr *localAddress, INT *addressLength)
7014 {
7015 
7016 #ifndef NX_DISABLE_IPV4
7017 struct nx_bsd_sockaddr_in  soc_struct;
7018 #endif /* NX_DISABLE_IPV4 */
7019 #ifdef FEATURE_NX_IPV6
7020 struct nx_bsd_sockaddr_in6 soc6_struct;
7021 #endif
7022 UINT                status;
7023 NX_BSD_SOCKET       *bsd_socket_ptr;
7024 
7025 
7026     /* Check whether supplied socket ID is valid.  */
7027     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
7028     {
7029 
7030         /* Set the socket error if extended options enabled. */
7031         nx_bsd_set_errno(EBADF);
7032 
7033         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7034         return(NX_SOC_ERROR);
7035     }
7036 
7037     if((localAddress == NX_NULL) || (addressLength == NX_NULL) || (*addressLength == 0))
7038     {
7039 
7040         /* Set the socket error if extended socket options enabled. */
7041         nx_bsd_set_errno(EINVAL);
7042 
7043         /* Return error.  */
7044         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7045         return(NX_SOC_ERROR);
7046     }
7047 
7048     /* Normalize the socket ID.  */
7049     sockID =  sockID - NX_BSD_SOCKFD_START;
7050 
7051     /* Setup pointer to socket.  */
7052     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
7053 
7054     /* Get the protection mutex.  */
7055     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
7056 
7057     /* Check the status.  */
7058     if (status)
7059     {
7060 
7061         /* Set the socket error if extended socket options enabled. */
7062         nx_bsd_set_errno(EACCES);
7063 
7064         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
7065         return(NX_SOC_ERROR);
7066     }
7067 
7068     /* Is the socket still in use?  */
7069     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
7070     {
7071 
7072         /* Set the socket error if extended options enabled. */
7073         nx_bsd_set_errno(EBADF);
7074         /* Release the protection mutex.  */
7075         tx_mutex_put(nx_bsd_protection_ptr);
7076 
7077         /* Return error.  */
7078         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7079         return(NX_SOC_ERROR);
7080     }
7081 
7082     if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND))
7083     {
7084         /* This socket is not bound yet.  Just return.
7085            According to the spec, if the socket is not bound, the value stored in
7086            localAddress is unspecified. */
7087         /* Release the protection mutex.  */
7088         tx_mutex_put(nx_bsd_protection_ptr);
7089 
7090         /* Success!  */
7091         return(NX_SOC_OK);
7092     }
7093 
7094 #ifndef NX_DISABLE_IPV4
7095     if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
7096     {
7097         if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
7098         {
7099             soc_struct.sin_addr.s_addr = INADDR_ANY;
7100         }
7101         else if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == 0)
7102         {
7103 
7104             nx_bsd_set_errno(EINVAL);
7105 
7106             /* Release the protection mutex.  */
7107             tx_mutex_put(nx_bsd_protection_ptr);
7108 
7109             /* Return error.  */
7110             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7111             return(NX_SOC_ERROR);
7112         }
7113         else
7114         {
7115             NX_INTERFACE* local_if = (NX_INTERFACE*)(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface);
7116             soc_struct.sin_addr.s_addr = htonl(local_if -> nx_interface_ip_address);
7117         }
7118         soc_struct.sin_port = htons((USHORT)bsd_socket_ptr -> nx_bsd_socket_local_port);
7119 
7120         soc_struct.sin_family = AF_INET;
7121 
7122         if((*addressLength) > (INT)sizeof(struct nx_bsd_sockaddr_in))
7123         {
7124             *addressLength = sizeof(struct nx_bsd_sockaddr_in);
7125         }
7126         memcpy(localAddress, &soc_struct, (UINT)(*addressLength)); /* Use case of memcpy is verified. */
7127     }
7128     else
7129 #endif /* NX_DISABLE_IPV4 */
7130 #ifdef FEATURE_NX_IPV6
7131     if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
7132     {
7133 
7134 
7135         if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
7136         {
7137             soc6_struct.sin6_addr._S6_un._S6_u32[0] = 0;
7138             soc6_struct.sin6_addr._S6_un._S6_u32[1] = 0;
7139             soc6_struct.sin6_addr._S6_un._S6_u32[2] = 0;
7140             soc6_struct.sin6_addr._S6_un._S6_u32[3] = 0;
7141         }
7142         else if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == 0)
7143         {
7144 
7145             nx_bsd_set_errno(EINVAL);
7146 
7147             /* Release the protection mutex.  */
7148             tx_mutex_put(nx_bsd_protection_ptr);
7149 
7150             /* Return error.  */
7151             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7152             return(NX_SOC_ERROR);
7153         }
7154         else
7155         {
7156             NXD_IPV6_ADDRESS* local_v6if = (NXD_IPV6_ADDRESS*)(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface);
7157 
7158             soc6_struct.sin6_addr._S6_un._S6_u32[0] = htonl(local_v6if -> nxd_ipv6_address[0]);
7159             soc6_struct.sin6_addr._S6_un._S6_u32[1] = htonl(local_v6if -> nxd_ipv6_address[1]);
7160             soc6_struct.sin6_addr._S6_un._S6_u32[2] = htonl(local_v6if -> nxd_ipv6_address[2]);
7161             soc6_struct.sin6_addr._S6_un._S6_u32[3] = htonl(local_v6if -> nxd_ipv6_address[3]);
7162         }
7163 
7164         soc6_struct.sin6_port =  htons((USHORT)bsd_socket_ptr -> nx_bsd_socket_local_port);
7165 
7166         soc6_struct.sin6_family = AF_INET6;
7167 
7168         if((*addressLength) > (INT)sizeof(struct nx_bsd_sockaddr_in6))
7169         {
7170             *addressLength = sizeof(struct nx_bsd_sockaddr_in6);
7171         }
7172         memcpy(localAddress, &soc6_struct, (UINT)(*addressLength)); /* Use case of memcpy is verified. */
7173 
7174     }
7175     else
7176 #endif /* FEATURE_NX_IPV6 */
7177     {
7178 
7179         /* Release the protection mutex.  */
7180         tx_mutex_put(nx_bsd_protection_ptr);
7181 
7182         nx_bsd_set_errno(EPROTONOSUPPORT);
7183 
7184         /* Return error.  */
7185         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7186         return(NX_SOC_ERROR);
7187     }
7188 
7189 
7190 
7191     /* Release the protection mutex.  */
7192     tx_mutex_put(nx_bsd_protection_ptr);
7193 
7194     /* Success!  */
7195     return(NX_SOC_OK);
7196 }
7197 
7198 
7199 /**************************************************************************/
7200 /*                                                                        */
7201 /*  FUNCTION                                               RELEASE        */
7202 /*                                                                        */
7203 /*    getpeername                                         PORTABLE C      */
7204 /*                                                           6.3.0        */
7205 /*  AUTHOR                                                                */
7206 /*                                                                        */
7207 /*    Yuxin Zhou, Microsoft Corporation                                   */
7208 /*                                                                        */
7209 /*  DESCRIPTION                                                           */
7210 /*                                                                        */
7211 /*    This function returns the socket's remote address and port.         */
7212 /*                                                                        */
7213 /*  INPUT                                                                 */
7214 /*                                                                        */
7215 /*    sockID                                socket descriptor             */
7216 /*    localAddress                          sockaddr struct to return     */
7217 /*                                          the remote address            */
7218 /*    addressLength                         Number of bytes in sockAddr   */
7219 /*                                                                        */
7220 /*  OUTPUT                                                                */
7221 /*                                                                        */
7222 /*    NX_SOC_OK (0)                         On success                    */
7223 /*    NX_SOC_ERROR (-1)                     On failure                    */
7224 /*                                                                        */
7225 /*  CALLS                                                                 */
7226 /*                                                                        */
7227 /*    tx_mutex_get                          Get protection                */
7228 /*    tx_mutex_put                          Release protection            */
7229 /*                                                                        */
7230 /*  CALLED BY                                                             */
7231 /*                                                                        */
7232 /*    Application Code                                                    */
7233 /*                                                                        */
7234 /*  RELEASE HISTORY                                                       */
7235 /*                                                                        */
7236 /*    DATE              NAME                      DESCRIPTION             */
7237 /*                                                                        */
7238 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7239 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7240 /*                                            resulting in version 6.1    */
7241 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
7242 /*                                            used new API/structs naming,*/
7243 /*                                            resulting in version 6.3.0  */
7244 /*                                                                        */
7245 /**************************************************************************/
nx_bsd_getpeername(INT sockID,struct nx_bsd_sockaddr * remoteAddress,INT * addressLength)7246 INT  nx_bsd_getpeername(INT sockID, struct nx_bsd_sockaddr *remoteAddress, INT *addressLength)
7247 {
7248 
7249 UINT                status;
7250 NX_BSD_SOCKET       *bsd_socket_ptr;
7251 #ifndef NX_DISABLE_IPV4
7252 struct nx_bsd_sockaddr_in  *soc_struct_ptr = NX_NULL;
7253 #endif /* NX_DISABLE_IPV4 */
7254 #ifdef FEATURE_NX_IPV6
7255 struct nx_bsd_sockaddr_in6 *soc6_struct_ptr = NX_NULL;
7256 #endif
7257 
7258 
7259     /* Check whether supplied socket ID is valid.  */
7260     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
7261     {
7262 
7263         /* Set the socket error if extended socket options enabled. */
7264         nx_bsd_set_errno(EINVAL);
7265 
7266         /* Error, invalid socket ID.  */
7267         NX_BSD_ERROR(ERROR, __LINE__);
7268         return(ERROR);
7269     }
7270 
7271     /* Normalize the socket ID.  */
7272     sockID =  sockID - NX_BSD_SOCKFD_START;
7273 
7274     /* Check the remote address and length pointers.  */
7275     if((remoteAddress == NX_NULL) ||(addressLength == NX_NULL))
7276     {
7277 
7278         /* Set the socket error if extended socket options enabled. */
7279         nx_bsd_set_errno(EINVAL);
7280 
7281         /* Return error.  */
7282         NX_BSD_ERROR(ERROR, __LINE__);
7283         return(ERROR);
7284     }
7285 
7286 
7287     /* Get the protection mutex.  */
7288     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
7289 
7290     /* Check the status.  */
7291     if (status)
7292     {
7293 
7294         /* Set the socket error if extended socket options enabled. */
7295         nx_bsd_set_errno(EACCES);
7296 
7297         /* Error getting the protection mutex.  */
7298         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
7299         return(ERROR);
7300     }
7301 
7302     /* Setup pointer to socket.  */
7303     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
7304 
7305 #ifndef NX_DISABLE_IPV4
7306     if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
7307     {
7308 
7309         /* This is an IPv4 only socket. */
7310 
7311         /* Now validate the size of remoteAddress structure. */
7312         if(*addressLength < (INT)sizeof(struct nx_bsd_sockaddr_in))
7313         {
7314 
7315             /* User supplied buffer is too small .*/
7316 
7317             /* Release the protection mutex.  */
7318             tx_mutex_put(nx_bsd_protection_ptr);
7319 
7320             /* Set the socket error, if socket enabled with extended BSD features. */
7321             nx_bsd_set_errno(ESOCKTNOSUPPORT);
7322 
7323             /* Return error.  */
7324             NX_BSD_ERROR(ERROR, __LINE__);
7325             return(ERROR);
7326         }
7327 
7328         soc_struct_ptr = (struct nx_bsd_sockaddr_in*)remoteAddress;
7329         *addressLength = sizeof(struct nx_bsd_sockaddr_in);
7330     }
7331     else
7332 #endif /* NX_DISABLE_IPV4 */
7333 #ifdef FEATURE_NX_IPV6
7334     if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
7335     {
7336 
7337         /* IPv6 socket */
7338 
7339         /* Now validate the size of remoteAddress structure. */
7340         if(*addressLength < (INT)sizeof(struct nx_bsd_sockaddr_in6))
7341         {
7342 
7343             /* User supplied buffer is too small .*/
7344 
7345             /* Release the protection mutex.  */
7346             tx_mutex_put(nx_bsd_protection_ptr);
7347 
7348             /* Set the socket error, if socket enabled with extended BSD features. */
7349             nx_bsd_set_errno(ESOCKTNOSUPPORT);
7350 
7351             /* Return error.  */
7352             NX_BSD_ERROR(ERROR, __LINE__);
7353             return(ERROR);
7354         }
7355 
7356         soc6_struct_ptr = (struct nx_bsd_sockaddr_in6*)remoteAddress;
7357         *addressLength = sizeof(struct nx_bsd_sockaddr_in6);
7358     }
7359     else
7360 #endif /* FEATURE_NX_IPV6 */
7361     {
7362 
7363         /* Not a valid address family. */
7364         /* Release the protection mutex.  */
7365         tx_mutex_put(nx_bsd_protection_ptr);
7366 
7367         /* Set the socket error, if socket enabled with extended BSD features. */
7368         nx_bsd_set_errno(ESOCKTNOSUPPORT);
7369 
7370         /* Return error.  */
7371         NX_BSD_ERROR(ERROR, __LINE__);
7372         return(ERROR);
7373     }
7374 
7375     /* Is the socket still in use?  */
7376     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
7377     {
7378 
7379         /* Error, socket not in use anymore.  */
7380 
7381         /* Release the protection mutex.  */
7382         tx_mutex_put(nx_bsd_protection_ptr);
7383 
7384         /* Set the socket error if extended options enabled. */
7385         nx_bsd_set_errno(EBADF);
7386 
7387         /* Return error.  */
7388         NX_BSD_ERROR(ERROR, __LINE__);
7389         return(ERROR);
7390     }
7391 
7392     /* Check whether TCP or UDP */
7393     if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
7394     {
7395 
7396 #ifndef NX_DISABLE_IPV4
7397         /* TCP Socket.  Determine socket family type. */
7398         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
7399         {
7400 
7401             soc_struct_ptr -> sin_family      =  AF_INET;
7402             soc_struct_ptr -> sin_port        =  htons((USHORT)bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_port);
7403             soc_struct_ptr -> sin_addr.s_addr =  htonl(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v4);
7404         }
7405         else
7406 #endif /* NX_DISABLE_IPV4 */
7407 #ifdef FEATURE_NX_IPV6
7408         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
7409         {
7410 
7411             soc6_struct_ptr -> sin6_family    =  AF_INET6;
7412             soc6_struct_ptr -> sin6_port      =  htons((USHORT)bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_port);
7413             soc6_struct_ptr -> sin6_addr._S6_un._S6_u32[0] = htonl(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[0]);
7414             soc6_struct_ptr -> sin6_addr._S6_un._S6_u32[1] = htonl(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[1]);
7415             soc6_struct_ptr -> sin6_addr._S6_un._S6_u32[2] = htonl(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[2]);
7416             soc6_struct_ptr -> sin6_addr._S6_un._S6_u32[3] = htonl(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[3]);
7417         }
7418         else
7419 #endif  /* FEATURE_NX_IPV6 */
7420         {
7421 
7422             /* Release the protection mutex.  */
7423             tx_mutex_put(nx_bsd_protection_ptr);
7424 
7425             /* Set the socket error if extended options enabled. */
7426             nx_bsd_set_errno(EBADF);
7427 
7428             /* Return error.  */
7429             NX_BSD_ERROR(ERROR, __LINE__);
7430             return(ERROR);
7431 
7432         }
7433     }
7434     else if (bsd_socket_ptr -> nx_bsd_socket_udp_socket)
7435     {
7436 
7437 #ifndef NX_DISABLE_IPV4
7438         /* UDP Socket.  Get Peer Name doesn't apply to UDP sockets.  Only fill in AF family information.*/
7439         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
7440         {
7441             soc_struct_ptr -> sin_family      =  AF_INET;
7442             soc_struct_ptr -> sin_port        =  0;
7443             soc_struct_ptr -> sin_addr.s_addr =  0;
7444         }
7445         else
7446 #endif /* NX_DISABLE_IPV4 */
7447 #ifdef FEATURE_NX_IPV6
7448         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
7449         {
7450             soc6_struct_ptr -> sin6_family    =  AF_INET6;
7451             soc6_struct_ptr -> sin6_port      =  0;
7452         }
7453         else
7454 #endif /* FEATURE_NX_IPV6 */
7455         {
7456 
7457             /* Release the protection mutex.  */
7458             tx_mutex_put(nx_bsd_protection_ptr);
7459 
7460             /* Set the socket error, if socket enabled with extended BSD features. */
7461             nx_bsd_set_errno(ESOCKTNOSUPPORT);
7462 
7463             /* Return error.  */
7464             NX_BSD_ERROR(ERROR, __LINE__);
7465             return(ERROR);
7466 
7467         }
7468     }
7469     else
7470     {
7471 
7472         /* Release the protection mutex.  */
7473         tx_mutex_put(nx_bsd_protection_ptr);
7474 
7475         /* Set the socket error, if socket enabled with extended BSD features. */
7476         nx_bsd_set_errno(ESOCKTNOSUPPORT);
7477 
7478         /* Return error.  */
7479         NX_BSD_ERROR(ERROR, __LINE__);
7480         return(ERROR);
7481     }
7482 
7483 
7484     /* Release the protection mutex.  */
7485     tx_mutex_put(nx_bsd_protection_ptr);
7486 
7487     /* Success!  */
7488     return(NX_SOC_OK);
7489 }
7490 
7491 /**************************************************************************/
7492 /*                                                                        */
7493 /*  FUNCTION                                               RELEASE        */
7494 /*                                                                        */
7495 /*    select                                              PORTABLE C      */
7496 /*                                                           6.3.0        */
7497 /*  AUTHOR                                                                */
7498 /*                                                                        */
7499 /*    Yuxin Zhou, Microsoft Corporation                                   */
7500 /*                                                                        */
7501 /*  DESCRIPTION                                                           */
7502 /*                                                                        */
7503 /*    This function allows for sockets to be checked for incoming packets.*/
7504 /*    nfds should be one greater than value of the largest valued socket  */
7505 /*    descriptor in any of the lists. If you don't wish to calculate this,*/
7506 /*    use FD_SETSIZE instead.For small numbers of sockets,select() will be*/
7507 /*    less efficient if FD_SETSIZE is passed.If the bit corresponding to  */
7508 /*    a socket in an fd_set is set,that socket will be checked for the    */
7509 /*    condition the fd_set corresponds to.If the condition they are       */
7510 /*    checked for is true, they will still be set to true when select()   */
7511 /*    returns (otherwise they will be set to false).                      */
7512 /*    Note that the sets are modified by select():thus they must be reset */
7513 /*    between each call to the function.                                  */
7514 /*                                                                        */
7515 /*    fd_sets can be manipulated using the following macros or functions: */
7516 /*                                                                        */
7517 /*    FD_SET(fd, fdset)  Sets socket fd in fdset to true.                 */
7518 /*    FD_CLR(fd, fdset)  Sets socket fd in fdset to false.                */
7519 /*    FD_ISSET(fd, fdset)Returns true if socket fd is set to true in fdset*/
7520 /*    FD_ZERO(fdset)  Sets all the sockets in fdset to false.             */
7521 /*                                                                        */
7522 /*    If the input timeout is NULL, select() blocks until one of the      */
7523 /*    sockets receives a packet. If the timeout is non-NULL, select waits */
7524 /*    for the specified time and returns regardless if any socket has     */
7525 /*    received a packet.  Otherwise as soon as a socket receives a packet */
7526 /*    this function will return immediately.                              */
7527 /*                                                                        */
7528 /*    To use select() in non-blocking mode call it with a non-null timeout*/
7529 /*    input but set tv_sec and tv_usec to zero, in Unix fashion.          */
7530 /*                                                                        */
7531 /*    select() returns the number of sockets for which the specified      */
7532 /*    conditions are true. If it encounters an error, it will return -1.  */
7533 /*                                                                        */
7534 /*    NOTE:  ****** When select returns NX_SOC_ERROR it won't update      */
7535 /*           the readfds descriptor.                                      */
7536 /*                                                                        */
7537 /*  INPUT                                                                 */
7538 /*                                                                        */
7539 /*    nfds                                 Maximum socket descriptor #    */
7540 /*    fd_set *readFDs                      List of read ready sockets     */
7541 /*    fd_set *writeFDs                     List of write ready sockets    */
7542 /*    fd_set *exceptFDs                    List of exceptions             */
7543 /*    struct timeval *timeOut                                             */
7544 /*                                                                        */
7545 /*  OUTPUT                                                                */
7546 /*                                                                        */
7547 /*    NX_SUCCESS                            No descriptors read           */
7548 /*                                             (successful completion)    */
7549 /*    status                                Number of descriptors read    */
7550 /*                                             (< 0 if error occurred)    */
7551 /*                                                                        */
7552 /*  CALLS                                                                 */
7553 /*                                                                        */
7554 /*    FD_ZERO                               Clear a socket ready list     */
7555 /*    FD_ISSET                              Check a socket is ready       */
7556 /*    FD_SET                                Set a socket to check         */
7557 /*    nx_tcp_socket_receive                 Receive TCP packet            */
7558 /*    nx_udp_source_extract                 Extract source IP and port    */
7559 /*    tx_event_flags_get                    Get events                    */
7560 /*    tx_mutex_get                          Get protection                */
7561 /*    tx_mutex_put                          Release protection            */
7562 /*    tx_thread_identify                    Get current thread pointer    */
7563 /*    tx_thread_preemption_change           Disable/restore preemption    */
7564 /*                                                                        */
7565 /*  CALLED BY                                                             */
7566 /*                                                                        */
7567 /*    Application Code                                                    */
7568 /*                                                                        */
7569 /*  RELEASE HISTORY                                                       */
7570 /*                                                                        */
7571 /*    DATE              NAME                      DESCRIPTION             */
7572 /*                                                                        */
7573 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7574 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7575 /*                                            resulting in version 6.1    */
7576 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
7577 /*                                            used new API/structs naming,*/
7578 /*                                            resulting in version 6.3.0  */
7579 /*                                                                        */
7580 /**************************************************************************/
nx_bsd_select(INT nfds,nx_bsd_fd_set * readfds,nx_bsd_fd_set * writefds,nx_bsd_fd_set * exceptfds,struct nx_bsd_timeval * timeout)7581 INT  nx_bsd_select(INT nfds, nx_bsd_fd_set *readfds, nx_bsd_fd_set *writefds, nx_bsd_fd_set *exceptfds, struct nx_bsd_timeval *timeout)
7582 {
7583 
7584 INT                     i;
7585 UINT                    status;
7586 NX_BSD_SOCKET_SUSPEND   suspend_request;
7587 NX_PACKET               *packet_ptr;
7588 nx_bsd_fd_set           readfds_found;
7589 nx_bsd_fd_set           writefds_found;
7590 nx_bsd_fd_set           exceptfds_found;
7591 INT                     readfds_left;
7592 INT                     writefds_left;
7593 INT                     exceptfds_left;
7594 ULONG                   ticks;
7595 UINT                    original_threshold;
7596 TX_THREAD               *current_thread_ptr;
7597 INT                     ret;
7598 
7599 
7600     /* Check for valid input parameters.  */
7601     if ((readfds == NX_NULL) && (writefds == NX_NULL) && (exceptfds == NX_NULL) && (timeout == NX_NULL))
7602     {
7603 
7604         /* Set the socket error if extended socket options enabled. */
7605         nx_bsd_set_errno(EINVAL);
7606 
7607         /* Return an error.  */
7608         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7609         return(NX_SOC_ERROR);
7610     }
7611 
7612     /* Check the maximum number of file descriptors.  */
7613     if((nfds < (NX_BSD_SOCKFD_START + 1)) || (nfds >= (NX_BSD_MAX_SOCKETS + NX_BSD_SOCKFD_START + 1)))
7614     {
7615 
7616         /* Set the socket error */
7617         nx_bsd_set_errno(EBADF);
7618 
7619         /* Return an error.  */
7620         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7621         return(NX_SOC_ERROR);
7622     }
7623 
7624     /* Clear the read and the write selector set.  */
7625     NX_BSD_FD_ZERO(&readfds_found);
7626     NX_BSD_FD_ZERO(&writefds_found);
7627     NX_BSD_FD_ZERO(&exceptfds_found);
7628 
7629     if(readfds)
7630         readfds_left = readfds -> fd_count;
7631     else
7632         readfds_left = 0;
7633 
7634     if(writefds)
7635     {
7636 
7637         writefds_left = writefds -> fd_count;
7638     }
7639     else
7640     {
7641 
7642         writefds_left = 0;
7643     }
7644 
7645     if(exceptfds)
7646     {
7647 
7648         exceptfds_left = exceptfds -> fd_count;
7649     }
7650     else
7651     {
7652 
7653         exceptfds_left = 0;
7654     }
7655 
7656     /* Compute the timeout for the suspension if a timeout value was supplied.  */
7657     if (timeout != NX_NULL)
7658     {
7659 
7660         /* Calculate ticks for the ThreadX Timer.  */
7661         ticks = (ULONG)(timeout -> tv_usec)/NX_MICROSECOND_PER_CPU_TICK + (ULONG)(timeout -> tv_sec) * NX_IP_PERIODIC_RATE;
7662     }
7663     else
7664     {
7665 
7666         /* If no timeout input, set the wait to 'forever.'  */
7667         ticks =  TX_WAIT_FOREVER;
7668     }
7669 
7670     /* Get the protection mutex.  */
7671     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
7672 
7673     /* Check the status.  */
7674     if (status != NX_SUCCESS)
7675     {
7676 
7677         /* Set the socket error if extended socket options enabled. */
7678         nx_bsd_set_errno(EACCES);
7679 
7680         /* Set the socket error. */
7681         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
7682         return(NX_SOC_ERROR);
7683     }
7684 
7685     /* Loop through the BSD sockets to see if the read ready request can be satisfied.  */
7686     for (i = 0; i < (nfds - NX_BSD_SOCKFD_START); i++)
7687     {
7688 
7689         if((readfds == NX_NULL) || (readfds_left == 0))
7690             break;
7691 
7692         /* Is this socket selected for read?  */
7693         if (NX_BSD_FD_ISSET((i + NX_BSD_SOCKFD_START), readfds))
7694         {
7695 
7696             /* Yes, decrement the number of read selectors left to search for.  */
7697             readfds_left--;
7698 
7699             /* Is this BSD socket in use?  */
7700             if (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
7701             {
7702 
7703                 /* There is; add this socket to the read ready list.  */
7704                 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
7705             }
7706 
7707             /* Check to see if there is a disconnection request pending.  */
7708             else if (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_DISCONNECTION_REQUEST)
7709             {
7710 
7711                 /* There is; add this socket to the read ready list.  */
7712                 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
7713             }
7714 
7715             /* Check to see if there is a receive packet pending.  */
7716             else if (nx_bsd_socket_array[i].nx_bsd_socket_received_packet)
7717             {
7718 
7719                 /* Therer is; add this socket to the read ready list.  */
7720                 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
7721             }
7722             /* Is this a TCP socket? */
7723             else if (nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket)
7724             {
7725                 /* Check if this is a master socket and if its associated secondary socket
7726                     is connected. If it is, the master socket should be considered readable. */
7727                 if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET)
7728                 {
7729 
7730                     if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN)
7731                     {
7732 
7733                         /* If the secondary socket does not exist, try to allocate one. */
7734                         if(nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id >= NX_BSD_MAX_SOCKETS)
7735                         {
7736 
7737                             /* This secondary socket is not avaialble yet.  This could happen if the
7738                                previous accept call fails to allocate a new secondary socket. */
7739                             ret = nx_bsd_tcp_create_listen_socket(i, 0);
7740 
7741                             if(ret < 0)
7742                             {
7743 
7744                                 /* Mark the FD set so the application could be notified. */
7745                                 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
7746                             }
7747                         }
7748 
7749                         if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
7750                         {
7751                             NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
7752                         }
7753                     }
7754                 }
7755                 else if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
7756                 {
7757 
7758                     /* Yes; attempt to perform a non-blocking read.  */
7759                     status =  nx_tcp_socket_receive(nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket, &packet_ptr, TX_NO_WAIT);
7760 
7761                     /* Check for success.  */
7762                     if (status == NX_SUCCESS)
7763                     {
7764 
7765                         /* Save the received packet in the TCP BSD socket packet pointer.  */
7766                         nx_bsd_socket_array[i].nx_bsd_socket_received_packet =  packet_ptr;
7767 
7768                         /* Reset the packet offset.  */
7769                         nx_bsd_socket_array[i].nx_bsd_socket_received_packet_offset =  0;
7770 
7771                         /* Increase the received count. */
7772                         nx_bsd_socket_array[i].nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
7773                         nx_bsd_socket_array[i].nx_bsd_socket_received_packet_count++;
7774 
7775                         /* Add this socket to the read ready list.  */
7776                         NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
7777                     }
7778                 }
7779             }
7780 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
7781             /* Is this a raw socket? */
7782             else if (nx_bsd_socket_array[i].nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET)
7783             {
7784 
7785                 /* Check the raw receive queue (by definition has a zero wait option (no suspension)).  */
7786                 status = nx_bsd_raw_packet_receive(&nx_bsd_socket_array[i], &packet_ptr);
7787 
7788                 /* Determine if we have a packet.  */
7789                 if ((status == NX_SUCCESS) && (packet_ptr))
7790                 {
7791 
7792                     /* Get the sender IP address from the raw packet.  */
7793                     status = nx_bsd_raw_packet_info_extract(packet_ptr, &(nx_bsd_socket_array[i].nx_bsd_socket_source_ip_address), NX_NULL);
7794 
7795                     /* Save the received packet in the BSD socket packet pointer.  */
7796                     nx_bsd_socket_array[i].nx_bsd_socket_received_packet =  packet_ptr;
7797 
7798                     /* Reset the packet offset.  */
7799                     nx_bsd_socket_array[i].nx_bsd_socket_received_packet_offset =  0;
7800 
7801                     /* Add this socket to the read ready list.  */
7802                     NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
7803                 }
7804             }
7805 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
7806 
7807         }
7808     }
7809     /* Loop through the BSD sockets to see if the write ready request can be satisfied.  */
7810     for(i = 0; i < (nfds - NX_BSD_SOCKFD_START); i++)
7811     {
7812 
7813         if((writefds == NX_NULL) || (writefds_left == 0))
7814             break;
7815 
7816         /* Is this socket selected for write?  */
7817         if (NX_BSD_FD_ISSET(i + NX_BSD_SOCKFD_START, writefds))
7818         {
7819 
7820             /* Yes, decrement the number of read selectors left to search for.  */
7821             writefds_left--;
7822 
7823             /* Is this BSD socket in use?  */
7824             if (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
7825             {
7826 
7827                 /* Yes, add this socket to the write ready list.  */
7828                 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &writefds_found);
7829             }
7830 
7831             /* Check to see if there is a connection request pending.  */
7832             else if (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_REQUEST)
7833             {
7834 
7835                 /* Yes, add this socket to the write ready list.  */
7836                 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &writefds_found);
7837             }
7838 
7839             /* Check to see if there is an error.*/
7840             else if (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
7841             {
7842 
7843                 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &writefds_found);
7844             }
7845         }
7846     }
7847 
7848     /* Loop through the BSD sockets to see if the exception request can be satisfied.  */
7849     for(i = 0; i < (nfds - NX_BSD_SOCKFD_START); i++)
7850     {
7851 
7852         if((exceptfds == NX_NULL) || (exceptfds_left == 0))
7853             break;
7854 
7855         /* Is this socket selected for exceptions?  */
7856         if (NX_BSD_FD_ISSET(i + NX_BSD_SOCKFD_START, exceptfds))
7857         {
7858 
7859             /* Yes, decrement the number of read selectors left to search for.  */
7860             exceptfds_left--;
7861 
7862             /* Is this BSD socket in use?  */
7863             if (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
7864             {
7865 
7866                 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &exceptfds_found);
7867             }
7868 
7869             /* Check to see if there is an error.*/
7870             else if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
7871             {
7872 
7873                 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &exceptfds_found);
7874             }
7875         }
7876     }
7877 
7878     /* Now determine if we have found anything that satisfies the select request.  */
7879     if (readfds_found.fd_count || writefds_found.fd_count || exceptfds_found.fd_count)
7880     {
7881 
7882         /* Yes, return what we have and we're done.   */
7883 
7884         /* Copy over the requested read ready fds.  */
7885         if(readfds)
7886             *readfds =  readfds_found;
7887 
7888         if(writefds)
7889             *writefds = writefds_found;
7890 
7891         if(exceptfds)
7892             *exceptfds = exceptfds_found;
7893 
7894         /* Release the protection mutex.  */
7895         tx_mutex_put(nx_bsd_protection_ptr);
7896 
7897         /* Return the number of fds found.  */
7898         return(readfds_found.fd_count + writefds_found.fd_count + exceptfds_found.fd_count);
7899     }
7900 
7901     /* Otherwise, nothing is ready to be read at this point.  */
7902 
7903     /* Pickup the current thread.  */
7904     current_thread_ptr =  tx_thread_identify();
7905 
7906     /* Save the fd requests in the local suspension structure. This will be used by the receive notify routines to
7907        wakeup threads on the select.  */
7908     suspend_request.nx_bsd_socket_suspend_actual_flags =  0;
7909 
7910     if(readfds)
7911         suspend_request.nx_bsd_socket_suspend_read_fd_set =  *readfds;
7912     else
7913         NX_BSD_FD_ZERO(&suspend_request.nx_bsd_socket_suspend_read_fd_set);
7914 
7915     if(writefds)
7916         suspend_request.nx_bsd_socket_suspend_write_fd_set = *writefds;
7917     else
7918         NX_BSD_FD_ZERO(&suspend_request.nx_bsd_socket_suspend_write_fd_set);
7919 
7920     if(exceptfds)
7921         suspend_request.nx_bsd_socket_suspend_exception_fd_set = *exceptfds;
7922     else
7923         NX_BSD_FD_ZERO(&suspend_request.nx_bsd_socket_suspend_exception_fd_set);
7924 
7925     /* Temporarily disable preemption.  */
7926     tx_thread_preemption_change(current_thread_ptr, 0, &original_threshold);
7927 
7928     /* Release the protection mutex.  */
7929     tx_mutex_put(nx_bsd_protection_ptr);
7930 
7931     status =  tx_event_flags_get(&nx_bsd_events, NX_BSD_SELECT_EVENT, TX_OR_CLEAR, (ULONG *) &suspend_request, ticks);
7932 
7933     /* Restore original preemption threshold.  */
7934     tx_thread_preemption_change(current_thread_ptr, original_threshold, &original_threshold);
7935 
7936     /* Check for an error.  */
7937     if (status != NX_SUCCESS)
7938     {
7939 
7940         /* If we got here, we received no packets. */
7941 
7942         /* TX_NO_EVENT implies an immediate return from the flag get call.
7943            This happens if the wait option is set to zero. */
7944         if (status == TX_NO_EVENTS)
7945         {
7946 
7947             /* Determine if the effected sockets are non blocking (zero ticks for the wait option). */
7948             if (ticks == 0)
7949                 nx_bsd_set_errno(EWOULDBLOCK);
7950             else
7951                 nx_bsd_set_errno(ETIMEDOUT);
7952 
7953             /* Do not handle as an error; just a timeout so return 0.  */
7954             return(0);
7955         }
7956         else
7957         {
7958 
7959             /* Actual error.  */
7960             /* Set the socket error if extended socket options enabled. */
7961             nx_bsd_set_errno(EINVAL);
7962 
7963             /* Error getting the protection mutex.  */
7964             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7965             return(NX_SOC_ERROR);
7966         }
7967     }
7968     else
7969     {
7970 
7971         /* Otherwise, a receive event has been found. Simply copy the receive events.  */
7972         if(readfds)
7973             *readfds =  suspend_request.nx_bsd_socket_suspend_read_fd_set;
7974         if(writefds)
7975             *writefds = suspend_request.nx_bsd_socket_suspend_write_fd_set;
7976         if(exceptfds)
7977             *exceptfds = suspend_request.nx_bsd_socket_suspend_exception_fd_set;
7978 
7979         /* Return the number of fds.  */
7980         return(suspend_request.nx_bsd_socket_suspend_read_fd_set.fd_count +
7981                suspend_request.nx_bsd_socket_suspend_write_fd_set.fd_count +
7982                suspend_request.nx_bsd_socket_suspend_exception_fd_set.fd_count);
7983     }
7984 
7985 
7986 }
7987 
7988 
7989 
7990 /**************************************************************************/
7991 /*                                                                        */
7992 /*  FUNCTION                                               RELEASE        */
7993 /*                                                                        */
7994 /*    nx_bsd_tcp_receive_notify                           PORTABLE C      */
7995 /*                                                           6.1          */
7996 /*  AUTHOR                                                                */
7997 /*                                                                        */
7998 /*    Yuxin Zhou, Microsoft Corporation                                   */
7999 /*                                                                        */
8000 /*  DESCRIPTION                                                           */
8001 /*                                                                        */
8002 /*    This is the NetX callback function for TCP Socket receive operation */
8003 /*    This function resumes all the threads suspended on the socket.      */
8004 /*                                                                        */
8005 /*  INPUT                                                                 */
8006 /*                                                                        */
8007 /*    *socket_ptr                           Pointer to the socket which   */
8008 /*                                            received the data packet    */
8009 /*                                                                        */
8010 /*  OUTPUT                                                                */
8011 /*                                                                        */
8012 /*    None                                                                */
8013 /*                                                                        */
8014 /*  CALLS                                                                 */
8015 /*                                                                        */
8016 /*    FD_ZERO                               Clear a socket ready list     */
8017 /*    FD_ISSET                              Check a socket is ready       */
8018 /*    FD_SET                                Set a socket to check         */
8019 /*    tx_event_flags_get                    Get events                    */
8020 /*    tx_mutex_get                          Get protection                */
8021 /*    tx_mutex_put                          Release protection            */
8022 /*    tx_thread_identify                    Get current thread pointer    */
8023 /*                                                                        */
8024 /*  CALLED BY                                                             */
8025 /*                                                                        */
8026 /*    NetX                                                                */
8027 /*                                                                        */
8028 /*  RELEASE HISTORY                                                       */
8029 /*                                                                        */
8030 /*    DATE              NAME                      DESCRIPTION             */
8031 /*                                                                        */
8032 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8033 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8034 /*                                            resulting in version 6.1    */
8035 /*                                                                        */
8036 /**************************************************************************/
nx_bsd_tcp_receive_notify(NX_TCP_SOCKET * socket_ptr)8037 static VOID  nx_bsd_tcp_receive_notify(NX_TCP_SOCKET *socket_ptr)
8038 {
8039 UINT                    bsd_socket_index;
8040 
8041     /* Figure out what BSD socket this is.  */
8042     bsd_socket_index =  (UINT) socket_ptr -> nx_tcp_socket_reserved_ptr;
8043 
8044     /* Determine if this is a good index into the BSD socket array.  */
8045     if (bsd_socket_index >= NX_BSD_MAX_SOCKETS)
8046     {
8047 
8048         /* Bad socket index... simply return!  */
8049         return;
8050     }
8051 
8052     /* Now check if the socket may have been released (e.g. socket closed) while
8053        waiting for the mutex. */
8054     if( socket_ptr -> nx_tcp_socket_id == 0 )
8055     {
8056 
8057         return;
8058     }
8059 
8060     /* Check the suspended socket list for one ready to receive or send packets. */
8061     nx_bsd_select_wakeup(bsd_socket_index, FDSET_READ);
8062 
8063 
8064     return;
8065 }
8066 
8067 
8068 /**************************************************************************/
8069 /*                                                                        */
8070 /*  FUNCTION                                               RELEASE        */
8071 /*                                                                        */
8072 /*    nx_bsd_tcp_establish_notify                         PORTABLE C      */
8073 /*                                                           6.1          */
8074 /*  AUTHOR                                                                */
8075 /*                                                                        */
8076 /*    Yuxin Zhou, Microsoft Corporation                                   */
8077 /*                                                                        */
8078 /*  DESCRIPTION                                                           */
8079 /*                                                                        */
8080 /*    This is the NetX callback function for TCP Server Socket listen.    */
8081 /*    This function resumes all the threads suspended on the socket.      */
8082 /*                                                                        */
8083 /*  INPUT                                                                 */
8084 /*                                                                        */
8085 /*    *socket_ptr                           Pointer to the socket which   */
8086 /*                                          Received the data packet      */
8087 /*                                                                        */
8088 /*  OUTPUT                                                                */
8089 /*                                                                        */
8090 /*    None                                                                */
8091 /*                                                                        */
8092 /*  CALLS                                                                 */
8093 /*                                                                        */
8094 /*    FD_ZERO                               Clear a socket ready list     */
8095 /*    FD_ISSET                              Check a socket is ready       */
8096 /*    FD_SET                                Set a socket to check         */
8097 /*    tx_event_flags_get                    Get events                    */
8098 /*    tx_mutex_get                          Get protection                */
8099 /*    tx_mutex_put                          Release protection            */
8100 /*    tx_thread_identify                    Get current thread pointer    */
8101 /*                                                                        */
8102 /*  CALLED BY                                                             */
8103 /*                                                                        */
8104 /*    NetX                                                                */
8105 /*                                                                        */
8106 /*  RELEASE HISTORY                                                       */
8107 /*                                                                        */
8108 /*    DATE              NAME                      DESCRIPTION             */
8109 /*                                                                        */
8110 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8111 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8112 /*                                            resulting in version 6.1    */
8113 /*                                                                        */
8114 /**************************************************************************/
8115 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
nx_bsd_tcp_establish_notify(NX_TCP_SOCKET * socket_ptr)8116 static VOID  nx_bsd_tcp_establish_notify(NX_TCP_SOCKET *socket_ptr)
8117 {
8118 UINT                    bsd_socket_index;
8119 UINT                    master_socket_index;
8120 
8121     /* Figure out what BSD socket this is.  */
8122     bsd_socket_index =  (UINT) socket_ptr -> nx_tcp_socket_reserved_ptr;
8123 
8124     /* Determine if this is a good index into the BSD socket array.  */
8125     if (bsd_socket_index >= NX_BSD_MAX_SOCKETS)
8126     {
8127 
8128         /* Bad socket index... simply return!  */
8129         return;
8130     }
8131 
8132     /* Initialize the master socket index to an invalid value so we can check if it was actually used
8133        later.  */
8134     master_socket_index =  NX_BSD_MAX_SOCKETS;
8135 
8136     /* Mark the socket as connected, and also clear the EINPROGRESS flag */
8137     nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
8138 
8139     nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags |=  NX_BSD_SOCKET_CONNECTION_REQUEST;
8140 
8141     /* Reset the listen-enabled flag. */
8142     nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_LISTEN);
8143 
8144     /* Mark the socket is bound. */
8145     nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
8146 
8147 #ifndef NX_DISABLE_IPV4
8148     /* Find out the local address this socket is connected on. */
8149     if(nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_family == AF_INET)
8150     {
8151         /* IPv4 case */
8152         nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_local_bind_interface = (ULONG)socket_ptr -> nx_tcp_socket_connect_interface;
8153     }
8154 #endif /* NX_DISABLE_IPV4 */
8155 #ifdef FEATURE_NX_IPV6
8156     if(nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_family == AF_INET6)
8157     {
8158         /* IPv6 */
8159         nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_local_bind_interface = (ULONG)socket_ptr -> nx_tcp_socket_ipv6_addr;
8160     }
8161 #endif
8162     /* Determine if the BSD socket is server socket. */
8163 
8164 
8165     /* Is this a secondary socket? */
8166     if (nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET)
8167     {
8168 
8169         /* Yes, get the master socket.  */
8170         master_socket_index =  (UINT)(nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_union_id.nx_bsd_socket_master_socket_id);
8171 
8172         /* Mark the server socket as also connected. */
8173         nx_bsd_socket_array[master_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
8174 
8175         nx_bsd_socket_array[master_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_REQUEST;
8176 
8177         /* Check on connect requests for all server sockets for this master socket. */
8178         nx_bsd_select_wakeup(master_socket_index, FDSET_READ);
8179     }
8180     else
8181     {
8182         /* This is a client socket. */
8183         nx_bsd_select_wakeup(bsd_socket_index, FDSET_WRITE);
8184     }
8185 }
8186 #endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */
8187 
8188 /**************************************************************************/
8189 /*                                                                        */
8190 /*  FUNCTION                                               RELEASE        */
8191 /*                                                                        */
8192 /*    nx_bsd_tcp_socket_disconnect_notify                 PORTABLE C      */
8193 /*                                                           6.1          */
8194 /*  AUTHOR                                                                */
8195 /*                                                                        */
8196 /*    Yuxin Zhou, Microsoft Corporation                                   */
8197 /*                                                                        */
8198 /*  DESCRIPTION                                                           */
8199 /*                                                                        */
8200 /*    This is the NetX callback function for TCP Socket disconnect.       */
8201 /*    This function resumes all the BSD threads suspended on the socket.  */
8202 /*                                                                        */
8203 /*  INPUT                                                                 */
8204 /*                                                                        */
8205 /*    *socket_ptr                           Pointer to the socket which   */
8206 /*                                            received the data packet    */
8207 /*                                                                        */
8208 /*  OUTPUT                                                                */
8209 /*                                                                        */
8210 /*    None                                                                */
8211 /*                                                                        */
8212 /*  CALLS                                                                 */
8213 /*                                                                        */
8214 /*    FD_ZERO                               Clear a socket ready list     */
8215 /*    FD_ISSET                              Check a socket is ready       */
8216 /*    FD_SET                                Set a socket to check         */
8217 /*    tx_event_flags_get                    Get events                    */
8218 /*    tx_mutex_get                          Get protection                */
8219 /*    tx_mutex_put                          Release protection            */
8220 /*    tx_thread_identify                    Get current thread pointer    */
8221 /*                                                                        */
8222 /*  CALLED BY                                                             */
8223 /*                                                                        */
8224 /*    NetX                                                                */
8225 /*                                                                        */
8226 /*  RELEASE HISTORY                                                       */
8227 /*                                                                        */
8228 /*    DATE              NAME                      DESCRIPTION             */
8229 /*                                                                        */
8230 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8231 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8232 /*                                            resulting in version 6.1    */
8233 /*                                                                        */
8234 /**************************************************************************/
nx_bsd_tcp_socket_disconnect_notify(NX_TCP_SOCKET * socket_ptr)8235 static VOID  nx_bsd_tcp_socket_disconnect_notify(NX_TCP_SOCKET *socket_ptr)
8236 {
8237 
8238 UINT                    bsd_socket_index;
8239 UINT                    master_socket_index;
8240 NX_BSD_SOCKET          *bsd_socket_ptr;
8241 UINT                    status;
8242 
8243 
8244     /* Figure out what BSD socket this is.  */
8245     bsd_socket_index =  (UINT) socket_ptr -> nx_tcp_socket_reserved_ptr;
8246 
8247     /* Determine if this is a good index into the BSD socket array.  */
8248     if (bsd_socket_index >= NX_BSD_MAX_SOCKETS)
8249     {
8250         /* No good! */
8251         return;
8252     }
8253 
8254     bsd_socket_ptr = &nx_bsd_socket_array[bsd_socket_index];
8255 
8256     /* If the socket already received a disconnect request, no need to do anything here. */
8257     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_DISCONNECTION_REQUEST)
8258     {
8259         return;
8260     }
8261 
8262     /* Mark this socket as having a disconnect request pending.  */
8263     bsd_socket_ptr -> nx_bsd_socket_status_flags |=  NX_BSD_SOCKET_DISCONNECTION_REQUEST;
8264 
8265     /* Is the socket trying to make a connection? */
8266     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_INPROGRESS)
8267     {
8268 
8269         /* Yes, clear the INPROGRESS flag. */
8270         bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
8271 
8272         /* If this is secondary server socket, there is no need to wake up the select call.  */
8273         if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET)
8274         {
8275 
8276 
8277             /* Instead the socket needs to be cleaned up and to perform a relisten. */
8278             if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED))
8279             {
8280 
8281                 /* Turn off the disconnection_request flag. */
8282                 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_DISCONNECTION_REQUEST);
8283 
8284                 nx_tcp_server_socket_unaccept(bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
8285 
8286                 /* Check if a listen request is queued up for this socket. */
8287                 nx_bsd_tcp_pending_connection(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port,
8288                                               bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
8289 
8290                 status = nx_tcp_server_socket_relisten(nx_bsd_default_ip,
8291                                                        bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port,
8292                                                        bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
8293 
8294                 /* Force the socket into SYN_RECEIVED state */
8295                 nx_tcp_server_socket_accept(bsd_socket_ptr -> nx_bsd_socket_tcp_socket, NX_NO_WAIT);
8296 
8297                 if(status == NX_CONNECTION_PENDING)
8298                 {
8299 
8300                     bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
8301                 }
8302                 else if(status != NX_SUCCESS)
8303                 {
8304 
8305                     /* Failed the relisten on the secondary socket.  Set the error code on the
8306                        master socket, and wake it up. */
8307 
8308                     master_socket_index = (UINT)(bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id;
8309 
8310                     nx_bsd_socket_array[master_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
8311                     nx_bsd_set_error_code(&nx_bsd_socket_array[master_socket_index], status);
8312 
8313                     nx_bsd_select_wakeup(master_socket_index, (FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION));
8314                 }
8315             }
8316 
8317         }
8318         else
8319         {
8320 
8321             /* Set error code. */
8322             bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
8323             bsd_socket_ptr -> nx_bsd_socket_error_code = ECONNREFUSED;
8324 
8325             /* Wake up the select on both read and write FDsets. */
8326             nx_bsd_select_wakeup(bsd_socket_index, (FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION));
8327         }
8328     }
8329     else if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
8330     {
8331 
8332         /* Wake up the select on both read and write FDsets. */
8333         nx_bsd_select_wakeup(bsd_socket_index, (FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION));
8334     }
8335     else
8336     {
8337 
8338         /* In this case, connection reaches maximum retries or is refused by peer. */
8339         bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
8340         bsd_socket_ptr -> nx_bsd_socket_error_code = ENOTCONN;
8341     }
8342 
8343 }
8344 
8345 
8346 
8347 /**************************************************************************/
8348 /*                                                                        */
8349 /*  FUNCTION                                               RELEASE        */
8350 /*                                                                        */
8351 /*    nx_bsd_udp_receive_notify                           PORTABLE C      */
8352 /*                                                           6.1          */
8353 /*  AUTHOR                                                                */
8354 /*                                                                        */
8355 /*    Yuxin Zhou, Microsoft Corporation                                   */
8356 /*                                                                        */
8357 /*  DESCRIPTION                                                           */
8358 /*                                                                        */
8359 /*    This is the NetX callback function for UDP Socket receive           */
8360 /*    operation.                                                          */
8361 /*                                                                        */
8362 /*  INPUT                                                                 */
8363 /*                                                                        */
8364 /*    *socket_ptr                           Pointer to the socket which   */
8365 /*                                          Received the data packet      */
8366 /*                                                                        */
8367 /*  OUTPUT                                                                */
8368 /*                                                                        */
8369 /*    None                                                                */
8370 /*                                                                        */
8371 /*  CALLS                                                                 */
8372 /*                                                                        */
8373 /*    FD_ZERO                               Clear a socket ready list     */
8374 /*    FD_ISSET                              Check a socket is ready       */
8375 /*    FD_SET                                Set a socket to check         */
8376 /*    tx_event_flags_get                    Get events                    */
8377 /*    tx_mutex_get                          Get protection                */
8378 /*    tx_mutex_put                          Release protection            */
8379 /*    tx_thread_identify                    Get current thread pointer    */
8380 /*    nx_udp_socket_receive                 Receive UDP packet            */
8381 /*                                                                        */
8382 /*  CALLED BY                                                             */
8383 /*                                                                        */
8384 /*    NetX                                                                */
8385 /*                                                                        */
8386 /*  RELEASE HISTORY                                                       */
8387 /*                                                                        */
8388 /*    DATE              NAME                      DESCRIPTION             */
8389 /*                                                                        */
8390 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8391 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8392 /*                                            resulting in version 6.1    */
8393 /*                                                                        */
8394 /**************************************************************************/
nx_bsd_udp_receive_notify(NX_UDP_SOCKET * socket_ptr)8395 static VOID  nx_bsd_udp_receive_notify(NX_UDP_SOCKET *socket_ptr)
8396 {
8397 
8398 UINT                    bsd_socket_index;
8399 NX_PACKET               *packet_ptr;
8400 NX_UDP_SOCKET           *udp_socket_ptr;
8401 
8402 
8403     /* Figure out what BSD socket this is.  */
8404     bsd_socket_index =  ((UINT) socket_ptr -> nx_udp_socket_reserved_ptr) & 0x0000FFFF;
8405 
8406     /* Determine if this is a good index into the BSD socket array.  */
8407     if (bsd_socket_index >= NX_BSD_MAX_SOCKETS)
8408     {
8409         return;
8410     }
8411 
8412     udp_socket_ptr = nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_udp_socket;
8413 
8414     if (nx_udp_socket_receive(udp_socket_ptr, &packet_ptr, NX_NO_WAIT))
8415     {
8416         return;
8417     }
8418 
8419     nx_bsd_udp_packet_received((INT)bsd_socket_index, packet_ptr);
8420 
8421 }
8422 
8423 
8424 /**************************************************************************/
8425 /*                                                                        */
8426 /*  FUNCTION                                               RELEASE        */
8427 /*                                                                        */
8428 /*    FD_SET                                              PORTABLE C      */
8429 /*                                                           6.3.0        */
8430 /*  AUTHOR                                                                */
8431 /*                                                                        */
8432 /*    Yuxin Zhou, Microsoft Corporation                                   */
8433 /*                                                                        */
8434 /*  DESCRIPTION                                                           */
8435 /*                                                                        */
8436 /*   This function adds a fd to the set.                                  */
8437 /*                                                                        */
8438 /*  INPUT                                                                 */
8439 /*                                                                        */
8440 /*    fd                                    fd to add.                    */
8441 /*    fd_set *fdset                         fd set.                       */
8442 /*                                                                        */
8443 /*  OUTPUT                                                                */
8444 /*                                                                        */
8445 /*    None                                                                */
8446 /*                                                                        */
8447 /*  CALLS                                                                 */
8448 /*                                                                        */
8449 /*    None                                                                */
8450 /*                                                                        */
8451 /*  CALLED BY                                                             */
8452 /*                                                                        */
8453 /*    Application Code                                                    */
8454 /*                                                                        */
8455 /*  RELEASE HISTORY                                                       */
8456 /*                                                                        */
8457 /*    DATE              NAME                      DESCRIPTION             */
8458 /*                                                                        */
8459 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8460 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8461 /*                                            resulting in version 6.1    */
8462 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
8463 /*                                            used new API/structs naming,*/
8464 /*                                            resulting in version 6.3.0  */
8465 /*                                                                        */
8466 /**************************************************************************/
NX_BSD_FD_SET(INT fd,nx_bsd_fd_set * fdset)8467 VOID  NX_BSD_FD_SET(INT fd, nx_bsd_fd_set *fdset)
8468 {
8469 
8470 UINT    index;
8471 
8472 
8473     /* Check the FD size.  */
8474     if (fd >= NX_BSD_SOCKFD_START)
8475     {
8476 
8477         /* Normalize the fd.  */
8478         fd =  fd - NX_BSD_SOCKFD_START;
8479 
8480         /* Now make sure it isn't too big.  */
8481         if (fd < NX_BSD_MAX_SOCKETS)
8482         {
8483 
8484             /* Calculate the index into the bit map.  */
8485             index =  (UINT)fd/32;
8486 
8487             /* Now calculate the bit position.  */
8488             fd =  fd % 32;
8489 
8490             /* Is the bit already set?  */
8491             if ((fdset -> fd_array[index] & (((ULONG) 1) << fd)) == 0)
8492             {
8493 
8494                 /* No, set the bit.  */
8495                 fdset -> fd_array[index] = fdset -> fd_array[index] | (((ULONG) 1) << fd);
8496 
8497                 /* Increment the counter.  */
8498                 fdset -> fd_count++;
8499             }
8500         }
8501     }
8502 }
8503 
8504 /**************************************************************************/
8505 /*                                                                        */
8506 /*  FUNCTION                                               RELEASE        */
8507 /*                                                                        */
8508 /*    FD_CLR                                              PORTABLE C      */
8509 /*                                                           6.3.0        */
8510 /*  AUTHOR                                                                */
8511 /*                                                                        */
8512 /*    Yuxin Zhou, Microsoft Corporation                                   */
8513 /*                                                                        */
8514 /*  DESCRIPTION                                                           */
8515 /*                                                                        */
8516 /*   This function removes a fd from a fd set.                            */
8517 /*                                                                        */
8518 /*  INPUT                                                                 */
8519 /*                                                                        */
8520 /*    fd                                    fd to remove.                 */
8521 /*    fd_set *fdset                         fd set.                       */
8522 /*                                                                        */
8523 /*  OUTPUT                                                                */
8524 /*                                                                        */
8525 /*    None                                                                */
8526 /*                                                                        */
8527 /*  CALLS                                                                 */
8528 /*                                                                        */
8529 /*    None                                                                */
8530 /*                                                                        */
8531 /*  CALLED BY                                                             */
8532 /*                                                                        */
8533 /*    Application Code                                                    */
8534 /*                                                                        */
8535 /*  RELEASE HISTORY                                                       */
8536 /*                                                                        */
8537 /*    DATE              NAME                      DESCRIPTION             */
8538 /*                                                                        */
8539 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8540 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8541 /*                                            resulting in version 6.1    */
8542 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
8543 /*                                            used new API/structs naming,*/
8544 /*                                            resulting in version 6.3.0  */
8545 /*                                                                        */
8546 /**************************************************************************/
NX_BSD_FD_CLR(INT fd,nx_bsd_fd_set * fdset)8547 VOID  NX_BSD_FD_CLR(INT fd, nx_bsd_fd_set *fdset)
8548 {
8549 
8550 UINT    index;
8551 
8552 
8553     /* Check the FD size.  */
8554     if (fd >= NX_BSD_SOCKFD_START)
8555     {
8556 
8557         /* Normalize the fd.  */
8558         fd =  fd - NX_BSD_SOCKFD_START;
8559 
8560         /* Now make sure it isn't too big.  */
8561         if ((fd < NX_BSD_MAX_SOCKETS) && (fdset -> fd_count))
8562         {
8563 
8564             /* Calculate the index into the bit map.  */
8565             index =  (UINT)fd/32;
8566 
8567             /* Now calculate the bit position.  */
8568             fd =  fd % 32;
8569 
8570             /* Determine if the bit is set.  */
8571             if (fdset -> fd_array[index] & (((ULONG) 1) << fd))
8572             {
8573 
8574                 /* Yes, clear the bit.  */
8575                 fdset -> fd_array[index] = fdset -> fd_array[index] & ~(((ULONG) 1) << fd);
8576 
8577                 /* Decrement the counter.  */
8578                 fdset -> fd_count--;
8579             }
8580         }
8581     }
8582 }
8583 
8584 
8585 /**************************************************************************/
8586 /*                                                                        */
8587 /*  FUNCTION                                               RELEASE        */
8588 /*                                                                        */
8589 /*    FD_ISSET                                            PORTABLE C      */
8590 /*                                                           6.1          */
8591 /*  AUTHOR                                                                */
8592 /*                                                                        */
8593 /*    Yuxin Zhou, Microsoft Corporation                                   */
8594 /*                                                                        */
8595 /*  DESCRIPTION                                                           */
8596 /*                                                                        */
8597 /*   This function tests to see if a fd is in the set.                    */
8598 /*                                                                        */
8599 /*  INPUT                                                                 */
8600 /*                                                                        */
8601 /*    fd                                    fd to add.                    */
8602 /*    fd_set *fdset                         fd set.                       */
8603 /*                                                                        */
8604 /*  OUTPUT                                                                */
8605 /*                                                                        */
8606 /*    NX_TRUE                               If fd is found in the set.    */
8607 /*    NX_FALSE                              If fd is not there in the set.*/
8608 /*                                                                        */
8609 /*  CALLS                                                                 */
8610 /*                                                                        */
8611 /*    None                                                                */
8612 /*                                                                        */
8613 /*  CALLED BY                                                             */
8614 /*                                                                        */
8615 /*    Application Code                                                    */
8616 /*                                                                        */
8617 /*  RELEASE HISTORY                                                       */
8618 /*                                                                        */
8619 /*    DATE              NAME                      DESCRIPTION             */
8620 /*                                                                        */
8621 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8622 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8623 /*                                            resulting in version 6.1    */
8624 /*                                                                        */
8625 /**************************************************************************/
NX_BSD_FD_ISSET(INT fd,nx_bsd_fd_set * fdset)8626 INT  NX_BSD_FD_ISSET(INT fd, nx_bsd_fd_set *fdset)
8627 {
8628 
8629 UINT    index;
8630 
8631 
8632     /* Check the FD size.  */
8633     if (fd >= NX_BSD_SOCKFD_START)
8634     {
8635 
8636         /* Normalize the fd.  */
8637         fd =  fd - NX_BSD_SOCKFD_START;
8638 
8639         /* Now make sure it isn't too big.  */
8640         if (fd < NX_BSD_MAX_SOCKETS)
8641         {
8642 
8643             /* Calculate the index into the bit map.  */
8644             index =  (UINT)fd/32;
8645 
8646             /* Now calculate the bit position.  */
8647             fd =  fd % 32;
8648 
8649             /* Finally, see if the bit is set.  */
8650             if (fdset -> fd_array[index] & (((ULONG) 1) << fd))
8651             {
8652 
8653                 /* Yes, return true!  */
8654                 return(NX_TRUE);
8655             }
8656         }
8657     }
8658 
8659     /* Otherwise, return false.  */
8660     return(NX_FALSE);
8661 }
8662 
8663 
8664 /**************************************************************************/
8665 /*                                                                        */
8666 /*  FUNCTION                                               RELEASE        */
8667 /*                                                                        */
8668 /*    FD_ZERO                                             PORTABLE C      */
8669 /*                                                           6.3.0        */
8670 /*  AUTHOR                                                                */
8671 /*                                                                        */
8672 /*    Yuxin Zhou, Microsoft Corporation                                   */
8673 /*                                                                        */
8674 /*  DESCRIPTION                                                           */
8675 /*                                                                        */
8676 /*   This function clears a fd set.                                       */
8677 /*                                                                        */
8678 /*  INPUT                                                                 */
8679 /*                                                                        */
8680 /*   fd_set *fdset                          fd set to clear.              */
8681 /*                                                                        */
8682 /*  OUTPUT                                                                */
8683 /*                                                                        */
8684 /*    None                                                                */
8685 /*                                                                        */
8686 /*  CALLS                                                                 */
8687 /*                                                                        */
8688 /*    None                                                                */
8689 /*                                                                        */
8690 /*  CALLED BY                                                             */
8691 /*                                                                        */
8692 /*    Application Code                                                    */
8693 /*                                                                        */
8694 /*  RELEASE HISTORY                                                       */
8695 /*                                                                        */
8696 /*    DATE              NAME                      DESCRIPTION             */
8697 /*                                                                        */
8698 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8699 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8700 /*                                            resulting in version 6.1    */
8701 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
8702 /*                                            used new API/structs naming,*/
8703 /*                                            resulting in version 6.3.0  */
8704 /*                                                                        */
8705 /**************************************************************************/
NX_BSD_FD_ZERO(nx_bsd_fd_set * fdset)8706 VOID  NX_BSD_FD_ZERO(nx_bsd_fd_set *fdset)
8707 {
8708 
8709 INT     i;
8710 
8711 
8712     /* Clear the count.  */
8713     fdset -> fd_count =  0;
8714 
8715     /* Loop to clear the fd set.  */
8716     for (i = 0; i < (NX_BSD_MAX_SOCKETS+31)/32; i++)
8717     {
8718         /* Clear an entry in the array.  */
8719         fdset -> fd_array[i] =  0;
8720     }
8721 }
8722 
8723 
8724 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
8725 /**************************************************************************/
8726 /*                                                                        */
8727 /*  FUNCTION                                               RELEASE        */
8728 /*                                                                        */
8729 /*    nx_bsd_raw_packet_filter                            PORTABLE C      */
8730 /*                                                           6.1.9        */
8731 /*  AUTHOR                                                                */
8732 /*                                                                        */
8733 /*    Yuxin Zhou, Microsoft Corporation                                   */
8734 /*                                                                        */
8735 /*  DESCRIPTION                                                           */
8736 /*                                                                        */
8737 /*    This function receives raw packets from NetX Duo and determines if  */
8738 /*    BSD will consume the packet (store on the BSD socket raw receive    */
8739 /*    queue) or if the packet is available to NetX Duo (not consumed).    */
8740 /*                                                                        */
8741 /*  INPUT                                                                 */
8742 /*                                                                        */
8743 /*    ip_ptr                               NetX Duo IP instance           */
8744 /*    protocol                             Received packet protocol       */
8745 /*    packet_ptr                           Pointer to the received packet */
8746 /*                                                                        */
8747 /*  OUTPUT                                                                */
8748 /*                                                                        */
8749 /*    0                                     Raw filter consumed the packet*/
8750 /*    1                                     Raw filter did not consume    */
8751 /*                                            packet.  Allow the caller to*/
8752 /*                                            process this packet         */
8753 /*                                                                        */
8754 /*  CALLS                                                                 */
8755 /*                                                                        */
8756 /*    nx_bsd_raw_receive_notify             Notify threads waiting to     */
8757 /*                                               receive a raw packet     */
8758 /*                                                                        */
8759 /*  CALLED BY                                                             */
8760 /*                                                                        */
8761 /*    NetX Duo                                                            */
8762 /*                                                                        */
8763 /*  RELEASE HISTORY                                                       */
8764 /*                                                                        */
8765 /*    DATE              NAME                      DESCRIPTION             */
8766 /*                                                                        */
8767 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8768 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8769 /*                                            resulting in version 6.1    */
8770 /*  10-15-2021     Yuxin Zhou               Modified comment(s),          */
8771 /*                                            fixed NULL pointer access   */
8772 /*                                            for raw socket,             */
8773 /*                                            resulting in version 6.1.9  */
8774 /*                                                                        */
8775 /**************************************************************************/
nx_bsd_raw_packet_filter(NX_IP * ip_ptr,ULONG protocol,NX_PACKET * packet_ptr)8776 static UINT  nx_bsd_raw_packet_filter(NX_IP *ip_ptr, ULONG protocol, NX_PACKET *packet_ptr)
8777 {
8778 
8779 UINT index;
8780 NX_BSD_SOCKET * bsd_socket_ptr;
8781 
8782     /* Calculate the hash index in the raw socket protocol table. */
8783     index = (UINT) ((protocol + (protocol >> 8)) & NX_BSD_SOCKET_RAW_PROTOCOL_TABLE_MASK);
8784 
8785     /* Search the bound sockets in this index for particular protocol. */
8786     bsd_socket_ptr = nx_bsd_socket_raw_protocol_table[index];
8787 
8788     /* Was a BSD socket with this protocol found? */
8789     if (bsd_socket_ptr == NX_NULL)
8790     {
8791         /* No, let NetX Duo continue processing the packet. */
8792         return 1;
8793     }
8794 
8795     do
8796     {
8797         /* Determine if the protocol is matched. */
8798         if ((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE) &&
8799             (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET ) &&
8800             (bsd_socket_ptr -> nx_bsd_socket_protocol == protocol))
8801         {
8802 
8803             /* This packet protocol matches the BSD socket. */
8804             /* Make sure the queue_next is zero'ed out. */
8805             packet_ptr -> nx_packet_queue_next = NX_NULL;
8806 
8807             /* Add the packet to the BSD socket raw packet receive queue.
8808                Are there any packets on this queue yet?  */
8809             if (bsd_socket_ptr -> nx_bsd_socket_received_packet == NX_NULL)
8810             {
8811 
8812                 /* No, this will be the only one. */
8813                 bsd_socket_ptr -> nx_bsd_socket_received_packet = packet_ptr;
8814                 bsd_socket_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
8815 
8816 
8817                 /* Set the packet count. */
8818                 bsd_socket_ptr -> nx_bsd_socket_received_byte_count = packet_ptr -> nx_packet_length;
8819                 bsd_socket_ptr -> nx_bsd_socket_received_packet_count = 1;
8820             }
8821             else
8822             {
8823                 /* Yes; add this packet to the end of the queue. */
8824 
8825                 /* Check if the queue is currently full. */
8826                 if (bsd_socket_ptr -> nx_bsd_socket_received_byte_count_max &&
8827                     (bsd_socket_ptr -> nx_bsd_socket_received_byte_count >=
8828                     bsd_socket_ptr -> nx_bsd_socket_received_byte_count_max))
8829                 {
8830 
8831                     /* Release the packet here, and tell NetX Duo the packet is 'consumed'. */
8832                     nx_packet_release(packet_ptr);
8833 
8834                     return 0;
8835                 }
8836 
8837                 /* Drop the packet if the receive queue exceeds max depth.*/
8838                 if(bsd_socket_ptr -> nx_bsd_socket_received_packet_count >=
8839                    bsd_socket_ptr -> nx_bsd_socket_received_packet_count_max)
8840                 {
8841                     /* Release the packet here, and tell NetX Duo the packet is 'consumed'. */
8842                     nx_packet_release(packet_ptr);
8843 
8844                     return 0;
8845                 }
8846 
8847                 /* Add this packet to the end of the BSD raw receive queue. */
8848                 (bsd_socket_ptr -> nx_bsd_socket_received_packet_tail) -> nx_packet_queue_next = packet_ptr;
8849                 bsd_socket_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
8850 
8851 
8852                 /* Update our packet count. */
8853                 bsd_socket_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
8854                 bsd_socket_ptr -> nx_bsd_socket_received_packet_count++;
8855             }
8856 
8857             /* Notify any suspended threads waiting on this receive event. */
8858             nx_bsd_raw_receive_notify(ip_ptr, (UINT)(bsd_socket_ptr -> nx_bsd_socket_id));
8859 
8860             return 0;
8861         }
8862 
8863     }while(bsd_socket_ptr != nx_bsd_socket_raw_protocol_table[index]);
8864 
8865     /* Was a BSD socket with this protocol found? */
8866     if (bsd_socket_ptr == nx_bsd_socket_raw_protocol_table[index])
8867     {
8868         /* No, let NetX Duo continue processing the packet. */
8869         return 1;
8870     }
8871 
8872     return(NX_SUCCESS);
8873 }
8874 
8875 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
8876 
8877 
8878 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
8879 /**************************************************************************/
8880 /*                                                                        */
8881 /*  FUNCTION                                               RELEASE        */
8882 /*                                                                        */
8883 /*    nx_bsd_raw_receive_notify                           PORTABLE C      */
8884 /*                                                           6.1          */
8885 /*  AUTHOR                                                                */
8886 /*                                                                        */
8887 /*    Yuxin Zhou, Microsoft Corporation                                   */
8888 /*                                                                        */
8889 /*  DESCRIPTION                                                           */
8890 /*                                                                        */
8891 /*    This is the NetX Duo callback function for raw socket receive       */
8892 /*    operation.                                                          */
8893 /*                                                                        */
8894 /*  INPUT                                                                 */
8895 /*                                                                        */
8896 /*    ip_ptr                               NetX Duo IP instance           */
8897 /*    bsd_socket_index                     Index of the raw socket which  */
8898 /*                                            received the data packet    */
8899 /*                                                                        */
8900 /*  OUTPUT                                                                */
8901 /*                                                                        */
8902 /*    None                                                                */
8903 /*                                                                        */
8904 /*  CALLS                                                                 */
8905 /*                                                                        */
8906 /*    FD_ZERO                               Clear a socket ready list     */
8907 /*    FD_ISSET                              Check a socket is ready       */
8908 /*    FD_SET                                Set a socket to check         */
8909 /*    tx_event_flags_get                    Get events                    */
8910 /*    tx_mutex_get                          Get protection                */
8911 /*    tx_mutex_put                          Release protection            */
8912 /*    tx_thread_identify                    Get current thread pointer    */
8913 /*                                                                        */
8914 /*  CALLED BY                                                             */
8915 /*                                                                        */
8916 /*    NetX                                                                */
8917 /*                                                                        */
8918 /*  RELEASE HISTORY                                                       */
8919 /*                                                                        */
8920 /*    DATE              NAME                      DESCRIPTION             */
8921 /*                                                                        */
8922 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8923 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8924 /*                                            resulting in version 6.1    */
8925 /*                                                                        */
8926 /**************************************************************************/
nx_bsd_raw_receive_notify(NX_IP * ip_ptr,UINT bsd_socket_index)8927 VOID  nx_bsd_raw_receive_notify(NX_IP *ip_ptr, UINT bsd_socket_index)
8928 {
8929     NX_PARAMETER_NOT_USED(ip_ptr);
8930 
8931     nx_bsd_select_wakeup(bsd_socket_index, FDSET_READ);
8932 
8933 }
8934 
8935 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
8936 
8937 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
8938 
8939 /**************************************************************************/
8940 /*                                                                        */
8941 /*  FUNCTION                                               RELEASE        */
8942 /*                                                                        */
8943 /*    nx_bsd_raw_packet_receive                           PORTABLE C      */
8944 /*                                                           6.3.0        */
8945 /*  AUTHOR                                                                */
8946 /*                                                                        */
8947 /*    Yuxin Zhou, Microsoft Corporation                                   */
8948 /*                                                                        */
8949 /*  DESCRIPTION                                                           */
8950 /*                                                                        */
8951 /*    This function retrieves a packet from the BSD raw socket receive    */
8952 /*    queue.                                                              */
8953 /*                                                                        */
8954 /*  INPUT                                                                 */
8955 /*                                                                        */
8956 /*    bsd_socket_ptr                       BSD raw socket                 */
8957 /*    packet_ptr                           Pointer to retrieved packet    */
8958 /*                                                                        */
8959 /*  OUTPUT                                                                */
8960 /*                                                                        */
8961 /*    NX_SUCCESS                           Packet successfully retrieved  */
8962 /*    NX_NO_PACKET                         No packet on receive queue     */
8963 /*    NX_NOT_ENABLED                       Not enabled for raw packets    */
8964 /*                                                                        */
8965 /*  CALLS                                                                 */
8966 /*                                                                        */
8967 /*    None                                                                */
8968 /*                                                                        */
8969 /*  CALLED BY                                                             */
8970 /*                                                                        */
8971 /*    select                              Checks for receive packets      */
8972 /*    recv                                Checks the specified socket for */
8973 /*                                           received packets             */
8974 /*                                                                        */
8975 /*  RELEASE HISTORY                                                       */
8976 /*                                                                        */
8977 /*    DATE              NAME                      DESCRIPTION             */
8978 /*                                                                        */
8979 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8980 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8981 /*                                            resulting in version 6.1    */
8982 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
8983 /*                                            used new API/structs naming,*/
8984 /*                                            resulting in version 6.3.0  */
8985 /*                                                                        */
8986 /**************************************************************************/
nx_bsd_raw_packet_receive(NX_BSD_SOCKET * bsd_socket_ptr,NX_PACKET ** packet_ptr)8987 UINT nx_bsd_raw_packet_receive(NX_BSD_SOCKET *bsd_socket_ptr, NX_PACKET **packet_ptr)
8988 {
8989 
8990 
8991     /* Sanity check. Check this is indeed a raw socket. */
8992     if (!(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET))
8993     {
8994         /* Set the socket error. */
8995         nx_bsd_set_errno(EPROTOTYPE);
8996 
8997         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
8998         return(NX_NOT_ENABLED);
8999     }
9000 
9001     /* Verify this socket is enabled for raw packet processing. */
9002     if (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET)
9003     {
9004 
9005         /* Are there any packets on the socket raw receive queue? */
9006         if (bsd_socket_ptr -> nx_bsd_socket_received_packet != NX_NULL)
9007         {
9008 
9009             /* Yes, return a pointer to the packet at the top of the queue. */
9010             *packet_ptr =  bsd_socket_ptr -> nx_bsd_socket_received_packet;
9011 
9012             /* Update the packet count. */
9013             bsd_socket_ptr -> nx_bsd_socket_received_byte_count -= (*packet_ptr) -> nx_packet_length;
9014             bsd_socket_ptr -> nx_bsd_socket_received_packet_count--;
9015 
9016 
9017             /* Remove this packet from the receive queue and update queue packet pointers. */
9018             bsd_socket_ptr -> nx_bsd_socket_received_packet =  (*packet_ptr) -> nx_packet_queue_next;
9019 
9020             /* If this was the last packet, set the tail pointer to NULL.  */
9021             if (bsd_socket_ptr -> nx_bsd_socket_received_packet == NX_NULL)
9022             {
9023                 bsd_socket_ptr -> nx_bsd_socket_received_packet_tail =  NX_NULL;
9024                 bsd_socket_ptr -> nx_bsd_socket_received_byte_count = 0;
9025                 bsd_socket_ptr -> nx_bsd_socket_received_packet_count = 0;
9026             }
9027         }
9028         else
9029         {
9030 
9031             /* No packets on the queue. Return the NetX Duo status. This is an internal call, so no BSD socket error to report. */
9032             return NX_NO_PACKET;
9033         }
9034     }
9035     else
9036     {
9037         return NX_NOT_ENABLED;
9038     }
9039 
9040     return NX_SUCCESS;
9041 }
9042 
9043 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
9044 
9045 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
9046 /**************************************************************************/
9047 /*                                                                        */
9048 /*  FUNCTION                                               RELEASE        */
9049 /*                                                                        */
9050 /*    nx_bsd_raw_packet_info_extract                      PORTABLE C      */
9051 /*                                                           6.1          */
9052 /*  AUTHOR                                                                */
9053 /*                                                                        */
9054 /*    Yuxin Zhou, Microsoft Corporation                                   */
9055 /*                                                                        */
9056 /*  DESCRIPTION                                                           */
9057 /*                                                                        */
9058 /*    This function extracts the source IP address and interface index    */
9059 /*    from the received packet.                                           */
9060 /*                                                                        */
9061 /*  INPUT                                                                 */
9062 /*                                                                        */
9063 /*    packet_ptr                            Pointer to received raw packet*/
9064 /*    address                               Pointer to sender IP address  */
9065 /*    interface_index                       Pointer to network index      */
9066 /*                                            packet received on          */
9067 /*                                                                        */
9068 /*  OUTPUT                                                                */
9069 /*                                                                        */
9070 /*    NX_SUCCESS                           Successful completion status   */
9071 /*                                                                        */
9072 /*  CALLS                                                                 */
9073 /*                                                                        */
9074 /*    COPY_IPV6_ADDRESS                    Copy IPv6 address              */
9075 /*                                                                        */
9076 /*  CALLED BY                                                             */
9077 /*                                                                        */
9078 /*    Application Code                                                    */
9079 /*                                                                        */
9080 /*  RELEASE HISTORY                                                       */
9081 /*                                                                        */
9082 /*    DATE              NAME                      DESCRIPTION             */
9083 /*                                                                        */
9084 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9085 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9086 /*                                            resulting in version 6.1    */
9087 /*                                                                        */
9088 /**************************************************************************/
nx_bsd_raw_packet_info_extract(NX_PACKET * packet_ptr,NXD_ADDRESS * address,UINT * interface_index)9089 UINT  nx_bsd_raw_packet_info_extract(NX_PACKET *packet_ptr, NXD_ADDRESS *address, UINT *interface_index)
9090 {
9091 
9092 NX_INTERFACE    *if_ptr = NX_NULL;
9093 
9094 
9095 #ifndef NX_DISABLE_IPV4
9096     /* Determine what IP version the packet is. */
9097     if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
9098     {
9099 
9100         NX_IPV4_HEADER *ip_header_ptr;
9101 
9102         /* Set a pointer to the IPv4 header. */
9103         ip_header_ptr = (NX_IPV4_HEADER  *)(packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_IPV4_HEADER));
9104 
9105         /* Fill in the IP address information. */
9106         address -> nxd_ip_version = NX_IP_VERSION_V4;
9107         address -> nxd_ip_address.v4 = ip_header_ptr -> nx_ip_header_source_ip;
9108 
9109         /* Pick up the packet interface. */
9110         if_ptr = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
9111     }
9112 #endif /* NX_DISABLE_IPV4 */
9113 #ifdef FEATURE_NX_IPV6
9114     if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
9115     {
9116 
9117         NX_IPV6_HEADER *ipv6_header_ptr;
9118 
9119         ipv6_header_ptr = (NX_IPV6_HEADER  *)(packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_IPV6_HEADER));
9120 
9121         /* Fill in the IPv6 address information. */
9122         address -> nxd_ip_version = NX_IP_VERSION_V6;
9123 
9124         /* Copy the IPv6 address. */
9125         address -> nxd_ip_address.v6[0] = ipv6_header_ptr -> nx_ip_header_source_ip[0];
9126         address -> nxd_ip_address.v6[1] = ipv6_header_ptr -> nx_ip_header_source_ip[1];
9127         address -> nxd_ip_address.v6[2] = ipv6_header_ptr -> nx_ip_header_source_ip[2];
9128         address -> nxd_ip_address.v6[3] = ipv6_header_ptr -> nx_ip_header_source_ip[3];
9129 
9130         /* Pick up the packet interface. */
9131         if_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
9132     }
9133 #endif
9134 
9135     /* The last piece of information is the packet interface. If the return pointer is NULL we are done! */
9136     if(interface_index == NX_NULL)
9137         return(NX_SUCCESS);
9138 
9139     /* Search for interface index number.  Initialize interface value as
9140        invalid (0xFFFFFFFF).  Once we find valid interface, we will update
9141        the returned value. */
9142     *interface_index = 0xFFFFFFFF;
9143 
9144     if(if_ptr == NX_NULL)
9145     {
9146         /* No interface attached.  Done here, and return success. */
9147         return(NX_SUCCESS);
9148     }
9149 
9150     /* Compute the index by difference of the packet's interface from the primary interface, and dividing by the size. */
9151     *interface_index = if_ptr -> nx_interface_index;
9152 
9153     return(NX_SUCCESS);
9154 }
9155 
9156 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
9157 
9158 /**************************************************************************/
9159 /*                                                                        */
9160 /*  FUNCTION                                               RELEASE        */
9161 /*                                                                        */
9162 /*    nx_bsd_set_socket_timed_wait_callback               PORTABLE C      */
9163 /*                                                           6.1          */
9164 /*  AUTHOR                                                                */
9165 /*                                                                        */
9166 /*    Yuxin Zhou, Microsoft Corporation                                   */
9167 /*                                                                        */
9168 /*  DESCRIPTION                                                           */
9169 /*                                                                        */
9170 /*    This function is called when a BSD TCP socket has closed. If the    */
9171 /*    BSD socket associated with the TCP socket is not enabled for        */
9172 /*    REUSEADDR, this function will put the BSD socket in the TIMED WAIT  */
9173 /*    state.                                                              */
9174 /*                                                                        */
9175 /*    When this time out expires, the BSD socket is removed from the TIME */
9176 /*    WAIT State and available to the host application.                   */
9177 /*                                                                        */
9178 /*    Note: only sockets not enabled with REUSEADDR are placed in the WAIT*/
9179 /*    STATE. All other BSD sockets are immediately available upon closing.*/
9180 /*                                                                        */
9181 /*  INPUT                                                                 */
9182 /*                                                                        */
9183 /*    tcp_socket_ptr                       TCP socket state being closed  */
9184 /*                                                                        */
9185 /*  OUTPUT                                                                */
9186 /*                                                                        */
9187 /*    None                                                                */
9188 /*                                                                        */
9189 /*  CALLS                                                                 */
9190 /*                                                                        */
9191 /*    tx_thread_identify                   Identify socket owning thread  */
9192 /*    tx_mutex_get                         Obtain BSD mutex protection    */
9193 /*    tx_mutex_put                         Release BSD mutex protection   */
9194 /*                                                                        */
9195 /*  CALLED BY                                                             */
9196 /*                                                                        */
9197 /*    NetX                                                                */
9198 /*                                                                        */
9199 /*  RELEASE HISTORY                                                       */
9200 /*                                                                        */
9201 /*    DATE              NAME                      DESCRIPTION             */
9202 /*                                                                        */
9203 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9204 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9205 /*                                            resulting in version 6.1    */
9206 /*                                                                        */
9207 /**************************************************************************/
nx_bsd_socket_timed_wait_callback(NX_TCP_SOCKET * tcp_socket_ptr)9208 VOID  nx_bsd_socket_timed_wait_callback(NX_TCP_SOCKET *tcp_socket_ptr)
9209 {
9210     NX_PARAMETER_NOT_USED(tcp_socket_ptr);
9211 
9212     /* Logic has been removed elsewhere but for compatibility with
9213        NetX we leave this function stub. */
9214 
9215     return;
9216 }
9217 
9218 
9219 
9220 /**************************************************************************/
9221 /*                                                                        */
9222 /*  FUNCTION                                               RELEASE        */
9223 /*                                                                        */
9224 /*    nx_packet_data_extract_offset                       PORTABLE C      */
9225 /*                                                           6.1          */
9226 /*  AUTHOR                                                                */
9227 /*                                                                        */
9228 /*    Yuxin Zhou, Microsoft Corporation                                   */
9229 /*                                                                        */
9230 /*  DESCRIPTION                                                           */
9231 /*                                                                        */
9232 /*    This function copies data from a NetX packet (or packet chain) into */
9233 /*    the supplied user buffer.                                           */
9234 /*                                                                        */
9235 /*    This basically defines the data extract service in the BSD source   */
9236 /*    code if it is not provided in the NetX or NetX Duo library already. */
9237 /*                                                                        */
9238 /*  INPUT                                                                 */
9239 /*                                                                        */
9240 /*    packet_ptr                        Pointer to the source packet      */
9241 /*    buffer_start                      Pointer to destination data area  */
9242 /*    buffer_length                     Size in bytes                     */
9243 /*    bytes_copied                      Number of bytes copied            */
9244 /*                                                                        */
9245 /*  OUTPUT                                                                */
9246 /*                                                                        */
9247 /*    status                            Completion status                 */
9248 /*                                                                        */
9249 /*  CALLS                                                                 */
9250 /*                                                                        */
9251 /*    None                                                                */
9252 /*                                                                        */
9253 /*  CALLED BY                                                             */
9254 /*                                                                        */
9255 /*    Application Code                                                    */
9256 /*                                                                        */
9257 /*  RELEASE HISTORY                                                       */
9258 /*                                                                        */
9259 /*    DATE              NAME                      DESCRIPTION             */
9260 /*                                                                        */
9261 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9262 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
9263 /*                                            verified memcpy use cases,  */
9264 /*                                            resulting in version 6.1    */
9265 /*                                                                        */
9266 /**************************************************************************/
9267 #ifdef NX_BSD_INCLUDE_DATA_EXTRACT_OFFSET
nx_packet_data_extract_offset(NX_PACKET * packet_ptr,ULONG offset,VOID * buffer_start,ULONG buffer_length,ULONG * bytes_copied)9268 UINT  nx_packet_data_extract_offset(NX_PACKET *packet_ptr, ULONG offset, VOID *buffer_start, ULONG buffer_length, ULONG *bytes_copied)
9269 {
9270 
9271 ULONG       remaining_bytes;
9272 UCHAR       *source_ptr;
9273 UCHAR       *destination_ptr;
9274 ULONG       offset_bytes;
9275 #ifndef NX_DISABLE_PACKET_CHAIN
9276 ULONG       packet_fragment_length;
9277 #endif
9278 ULONG       bytes_to_copy;
9279 NX_PACKET   *working_packet_ptr;
9280 
9281     working_packet_ptr =  packet_ptr;
9282 
9283     /* Check for an invalid offset or packet length.  */
9284     if(offset >= working_packet_ptr -> nx_packet_length)
9285     {
9286         /* Note: A zero offset with a packet of zero length is ok. */
9287         if ((offset == 0) && (working_packet_ptr -> nx_packet_length == 0))
9288         {
9289             *bytes_copied = 0;
9290             return(NX_SUCCESS);
9291         }
9292 
9293         /* Otherwise, this is an invalid offset or packet length. */
9294         return(NX_PACKET_OFFSET_ERROR);
9295     }
9296 
9297     /* Initialize the source pointer to NULL.  */
9298     source_ptr =  NX_NULL;
9299 
9300     /* Traverse packet chain to offset.  */
9301     offset_bytes =  offset;
9302 #ifndef NX_DISABLE_PACKET_CHAIN
9303     while (working_packet_ptr)
9304     {
9305         packet_fragment_length =  (working_packet_ptr -> nx_packet_append_ptr - working_packet_ptr -> nx_packet_prepend_ptr) ;
9306 
9307         /* Determine if we are at the offset location fragment in the packet chain  */
9308         if (packet_fragment_length > offset_bytes)
9309         {
9310             /* Setup loop to copy from this packet.  */
9311             source_ptr =  working_packet_ptr -> nx_packet_prepend_ptr + offset_bytes;
9312 
9313             /* Yes, get out of this  loop.  */
9314             break;
9315         }
9316 
9317         /* Decrement the remaining offset bytes*/
9318         offset_bytes = offset_bytes - packet_fragment_length ;
9319 
9320         /* Move to next packet.  */
9321         working_packet_ptr =  working_packet_ptr -> nx_packet_next;
9322     }
9323 #else /* NX_DISABLE_PACKET_CHAIN */
9324 
9325     /* Setup loop to copy from this packet.  */
9326     source_ptr =  working_packet_ptr -> nx_packet_prepend_ptr + offset_bytes;
9327 
9328 #endif /* NX_DISABLE_PACKET_CHAIN */
9329 
9330     /* Check for a valid source pointer.  */
9331     if (source_ptr == NX_NULL)
9332         return(NX_PACKET_OFFSET_ERROR);
9333 
9334     /* Setup the destination pointer.  */
9335     destination_ptr =  buffer_start;
9336     bytes_to_copy =   (packet_ptr->nx_packet_length - offset);
9337 
9338     /* Pickup the amount of bytes to copy.  */
9339     if( bytes_to_copy < buffer_length)
9340     {
9341         *bytes_copied =  bytes_to_copy;     /* the amount of bytes returned to the caller */
9342         remaining_bytes =  bytes_to_copy;   /* for use in the copy loop */
9343     }
9344     else
9345     {
9346         *bytes_copied =  buffer_length;
9347         remaining_bytes =  buffer_length;
9348     }
9349 
9350 #ifndef NX_DISABLE_PACKET_CHAIN
9351     /* Loop to copy bytes from packet(s).  */
9352     while (working_packet_ptr && remaining_bytes)
9353     {
9354 #endif /* NX_DISABLE_PACKET_CHAIN */
9355 
9356         /* Calculate bytes to copy.  */
9357         bytes_to_copy = working_packet_ptr -> nx_packet_append_ptr - source_ptr;
9358         if(remaining_bytes < bytes_to_copy)
9359             bytes_to_copy = remaining_bytes;
9360 
9361         /* Copy data from this packet.  */
9362         memcpy(destination_ptr, source_ptr, bytes_to_copy); /* Use case of memcpy is verified. */
9363 
9364         /* Update the pointers. */
9365         destination_ptr += bytes_to_copy;
9366         remaining_bytes -= bytes_to_copy;
9367 
9368 #ifndef NX_DISABLE_PACKET_CHAIN
9369         /* Move to next packet.  */
9370         working_packet_ptr =  working_packet_ptr -> nx_packet_next;
9371 
9372         /* Check for a next packet.  */
9373         if (working_packet_ptr)
9374         {
9375 
9376             /* Setup new source pointer.  */
9377             source_ptr = working_packet_ptr -> nx_packet_prepend_ptr;
9378         }
9379     }
9380 #endif /* NX_DISABLE_PACKET_CHAIN */
9381 
9382     /* Return successful completion.  */
9383     return(NX_SUCCESS);
9384 
9385 }
9386 #endif /* NX_BSD_INCLUDE_DATA_EXTRACT_OFFSET */
9387 
9388 /**************************************************************************/
9389 /*                                                                        */
9390 /*  FUNCTION                                               RELEASE        */
9391 /*                                                                        */
9392 /*    nx_bsd_timer_entry                                  PORTABLE C      */
9393 /*                                                           6.1          */
9394 /*  AUTHOR                                                                */
9395 /*                                                                        */
9396 /*    Yuxin Zhou, Microsoft Corporation                                   */
9397 /*                                                                        */
9398 /*  DESCRIPTION                                                           */
9399 /*                                                                        */
9400 /*    This function is called when the nx_bsd_socket_wait_timer expires.  */
9401 /*    It signals the BSD thread task to check and decrement the time      */
9402 /*    remaining on all sockets suspended in the wait state.               */
9403 /*                                                                        */
9404 /*  INPUT                                                                 */
9405 /*                                                                        */
9406 /*    info                                 Timer thread data (not used)   */
9407 /*                                                                        */
9408 /*  OUTPUT                                                                */
9409 /*                                                                        */
9410 /*    None                                                                */
9411 /*                                                                        */
9412 /*  CALLS                                                                 */
9413 /*                                                                        */
9414 /*    tx_event_flags_set                   Sets the WAIT event in the BSD */
9415 /*                                              event group               */
9416 /*                                                                        */
9417 /*  CALLED BY                                                             */
9418 /*                                                                        */
9419 /*    ThreadX                                                             */
9420 /*                                                                        */
9421 /*  RELEASE HISTORY                                                       */
9422 /*                                                                        */
9423 /*    DATE              NAME                      DESCRIPTION             */
9424 /*                                                                        */
9425 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9426 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9427 /*                                            resulting in version 6.1    */
9428 /*                                                                        */
9429 /**************************************************************************/
9430 #ifdef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
nx_bsd_timer_entry(ULONG info)9431 VOID  nx_bsd_timer_entry(ULONG info)
9432 {
9433     nx_bsd_timeout_process();
9434 }
9435 #endif
9436 
9437 
9438 /**************************************************************************/
9439 /*                                                                        */
9440 /*  FUNCTION                                               RELEASE        */
9441 /*                                                                        */
9442 /*    nx_bsd_socket_set_inherited_settings                PORTABLE C      */
9443 /*                                                           6.1          */
9444 /*  AUTHOR                                                                */
9445 /*                                                                        */
9446 /*    Yuxin Zhou, Microsoft Corporation                                   */
9447 /*                                                                        */
9448 /*  DESCRIPTION                                                           */
9449 /*                                                                        */
9450 /*    This function applies the socket options of the specified parent    */
9451 /*    (master) socket to the specified child (secondary) socket, if BSD   */
9452 /*    extended socket options are enabled. If they are not, this function */
9453 /*    has no effect.                                                      */
9454 /*                                                                        */
9455 /*  INPUT                                                                 */
9456 /*                                                                        */
9457 /*    master_sock_id                       Source of socket options       */
9458 /*    secondary_sock_id                    Socket inheriting options      */
9459 /*                                                                        */
9460 /*  OUTPUT                                                                */
9461 /*                                                                        */
9462 /*    NX_SUCCESS                          Successful completion           */
9463 /*                                                                        */
9464 /*  CALLS                                                                 */
9465 /*                                                                        */
9466 /*    None                                                                */
9467 /*                                                                        */
9468 /*  CALLED BY                                                             */
9469 /*                                                                        */
9470 /*    ThreadX                                                             */
9471 /*                                                                        */
9472 /*  RELEASE HISTORY                                                       */
9473 /*                                                                        */
9474 /*    DATE              NAME                      DESCRIPTION             */
9475 /*                                                                        */
9476 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9477 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9478 /*                                            resulting in version 6.1    */
9479 /*                                                                        */
9480 /**************************************************************************/
nx_bsd_socket_set_inherited_settings(UINT master_sock_id,UINT secondary_sock_id)9481 UINT nx_bsd_socket_set_inherited_settings(UINT master_sock_id, UINT secondary_sock_id)
9482 {
9483 
9484     /* Update the secondary socket options from the master socket. */
9485     if(nx_bsd_socket_array[master_sock_id].nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING)
9486         nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING;
9487     else
9488         nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING);
9489 
9490     if(nx_bsd_socket_array[master_sock_id].nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR)
9491         nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR;
9492     else
9493         nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR);
9494 
9495 #ifdef NX_ENABLE_TCP_WINDOW_SCALING
9496     nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_maximum =
9497                                                          nx_bsd_socket_array[master_sock_id].nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_maximum;
9498 #endif
9499 
9500 
9501     /* Does this version of NetX Duo support TCP keep alive? */
9502     /* Is NetX Duo currently enabled for TCP keep alive? */
9503 #ifdef NX_ENABLE_TCP_KEEPALIVE
9504 
9505     nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled =
9506                         nx_bsd_socket_array[master_sock_id].nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled;
9507 
9508 #endif /* NX_ENABLE_TCP_KEEPALIVE */
9509 
9510 
9511     return NX_SUCCESS;
9512 }
9513 
9514 
9515 /**************************************************************************/
9516 /*                                                                        */
9517 /*  FUNCTION                                               RELEASE        */
9518 /*                                                                        */
9519 /*    nx_bsd_isspace                                      PORTABLE C      */
9520 /*                                                           6.1          */
9521 /*  AUTHOR                                                                */
9522 /*                                                                        */
9523 /*    Yuxin Zhou, Microsoft Corporation                                   */
9524 /*                                                                        */
9525 /*  DESCRIPTION                                                           */
9526 /*                                                                        */
9527 /*    This function determines if the input character is white space      */
9528 /*    (ascii characters 0x09 - 0x0D or space (0x20).                      */
9529 /*                                                                        */
9530 /*  INPUT                                                                 */
9531 /*                                                                        */
9532 /*    c                                    Input character to examine     */
9533 /*                                                                        */
9534 /*  OUTPUT                                                                */
9535 /*                                                                        */
9536 /*    NX_TRUE                              Input character is white space */
9537 /*    NX_FALSE                             Input character not white space*/
9538 /*                                                                        */
9539 /*  CALLS                                                                 */
9540 /*                                                                        */
9541 /*    None                                                                */
9542 /*                                                                        */
9543 /*  CALLED BY                                                             */
9544 /*                                                                        */
9545 /*    ThreadX                                                             */
9546 /*                                                                        */
9547 /*  RELEASE HISTORY                                                       */
9548 /*                                                                        */
9549 /*    DATE              NAME                      DESCRIPTION             */
9550 /*                                                                        */
9551 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9552 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9553 /*                                            resulting in version 6.1    */
9554 /*                                                                        */
9555 /**************************************************************************/
nx_bsd_isspace(UCHAR c)9556 static UINT nx_bsd_isspace(UCHAR c)
9557 {
9558 
9559     /* Check for horizontal, vertical tabs, carriage return or formfeed characters. */
9560     if ((c >= 0x09) && (c <= 0x0D))
9561     {
9562         return NX_TRUE;
9563     }
9564     /* Check for a single space character*/
9565     else if (c == 20)
9566     {
9567         return NX_TRUE;
9568     }
9569     else
9570         /* Not a white space character. */
9571         return NX_FALSE;
9572 }
9573 
9574 
9575 /**************************************************************************/
9576 /*                                                                        */
9577 /*  FUNCTION                                               RELEASE        */
9578 /*                                                                        */
9579 /*    nx_bsd_islower                                      PORTABLE C      */
9580 /*                                                           6.1          */
9581 /*  AUTHOR                                                                */
9582 /*                                                                        */
9583 /*    Yuxin Zhou, Microsoft Corporation                                   */
9584 /*                                                                        */
9585 /*  DESCRIPTION                                                           */
9586 /*                                                                        */
9587 /*    This function determines if the input character is lower case       */
9588 /*    alphabetic character.                                               */
9589 /*                                                                        */
9590 /*  INPUT                                                                 */
9591 /*                                                                        */
9592 /*    c                                    Input character to examine     */
9593 /*                                                                        */
9594 /*  OUTPUT                                                                */
9595 /*                                                                        */
9596 /*    NX_TRUE                              Input character is lower case  */
9597 /*    NX_FALSE                             Input character not lower case */
9598 /*                                                                        */
9599 /*  CALLS                                                                 */
9600 /*                                                                        */
9601 /*    None                                                                */
9602 /*                                                                        */
9603 /*  CALLED BY                                                             */
9604 /*                                                                        */
9605 /*    ThreadX                                                             */
9606 /*                                                                        */
9607 /*  RELEASE HISTORY                                                       */
9608 /*                                                                        */
9609 /*    DATE              NAME                      DESCRIPTION             */
9610 /*                                                                        */
9611 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9612 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9613 /*                                            resulting in version 6.1    */
9614 /*                                                                        */
9615 /**************************************************************************/
nx_bsd_islower(UCHAR c)9616 static UINT nx_bsd_islower(UCHAR c)
9617 {
9618 
9619     /* Check if characters is any character 'a' through 'z'. */
9620     if ((c >= 0x61) && (c <= 0x7A))
9621     {
9622 
9623         return NX_TRUE;
9624     }
9625     else
9626         return NX_FALSE;
9627 
9628 }
9629 
9630 /**************************************************************************/
9631 /*                                                                        */
9632 /*  FUNCTION                                               RELEASE        */
9633 /*                                                                        */
9634 /*    nx_bsd_isdigit                                      PORTABLE C      */
9635 /*                                                           6.1          */
9636 /*  AUTHOR                                                                */
9637 /*                                                                        */
9638 /*    Yuxin Zhou, Microsoft Corporation                                   */
9639 /*                                                                        */
9640 /*  DESCRIPTION                                                           */
9641 /*                                                                        */
9642 /*    This function determines if the input character is a digit (0-9)    */
9643 /*    Does not include hex digits, (see nx_bsd_isxdigit).                 */
9644 /*                                                                        */
9645 /*  INPUT                                                                 */
9646 /*                                                                        */
9647 /*    c                                    Input character to examine     */
9648 /*                                                                        */
9649 /*  OUTPUT                                                                */
9650 /*                                                                        */
9651 /*    NX_TRUE                              Input character is a digit     */
9652 /*    NX_FALSE                             Input character not a digit    */
9653 /*                                                                        */
9654 /*  CALLS                                                                 */
9655 /*                                                                        */
9656 /*    None                                                                */
9657 /*                                                                        */
9658 /*  CALLED BY                                                             */
9659 /*                                                                        */
9660 /*    ThreadX                                                             */
9661 /*                                                                        */
9662 /*  RELEASE HISTORY                                                       */
9663 /*                                                                        */
9664 /*    DATE              NAME                      DESCRIPTION             */
9665 /*                                                                        */
9666 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9667 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9668 /*                                            resulting in version 6.1    */
9669 /*                                                                        */
9670 /**************************************************************************/
nx_bsd_isdigit(UCHAR c)9671 static UINT nx_bsd_isdigit(UCHAR c)
9672 {
9673 
9674     /* Is the character any digit between 0 and 9? */
9675     if ((c >= 0x30) && (c <= 0x39))
9676     {
9677         return NX_TRUE;
9678     }
9679     else
9680         return NX_FALSE;
9681 }
9682 
9683 
9684 /**************************************************************************/
9685 /*                                                                        */
9686 /*  FUNCTION                                               RELEASE        */
9687 /*                                                                        */
9688 /*    nx_bsd_isxdigit                                     PORTABLE C      */
9689 /*                                                           6.1          */
9690 /*  AUTHOR                                                                */
9691 /*                                                                        */
9692 /*    Yuxin Zhou, Microsoft Corporation                                   */
9693 /*                                                                        */
9694 /*  DESCRIPTION                                                           */
9695 /*                                                                        */
9696 /*    This function determines if the input character is a digit (0-9)    */
9697 /*    or hex digit (A - F, or a-f).  For decimal digits, see              */
9698 /*    nx_bsd_isdigit.                                                     */
9699 /*                                                                        */
9700 /*  INPUT                                                                 */
9701 /*                                                                        */
9702 /*    c                                    Input character to examine     */
9703 /*                                                                        */
9704 /*  OUTPUT                                                                */
9705 /*                                                                        */
9706 /*    NX_TRUE                              Input character is hex digit   */
9707 /*    NX_FALSE                             Input character not hex digit  */
9708 /*                                                                        */
9709 /*  CALLS                                                                 */
9710 /*                                                                        */
9711 /*    None                                                                */
9712 /*                                                                        */
9713 /*  CALLED BY                                                             */
9714 /*                                                                        */
9715 /*    ThreadX                                                             */
9716 /*                                                                        */
9717 /*  RELEASE HISTORY                                                       */
9718 /*                                                                        */
9719 /*    DATE              NAME                      DESCRIPTION             */
9720 /*                                                                        */
9721 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9722 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9723 /*                                            resulting in version 6.1    */
9724 /*                                                                        */
9725 /**************************************************************************/
nx_bsd_isxdigit(UCHAR c)9726 static UINT nx_bsd_isxdigit(UCHAR c)
9727 {
9728 
9729     /* Is the character any digit between 0 - 9? */
9730     if ((c >= 0x30) && (c <= 0x39))
9731     {
9732         return NX_TRUE;
9733     }
9734 
9735     /* Or is the character any base 16 digit A-F? */
9736     if ((c >= 0x41) && (c <= 0x46))
9737     {
9738         return NX_TRUE;
9739     }
9740 
9741     /* Lastly, check if character is any base 16 digit a-f? */
9742     if ((c >= 0x61) && (c <= 0x66))
9743     {
9744         return NX_TRUE;
9745     }
9746     else
9747         return NX_FALSE;
9748 }
9749 
9750 /**************************************************************************/
9751 /*                                                                        */
9752 /*  FUNCTION                                               RELEASE        */
9753 /*                                                                        */
9754 /*    set_errno                                           PORTABLE C      */
9755 /*                                                           6.3.0        */
9756 /*  AUTHOR                                                                */
9757 /*                                                                        */
9758 /*    Yuxin Zhou, Microsoft Corporation                                   */
9759 /*                                                                        */
9760 /*  DESCRIPTION                                                           */
9761 /*                                                                        */
9762 /*    This function sets the error on the current socket (thread) for     */
9763 /*    sockets enabled with BSD extended socket options. For sockets not   */
9764 /*    enabled with extended features, this function has no effect.        */
9765 /*                                                                        */
9766 /*  INPUT                                                                 */
9767 /*                                                                        */
9768 /*    tx_errno                                Socket error status code    */
9769 /*                                                                        */
9770 /*  OUTPUT                                                                */
9771 /*                                                                        */
9772 /*    None                                                                */
9773 /*                                                                        */
9774 /*  CALLS                                                                 */
9775 /*                                                                        */
9776 /*    None                                                                */
9777 /*                                                                        */
9778 /*  CALLED BY                                                             */
9779 /*                                                                        */
9780 /*    ThreadX                                                             */
9781 /*                                                                        */
9782 /*  RELEASE HISTORY                                                       */
9783 /*                                                                        */
9784 /*    DATE              NAME                      DESCRIPTION             */
9785 /*                                                                        */
9786 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9787 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9788 /*                                            resulting in version 6.1    */
9789 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
9790 /*                                            used new API/structs naming,*/
9791 /*                                            resulting in version 6.3.0  */
9792 /*                                                                        */
9793 /**************************************************************************/
nx_bsd_set_errno(INT tx_errno)9794 VOID nx_bsd_set_errno(INT tx_errno)
9795 {
9796 
9797 TX_INTERRUPT_SAVE_AREA
9798 TX_THREAD       *current_thread_ptr;
9799 
9800 
9801       TX_DISABLE
9802 
9803       current_thread_ptr =  tx_thread_identify();
9804       current_thread_ptr -> bsd_errno = tx_errno;
9805 
9806       TX_RESTORE
9807 
9808       return;
9809 }
9810 
9811 /**************************************************************************/
9812 /*                                                                        */
9813 /*  FUNCTION                                               RELEASE        */
9814 /*                                                                        */
9815 /*    get_errno                                           PORTABLE C      */
9816 /*                                                           6.1          */
9817 /*  AUTHOR                                                                */
9818 /*                                                                        */
9819 /*    Yuxin Zhou, Microsoft Corporation                                   */
9820 /*                                                                        */
9821 /*  DESCRIPTION                                                           */
9822 /*                                                                        */
9823 /*    This function retrieves the error on the current socket (thread) for*/
9824 /*    sockets enabled with BSD extended socket options. For sockets not   */
9825 /*    enabled with extended features, this function has no effect.        */
9826 /*                                                                        */
9827 /*  INPUT                                                                 */
9828 /*                                                                        */
9829 /*    None                                                                */
9830 /*                                                                        */
9831 /*  OUTPUT                                                                */
9832 /*                                                                        */
9833 /*    Socket error status code                                            */
9834 /*                                                                        */
9835 /*  CALLS                                                                 */
9836 /*                                                                        */
9837 /*    None                                                                */
9838 /*                                                                        */
9839 /*  CALLED BY                                                             */
9840 /*                                                                        */
9841 /*    ThreadX                                                             */
9842 /*                                                                        */
9843 /*  RELEASE HISTORY                                                       */
9844 /*                                                                        */
9845 /*    DATE              NAME                      DESCRIPTION             */
9846 /*                                                                        */
9847 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9848 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9849 /*                                            resulting in version 6.1    */
9850 /*                                                                        */
9851 /**************************************************************************/
_nxd_get_errno()9852 INT _nxd_get_errno()
9853 {
9854 
9855 TX_INTERRUPT_SAVE_AREA
9856 INT val;
9857 TX_THREAD       *current_thread_ptr;
9858 
9859 
9860     TX_DISABLE
9861 
9862     current_thread_ptr =  tx_thread_identify();
9863     val = current_thread_ptr -> bsd_errno;
9864 
9865     TX_RESTORE
9866 
9867     return (val);
9868 }
9869 
9870 
9871 /**************************************************************************/
9872 /*                                                                        */
9873 /*  FUNCTION                                               RELEASE        */
9874 /*                                                                        */
9875 /*    nx_bsd_select_wakeup                                PORTABLE C      */
9876 /*                                                           6.3.0        */
9877 /*  AUTHOR                                                                */
9878 /*                                                                        */
9879 /*    Yuxin Zhou, Microsoft Corporation                                   */
9880 /*                                                                        */
9881 /*  DESCRIPTION                                                           */
9882 /*                                                                        */
9883 /*    This function checks the suspend list for a given socket being      */
9884 /*    readable or writeable.                                              */
9885 /*                                                                        */
9886 /*  INPUT                                                                 */
9887 /*                                                                        */
9888 /*    sock_id                               BSD socket ID                 */
9889 /*    fd_sets                               The FD set to check           */
9890 /*                                                                        */
9891 /*  OUTPUT                                                                */
9892 /*                                                                        */
9893 /*    None                                                                */
9894 /*                                                                        */
9895 /*  CALLS                                                                 */
9896 /*                                                                        */
9897 /*    FD_ZERO                               Zeros out an FD Set           */
9898 /*    FD_SET                                Set a socket in the FDSET     */
9899 /*    TX_DISABLE                            Disable Interrupt             */
9900 /*    TX_RESTORE                            Enable Interrupt              */
9901 /*    tx_event_flags_set                    Set an event flag             */
9902 /*                                                                        */
9903 /*  CALLED BY                                                             */
9904 /*                                                                        */
9905 /*    nx_bsd_timeout_process                                              */
9906 /*    nx_bsd_tcp_receive_notify                                           */
9907 /*    nx_bsd_tcp_establish_notify                                         */
9908 /*    nx_bsd_tcp_socket_disconnect_notify                                 */
9909 /*    nx_bsd_raw_receive_notify                                           */
9910 /*    nx_bsd_udp_packet_received                                          */
9911 /*                                                                        */
9912 /*  RELEASE HISTORY                                                       */
9913 /*                                                                        */
9914 /*    DATE              NAME                      DESCRIPTION             */
9915 /*                                                                        */
9916 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9917 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9918 /*                                            resulting in version 6.1    */
9919 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
9920 /*                                            used new API/structs naming,*/
9921 /*                                            resulting in version 6.3.0  */
9922 /*                                                                        */
9923 /**************************************************************************/
nx_bsd_select_wakeup(UINT sock_id,UINT fd_sets)9924 static VOID nx_bsd_select_wakeup(UINT sock_id, UINT fd_sets)
9925 {
9926 TX_INTERRUPT_SAVE_AREA
9927 nx_bsd_fd_set           local_fd;
9928 TX_THREAD               *suspended_thread;
9929 ULONG                   suspended_count;
9930 ULONG                   original_suspended_count;
9931 NX_BSD_SOCKET_SUSPEND   *suspend_info;
9932 
9933 
9934     /* At this point the thread should NOT own the IP mutex, and it must own the
9935        BSD mutex. */
9936 
9937 
9938     NX_BSD_FD_ZERO(&local_fd);
9939     NX_BSD_FD_SET((INT)sock_id + NX_BSD_SOCKFD_START, &local_fd);
9940 
9941     /* Disable interrupts temporarily.  */
9942     TX_DISABLE
9943 
9944     /* Setup the head pointer and the count.  */
9945     suspended_thread =   nx_bsd_events.tx_event_flags_group_suspension_list;
9946     suspended_count =    nx_bsd_events.tx_event_flags_group_suspended_count;
9947 
9948     /* Save the original suspended count.  */
9949     original_suspended_count =  suspended_count;
9950 
9951     /* Loop to examine all threads suspended on select via the BSD event flag group.  */
9952     while (suspended_count--)
9953     {
9954 
9955         /* Determine if this thread is suspended on select.  */
9956         if (suspended_thread -> tx_thread_suspend_info == NX_BSD_SELECT_EVENT)
9957         {
9958 
9959             /* Yes, this thread is suspended on select.  */
9960 
9961             /* Pickup a pointer to its select suspend structure.  */
9962             suspend_info =  (NX_BSD_SOCKET_SUSPEND *) suspended_thread -> tx_thread_additional_suspend_info;
9963 
9964             /* Now determine if this thread was waiting for this socket.  */
9965             if ((fd_sets & FDSET_READ) && (NX_BSD_FD_ISSET((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_read_fd_set)))
9966             {
9967 
9968                 /* Copy the local fd over so that the return shows the receive socket.  */
9969                 suspend_info -> nx_bsd_socket_suspend_read_fd_set = local_fd;
9970 
9971                 /* Adjust the suspension type so that the event flag set below will wakeup the thread
9972                    selecting.  */
9973                 suspended_thread -> tx_thread_suspend_info =  NX_BSD_RECEIVE_EVENT;
9974             }
9975 
9976             /* Now determine if this thread was waiting for this socket.  */
9977             if ((fd_sets & FDSET_WRITE) && (NX_BSD_FD_ISSET((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_write_fd_set)))
9978             {
9979 
9980                 /* Copy the local fd over so that the return shows the receive socket.  */
9981                 suspend_info -> nx_bsd_socket_suspend_write_fd_set = local_fd;
9982 
9983                 /* Adjust the suspension type so that the event flag set below will wakeup the thread
9984                    selecting.  */
9985                 suspended_thread -> tx_thread_suspend_info =  NX_BSD_RECEIVE_EVENT;
9986             }
9987 
9988             /* Now determine if this thread was waiting for this socket.  */
9989             if ((fd_sets & FDSET_EXCEPTION) && (NX_BSD_FD_ISSET((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_exception_fd_set)))
9990             {
9991 
9992                 /* Copy the local fd over so that the return shows the receive socket.  */
9993                 suspend_info -> nx_bsd_socket_suspend_exception_fd_set = local_fd;
9994 
9995                 /* Adjust the suspension type so that the event flag set below will wakeup the thread
9996                    selecting.  */
9997                 suspended_thread -> tx_thread_suspend_info =  NX_BSD_RECEIVE_EVENT;
9998             }
9999 
10000             /* Clear FD that is not set. */
10001             if (suspended_thread -> tx_thread_suspend_info == NX_BSD_RECEIVE_EVENT)
10002             {
10003                 if (!(fd_sets & FDSET_READ) && (NX_BSD_FD_ISSET((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_read_fd_set)))
10004                 {
10005 
10006                     /* Clear read FD. */
10007                     NX_BSD_FD_CLR((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_read_fd_set);
10008                 }
10009 
10010                 if (!(fd_sets & FDSET_WRITE) && (NX_BSD_FD_ISSET((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_write_fd_set)))
10011                 {
10012 
10013                     /* Clear write FD. */
10014                     NX_BSD_FD_CLR((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_write_fd_set);
10015                 }
10016 
10017                 if (!(fd_sets & FDSET_EXCEPTION) && (NX_BSD_FD_ISSET((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_exception_fd_set)))
10018                 {
10019 
10020                     /* Clear exception FD. */
10021                     NX_BSD_FD_CLR((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_exception_fd_set);
10022                 }
10023             }
10024         }
10025 
10026         /* Now move to the next event.  */
10027         suspended_thread =  suspended_thread -> tx_thread_suspended_next;
10028 
10029         /* Restore interrupts.  */
10030         TX_RESTORE
10031 
10032         /* Disable interrupts again.  */
10033         TX_DISABLE
10034 
10035         /* Determine if something changes on the suspension list... this could have happened if there
10036            was a timeout or a wait abort on the thread.  */
10037         if (original_suspended_count != nx_bsd_events.tx_event_flags_group_suspended_count)
10038         {
10039 
10040             /* Something changed, so simply restart the search.  */
10041 
10042             /* Setup the head pointer and the count.  */
10043             suspended_thread =   nx_bsd_events.tx_event_flags_group_suspension_list;
10044             suspended_count =    nx_bsd_events.tx_event_flags_group_suspended_count;
10045 
10046             /* Save the original suspended count.  */
10047             original_suspended_count =  suspended_count;
10048         }
10049     }
10050 
10051     /* Restore interrupts.  */
10052     TX_RESTORE
10053 
10054     /* Wakeup all threads that are attempting to perform a receive or that had their select satisfied.  */
10055     tx_event_flags_set(&nx_bsd_events, NX_BSD_RECEIVE_EVENT, TX_OR);
10056 
10057     return;
10058 
10059 }
10060 
10061 /**************************************************************************/
10062 /*                                                                        */
10063 /*  FUNCTION                                               RELEASE        */
10064 /*                                                                        */
10065 /*    nx_bsd_set_error_code                               PORTABLE C      */
10066 /*                                                           6.3.0        */
10067 /*  AUTHOR                                                                */
10068 /*                                                                        */
10069 /*    Yuxin Zhou, Microsoft Corporation                                   */
10070 /*                                                                        */
10071 /*  DESCRIPTION                                                           */
10072 /*                                                                        */
10073 /*    This is sets the BSD error code based on NetX Duo API return code   */
10074 /*                                                                        */
10075 /*  INPUT                                                                 */
10076 /*                                                                        */
10077 /*    bsd_socket_ptr                        Pointer to the BSD socket     */
10078 /*    status_code                           NetX Duo API return code      */
10079 /*                                                                        */
10080 /*  OUTPUT                                                                */
10081 /*                                                                        */
10082 /*    None                                                                */
10083 /*                                                                        */
10084 /*  CALLS                                                                 */
10085 /*                                                                        */
10086 /*    set_errno                             Sets the BSD errno            */
10087 /*                                                                        */
10088 /*  CALLED BY                                                             */
10089 /*                                                                        */
10090 /*    connect                                                             */
10091 /*    bind                                                                */
10092 /*                                                                        */
10093 /*  RELEASE HISTORY                                                       */
10094 /*                                                                        */
10095 /*    DATE              NAME                      DESCRIPTION             */
10096 /*                                                                        */
10097 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10098 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10099 /*                                            resulting in version 6.1    */
10100 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
10101 /*                                            used new API/structs naming,*/
10102 /*                                            resulting in version 6.3.0  */
10103 /*                                                                        */
10104 /**************************************************************************/
nx_bsd_set_error_code(NX_BSD_SOCKET * bsd_socket_ptr,UINT status_code)10105 static VOID nx_bsd_set_error_code(NX_BSD_SOCKET *bsd_socket_ptr, UINT status_code)
10106 {
10107     switch(status_code)
10108     {
10109         case NX_NOT_CLOSED:
10110             /* TCP connection is not closed state. */
10111             nx_bsd_set_errno(EISCONN);
10112             break;
10113 
10114         case NX_PTR_ERROR:
10115         case NX_INVALID_PORT:
10116             /* Invalid arguement. */
10117             nx_bsd_set_errno(EINVAL);
10118             break;
10119 
10120         case NX_MAX_LISTEN:
10121             nx_bsd_set_errno(ENOBUFS);
10122             break;
10123 
10124         case NX_PORT_UNAVAILABLE:
10125         case NX_NO_FREE_PORTS:
10126             nx_bsd_set_errno(EADDRNOTAVAIL);
10127             break;
10128 
10129         case NX_ALREADY_BOUND:
10130             nx_bsd_set_errno(EINVAL);
10131             break;
10132 
10133         case NX_WAIT_ABORTED:
10134             nx_bsd_set_errno(ETIMEDOUT);
10135             break;
10136 
10137         case NX_NOT_CONNECTED:
10138             /* NX TCP connect service may return NX_NOT_CONNECTED if the timeout is WAIT_FOREVER. */
10139             nx_bsd_set_errno(ECONNREFUSED);
10140             break;
10141 
10142         case NX_IN_PROGRESS:
10143             /* The NetX "in progress" status is the equivalent of the non blocking BSD socket waiting
10144                to connect. This can only happen if timeout is NX_NO_WAIT.*/
10145             if (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING)
10146             {
10147                 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
10148                 nx_bsd_set_errno(EINPROGRESS);
10149             }
10150             else
10151                 nx_bsd_set_errno(EINTR);
10152             break;
10153 
10154         case NX_INVALID_INTERFACE:
10155         case NX_IP_ADDRESS_ERROR:
10156             nx_bsd_set_errno(ENETUNREACH);
10157             break;
10158 
10159         case NX_NOT_ENABLED:
10160             nx_bsd_set_errno(EPROTONOSUPPORT);
10161             break;
10162 
10163         case NX_NOT_BOUND:
10164         case NX_DUPLICATE_LISTEN:
10165         default:
10166             nx_bsd_set_errno(EINVAL);
10167             break;
10168     }
10169 
10170     return;
10171 }
10172 
10173 /**************************************************************************/
10174 /*                                                                        */
10175 /*  FUNCTION                                               RELEASE        */
10176 /*                                                                        */
10177 /*    nx_bsd_udp_packet_received                          PORTABLE C      */
10178 /*                                                           6.1          */
10179 /*  AUTHOR                                                                */
10180 /*                                                                        */
10181 /*    Yuxin Zhou, Microsoft Corporation                                   */
10182 /*                                                                        */
10183 /*  DESCRIPTION                                                           */
10184 /*                                                                        */
10185 /*    This is executed as part of the UDP packet receive callback         */
10186 /*    function.                                                           */
10187 /*                                                                        */
10188 /*    This routine puts an incoming UDP packet into the appropriate       */
10189 /*    UDP BSD socket, taking into consideration that multiple BSD sockets */
10190 /*    may be mapped to the same NetX Duo UDP socket.                      */
10191 /*                                                                        */
10192 /*  INPUT                                                                 */
10193 /*                                                                        */
10194 /*    sockID                                The BSD socket descriptor     */
10195 /*    packet_ptr                            The incoming UDP packet       */
10196 /*                                                                        */
10197 /*  OUTPUT                                                                */
10198 /*                                                                        */
10199 /*    None                                                                */
10200 /*                                                                        */
10201 /*  CALLS                                                                 */
10202 /*                                                                        */
10203 /*    nx_packet_release                     Release a packet that is not  */
10204 /*                                            received by any sockets.    */
10205 /*    nx_bsd_select_wakeup                  Wake up any asychronous       */
10206 /*                                            receive call                */
10207 /*                                                                        */
10208 /*  CALLED BY                                                             */
10209 /*                                                                        */
10210 /*    nx_bsd_udp_receive_notify                                           */
10211 /*                                                                        */
10212 /*  RELEASE HISTORY                                                       */
10213 /*                                                                        */
10214 /*    DATE              NAME                      DESCRIPTION             */
10215 /*                                                                        */
10216 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10217 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10218 /*                                            resulting in version 6.1    */
10219 /*                                                                        */
10220 /**************************************************************************/
nx_bsd_udp_packet_received(INT sockID,NX_PACKET * packet_ptr)10221 static VOID nx_bsd_udp_packet_received(INT sockID, NX_PACKET *packet_ptr)
10222 {
10223 
10224 NX_BSD_SOCKET *bsd_ptr;
10225 ULONG          addr_family;
10226 NX_BSD_SOCKET *exact_match = NX_NULL;
10227 NX_BSD_SOCKET *receiver_match = NX_NULL;
10228 NX_BSD_SOCKET *wildcard_match = NX_NULL;
10229 NX_INTERFACE   *interface_ptr;
10230 
10231 
10232     bsd_ptr = &nx_bsd_socket_array[sockID];
10233 
10234 #ifndef NX_DISABLE_IPV4
10235     if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
10236     {
10237         addr_family = AF_INET;
10238         interface_ptr = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
10239     }
10240     else
10241 #endif /* NX_DISABLE_IPV4 */
10242 #ifdef FEATURE_NX_IPV6
10243     if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
10244     {
10245         addr_family = AF_INET6;
10246         interface_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
10247     }
10248     else
10249 #endif /* FEATURE_NX_IPV6 */
10250     {
10251 
10252         /* Invalid version.  Release the packet and return. */
10253         nx_packet_release(packet_ptr);
10254 
10255         return;
10256     }
10257 
10258     /* Start the search for the BSD socket we received this packet on from current input socket ID.  */
10259     bsd_ptr = &nx_bsd_socket_array[sockID];
10260 
10261     do
10262     {
10263         /* Skip the sockets with different address family. */
10264         if(bsd_ptr -> nx_bsd_socket_family == addr_family)
10265         {
10266             /* bsd_ptr points to a related UDP socket. */
10267             if(bsd_ptr -> nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
10268             {
10269                 wildcard_match = bsd_ptr;
10270             }
10271             else if(((ULONG)(interface_ptr) == bsd_ptr -> nx_bsd_socket_local_bind_interface) ||
10272                     ((ULONG)(packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr) == bsd_ptr -> nx_bsd_socket_local_bind_interface))
10273             {
10274 
10275                 receiver_match = bsd_ptr;
10276             }
10277             else
10278             {
10279 
10280                 /* Does not match the local interface. Move to the next entry. */
10281                 bsd_ptr = bsd_ptr -> nx_bsd_socket_next;
10282                 continue;
10283             }
10284 
10285             /* At this point this socket is either a wildcard match or a receiver match. */
10286 
10287             /* If the socket is connected, we check for sender's address match. */
10288             if(bsd_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
10289             {
10290 
10291                 nxd_udp_source_extract(packet_ptr,
10292                                        &bsd_ptr -> nx_bsd_socket_source_ip_address,
10293                                        (UINT *)&bsd_ptr -> nx_bsd_socket_source_port);
10294 
10295 #ifndef NX_DISABLE_IPV4
10296                 if(bsd_ptr -> nx_bsd_socket_family == AF_INET)
10297                 {
10298 
10299                     /* Now we can check for an exact match based on sender IP address and port. */
10300                     if((bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v4 ==
10301                         bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v4) &&
10302                        (bsd_ptr -> nx_bsd_socket_source_port ==
10303                         bsd_ptr -> nx_bsd_socket_peer_port))
10304                     {
10305                         exact_match = bsd_ptr;
10306                     }
10307                 }
10308 #endif /* NX_DISABLE_IPV4 */
10309 #ifdef FEATURE_NX_IPV6
10310                 if(bsd_ptr -> nx_bsd_socket_family == AF_INET6)
10311                 {
10312 
10313                     /* Now we can check for an exact match based on sender IP address and port. */
10314                     if((bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[0] ==
10315                         bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[0]) &&
10316                        (bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[1] ==
10317                         bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[1]) &&
10318                        (bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[2] ==
10319                         bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[2]) &&
10320                        (bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[3] ==
10321                         bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[3]) &&
10322                        (bsd_ptr -> nx_bsd_socket_source_port ==
10323                         bsd_ptr -> nx_bsd_socket_peer_port))
10324                     {
10325 
10326                         exact_match = bsd_ptr;
10327                     }
10328                 }
10329 #endif
10330 
10331                 if(exact_match != NX_NULL)
10332                     break;
10333 
10334                 if(receiver_match != NX_NULL)
10335                     receiver_match = NX_NULL;
10336 
10337                 if(wildcard_match != NX_NULL)
10338                     wildcard_match = NX_NULL;
10339             }
10340         }
10341 
10342         /* Move to the next entry. */
10343         bsd_ptr = bsd_ptr -> nx_bsd_socket_next;
10344 
10345     }while(bsd_ptr != &nx_bsd_socket_array[sockID]);
10346 
10347     /* Let bsd_ptr point to the matched socket. */
10348     if(exact_match != NX_NULL)
10349         bsd_ptr = exact_match;
10350     else if(receiver_match != NX_NULL)
10351         bsd_ptr = receiver_match;
10352     else if(wildcard_match != NX_NULL)
10353         bsd_ptr = wildcard_match;
10354     else
10355     {
10356         /* This packet is not for any of the BSD sockets. Release the packet and we are done. */
10357         nx_packet_release(packet_ptr);
10358 
10359         return;
10360     }
10361 
10362     /* Move the packet to the socket internal receive queue. */
10363 
10364     if(bsd_ptr -> nx_bsd_socket_received_byte_count_max &&
10365        (bsd_ptr -> nx_bsd_socket_received_byte_count >= bsd_ptr -> nx_bsd_socket_received_byte_count_max))
10366     {
10367 
10368         /* Receive buffer is full.  Release the packet and return. */
10369         nx_packet_release(packet_ptr);
10370 
10371         return;
10372     }
10373 
10374     /* Drop the packet if the receive queue exceeds max depth.*/
10375     if(bsd_ptr -> nx_bsd_socket_received_packet_count >=
10376        bsd_ptr -> nx_bsd_socket_received_packet_count_max)
10377     {
10378 
10379         /* Receive buffer is full.  Release the packet and return. */
10380         nx_packet_release(packet_ptr);
10381 
10382         return;
10383     }
10384     if(bsd_ptr -> nx_bsd_socket_received_packet)
10385     {
10386         bsd_ptr -> nx_bsd_socket_received_packet_tail -> nx_packet_queue_next = packet_ptr;
10387     }
10388     else
10389     {
10390 
10391         bsd_ptr -> nx_bsd_socket_received_packet = packet_ptr;
10392         bsd_ptr -> nx_bsd_socket_received_packet_offset = 0;
10393     }
10394 
10395     bsd_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
10396     bsd_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
10397     bsd_ptr -> nx_bsd_socket_received_packet_count++;
10398 
10399     nx_bsd_select_wakeup((UINT)(bsd_ptr -> nx_bsd_socket_id), FDSET_READ);
10400 
10401     return;
10402 }
10403 
10404 /**************************************************************************/
10405 /*                                                                        */
10406 /*  FUNCTION                                               RELEASE        */
10407 /*                                                                        */
10408 /*    nx_bsd_tcp_syn_received_notify                      PORTABLE C      */
10409 /*                                                           6.1          */
10410 /*  AUTHOR                                                                */
10411 /*                                                                        */
10412 /*    Yuxin Zhou, Microsoft Corporation                                   */
10413 /*                                                                        */
10414 /*  DESCRIPTION                                                           */
10415 /*                                                                        */
10416 /*    This function checks if the socket has a connection request.        */
10417 /*                                                                        */
10418 /*  INPUT                                                                 */
10419 /*                                                                        */
10420 /*    socket_ptr                           Socket receiving the packet    */
10421 /*    packet_ptr                           Pointer to the received packet */
10422 /*                                                                        */
10423 /*  OUTPUT                                                                */
10424 /*                                                                        */
10425 /*    0                                     Not a valid match             */
10426 /*    1                                     Valid match found             */
10427 /*                                                                        */
10428 /*  CALLS                                                                 */
10429 /*                                                                        */
10430 /*    None                                                                */
10431 /*                                                                        */
10432 /*  CALLED BY                                                             */
10433 /*                                                                        */
10434 /*    NetX Duo                                                            */
10435 /*                                                                        */
10436 /*  RELEASE HISTORY                                                       */
10437 /*                                                                        */
10438 /*    DATE              NAME                      DESCRIPTION             */
10439 /*                                                                        */
10440 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10441 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10442 /*                                            resulting in version 6.1    */
10443 /*                                                                        */
10444 /**************************************************************************/
nx_bsd_tcp_syn_received_notify(NX_TCP_SOCKET * socket_ptr,NX_PACKET * packet_ptr)10445 static UINT  nx_bsd_tcp_syn_received_notify(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr)
10446 {
10447 
10448 UINT            bsd_socket_index;
10449 INT             i;
10450 INT             sockID_find;
10451 ULONG           addr_family;
10452 INT             search_index;
10453 INT             receiver_match = NX_BSD_MAX_SOCKETS;
10454 INT             wildcard_match = NX_BSD_MAX_SOCKETS;
10455 NX_BSD_SOCKET  *bsd_socket_ptr;
10456 NX_INTERFACE   *interface_ptr;
10457 
10458 
10459     bsd_socket_index = (UINT)socket_ptr -> nx_tcp_socket_reserved_ptr;
10460 
10461     if(bsd_socket_index >= NX_BSD_MAX_SOCKETS)
10462     {
10463 
10464         /* Bad socket index... simply return!  */
10465         return(NX_FALSE);
10466     }
10467 
10468     nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
10469 
10470 #ifndef NX_DISABLE_IPV4
10471     if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
10472     {
10473         addr_family = AF_INET;
10474     }
10475     else
10476 #endif /* NX_DISABLE_IPV4 */
10477     {
10478         addr_family = AF_INET6;
10479     }
10480 
10481     /* Start the search at the position of the input socket. */
10482     search_index = (INT)bsd_socket_index;
10483 
10484     /* Get the packet interface. */
10485 #ifdef FEATURE_NX_IPV6
10486     if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
10487 #endif /* FEATURE_NX_IPV6 */
10488         interface_ptr = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
10489 #ifdef FEATURE_NX_IPV6
10490     else if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
10491         interface_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
10492     else
10493         return (NX_FALSE);
10494 #endif /* FEATURE_NX_IPV6 */
10495 
10496     for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
10497     {
10498 
10499         bsd_socket_ptr = &nx_bsd_socket_array[search_index];
10500 
10501         /* Skip the unrelated sockets. */
10502         if((bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP) &&
10503            (bsd_socket_ptr -> nx_bsd_socket_family == addr_family) &&
10504            ((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED) == 0) &&
10505            (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) &&
10506            (bsd_socket_ptr -> nx_bsd_socket_local_port == socket_ptr -> nx_tcp_socket_port) &&
10507            (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
10508         {
10509 
10510             if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
10511             {
10512 
10513                 wildcard_match = search_index;
10514             }
10515             else if(((ULONG)(interface_ptr) == bsd_socket_ptr -> nx_bsd_socket_local_bind_interface) ||
10516                     ((ULONG)(packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr) == bsd_socket_ptr -> nx_bsd_socket_local_bind_interface))
10517             {
10518 
10519                 receiver_match = search_index;
10520 
10521                 /* Found a receiver match, which is a tighter match than the wildcard match.
10522                    So we can get out of the loop. */
10523                 break;
10524             }
10525         }
10526 
10527         /*  Move to the next entry. */
10528         search_index++;
10529 
10530         if(search_index >= NX_BSD_MAX_SOCKETS)
10531             search_index = 0;
10532     }
10533 
10534     if(receiver_match != NX_BSD_MAX_SOCKETS)
10535         sockID_find = receiver_match;
10536     else if(wildcard_match != NX_BSD_MAX_SOCKETS)
10537         sockID_find = wildcard_match;
10538     else
10539     {
10540 
10541         /* No match found.  Simply return .*/
10542         return(NX_FALSE);
10543     }
10544 
10545     /*  Found the listening master socket.  Update the master socket ID of the input socket. */
10546     nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_union_id.nx_bsd_socket_master_socket_id = sockID_find;
10547 
10548     return(NX_TRUE);
10549 }
10550 
10551 /**************************************************************************/
10552 /*                                                                        */
10553 /*  FUNCTION                                               RELEASE        */
10554 /*                                                                        */
10555 /*    nx_bsd_tcp_create_listen_socket                     PORTABLE C      */
10556 /*                                                           6.3.0        */
10557 /*  AUTHOR                                                                */
10558 /*                                                                        */
10559 /*    Yuxin Zhou, Microsoft Corporation                                   */
10560 /*                                                                        */
10561 /*  DESCRIPTION                                                           */
10562 /*                                                                        */
10563 /*    This routine sets up the input socket as a listen socket.           */
10564 /*                                                                        */
10565 /*  INPUT                                                                 */
10566 /*                                                                        */
10567 /*    master_sockid                        Index to the master socket     */
10568 /*    backlog                              Size of the socket listen queue*/
10569 /*                                                                        */
10570 /*  OUTPUT                                                                */
10571 /*                                                                        */
10572 /*    NX_SOC_OK                             Successfully set up socket    */
10573 /*    NX_SOC_ERROR                          Error setting up the socket   */
10574 /*                                                                        */
10575 /*  CALLS                                                                 */
10576 /*                                                                        */
10577 /*    socket                                Allocate a BSD socket         */
10578 /*    nx_bsd_socket_set_inherited_settings  Apply master socket options   */
10579 /*    nx_tcp_server_socket_listen           Enable the socket to listen   **/
10580 /*    nx_tcp_server_socket_accept           Wait for connection request   */
10581 /*    nx_tcp_server_socket_relisten         Reset the socket to listen    */
10582 /*                                                                        */
10583 /*  CALLED BY                                                             */
10584 /*                                                                        */
10585 /*    NetX Duo                                                            */
10586 /*                                                                        */
10587 /*  RELEASE HISTORY                                                       */
10588 /*                                                                        */
10589 /*    DATE              NAME                      DESCRIPTION             */
10590 /*                                                                        */
10591 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10592 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10593 /*                                            resulting in version 6.1    */
10594 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
10595 /*                                            used new API/structs naming,*/
10596 /*                                            resulting in version 6.3.0  */
10597 /*                                                                        */
10598 /**************************************************************************/
nx_bsd_tcp_create_listen_socket(INT master_sockid,INT backlog)10599 static INT nx_bsd_tcp_create_listen_socket(INT master_sockid, INT backlog)
10600 {
10601 
10602 INT                 i;
10603 UINT                status;
10604 UINT                local_port;
10605 NX_BSD_SOCKET       *master_socket_ptr = &nx_bsd_socket_array[master_sockid];
10606 NX_BSD_SOCKET       *bsd_secondary_socket;
10607 NX_BSD_SOCKET       *bsd_socket_ptr;
10608 NX_TCP_SOCKET       *sec_socket_ptr;
10609 INT                 secondary_sockID = NX_BSD_MAX_SOCKETS;
10610 
10611 
10612     /* This is called from BSD internal code so the BSD mutex is obtained. */
10613 
10614     /* Search through the sockets to find a master socket that is listening on the same port. */
10615     for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
10616     {
10617 
10618         /* Skip the entry if it is not master socket */
10619         if((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) == 0)
10620             continue;
10621 
10622         /* Skip the current master socket. */
10623         if(i == master_sockid)
10624             continue;
10625 
10626         /* Skip the entry if it is not TCP */
10627         if(nx_bsd_socket_array[i].nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
10628             continue;
10629 
10630         /* Skip the entry if the the secondary socket id field is not valid. */
10631         if(nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id == NX_BSD_MAX_SOCKETS)
10632             continue;
10633 
10634         /* Check if another master socket is listening on the same port.  */
10635         if((nx_bsd_socket_array[i].nx_bsd_socket_local_port == master_socket_ptr -> nx_bsd_socket_local_port) &&
10636            (nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id
10637             != (master_socket_ptr -> nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id)) &&
10638            (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN))
10639         {
10640 
10641             /* This one is. Point to the same secondary socket. */
10642             (master_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id =
10643               nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id;
10644             master_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ENABLE_LISTEN;
10645             master_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET);
10646             master_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_client_type =  NX_FALSE;
10647             master_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_SERVER_MASTER_SOCKET;
10648 
10649             return(NX_SOC_OK);
10650         }
10651     }
10652 
10653     /* Did not find an existing master socket for listening. */
10654 
10655     /* Check for a valid backlog. */
10656     if(backlog)
10657     {
10658 
10659         /* Check backlog argument is within limits.  */
10660         if (backlog > NX_BSD_MAX_LISTEN_BACKLOG)
10661         {
10662 
10663             /* Error, invalid backlog.  */
10664             /* Set the socket error if extended socket options enabled. */
10665             nx_bsd_set_errno(ENOBUFS);
10666 
10667             /* Return error code.  */
10668             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
10669             return(NX_SOC_ERROR);
10670         }
10671     }
10672 
10673     /* Now create a dedicated secondary socket to listen for next client connection.  */
10674     secondary_sockID =  nx_bsd_socket((INT)(master_socket_ptr -> nx_bsd_socket_family), SOCK_STREAM, IPPROTO_TCP);
10675 
10676     /* Determine if there was an error.  */
10677     if (secondary_sockID == NX_SOC_ERROR)
10678     {
10679 
10680         /* Secondary socket create failed. Note: The socket thread error is set in socket().  */
10681         nx_bsd_set_errno(ENOMEM);
10682 
10683         /* Return error code.  */
10684         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
10685         return(NX_SOC_ERROR);
10686     }
10687 
10688     /* Adjust the secondary socket ID.  */
10689     secondary_sockID =  secondary_sockID - NX_BSD_SOCKFD_START;
10690 
10691     /* The master server socket will never connect to a client! For each successful
10692        client connection there will be a new secondary server socket and
10693        each such socket is associated with this master server socket. This is
10694        the difference between NetX and BSD sockets. The NetX listen() service is used
10695        with this secondary server socket.  */
10696 
10697     /* Set a pointer to the secondary socket. */
10698     bsd_secondary_socket = &nx_bsd_socket_array[secondary_sockID];
10699 
10700     /* Apply the master socket options to the secondary socket. */
10701     nx_bsd_socket_set_inherited_settings((UINT)master_sockid, (UINT)secondary_sockID);
10702 
10703     local_port = master_socket_ptr -> nx_bsd_socket_local_port;
10704 
10705     /* Invalidate the secondary master socket ID. */
10706     (bsd_secondary_socket -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id = NX_BSD_MAX_SOCKETS;
10707 
10708     /* Now call listen for the secondary server socket.  */
10709     if(backlog)
10710         status = nx_tcp_server_socket_listen(nx_bsd_default_ip, local_port, bsd_secondary_socket -> nx_bsd_socket_tcp_socket, (UINT)backlog, NX_NULL);
10711     else
10712     {
10713 
10714         /* Since a zero backlog is specified, this secondary socket needs to share with another master socket. */
10715         bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port = local_port;
10716 
10717         /* Check if a listen request is queued up for this socket. */
10718         nx_bsd_tcp_pending_connection(local_port, bsd_secondary_socket -> nx_bsd_socket_tcp_socket);
10719 
10720         status =  nx_tcp_server_socket_relisten(nx_bsd_default_ip, local_port, bsd_secondary_socket -> nx_bsd_socket_tcp_socket);
10721     }
10722 
10723     /* Check for an error.  */
10724     if ((status != NX_SUCCESS) && (status != NX_CONNECTION_PENDING))
10725     {
10726 
10727         /* Error, listen or relisten failed.  */
10728 
10729         /* Set the socket error depending on the NetX error status returned.  */
10730         nx_bsd_set_error_code(master_socket_ptr, status);
10731 
10732         /* Return error code.  */
10733         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
10734         return(NX_SOC_ERROR);
10735     }
10736 
10737     /* Now mark this as a master server socket listening to client connections.  */
10738     master_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ENABLE_LISTEN;
10739     master_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET);
10740     master_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_client_type =  NX_FALSE;
10741     master_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_SERVER_MASTER_SOCKET;
10742 
10743     /* This is a master socket.  So we use the nx_bsd_socket_master_socket_id field to
10744        record the secondary socket that is doing the real listen/accept work. */
10745     (master_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = secondary_sockID;
10746 
10747     /* Mark the secondary server socket as assigned to this master server socket.   */
10748     bsd_secondary_socket -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_ACCEPTING);
10749     bsd_secondary_socket -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET;
10750     bsd_secondary_socket -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ENABLE_LISTEN;
10751     bsd_secondary_socket -> nx_bsd_socket_local_port              =  (USHORT)local_port;
10752 
10753     /* If the master server socket is marked as non-blocking, we need to
10754        start the NetX accept process here. */
10755 
10756     sec_socket_ptr = bsd_secondary_socket -> nx_bsd_socket_tcp_socket;
10757 
10758     /* Allow accept from remote. */
10759     nx_tcp_server_socket_accept(sec_socket_ptr, 0);
10760 
10761     /* Set the master socket of other BSD TCP sockets that bind to the same port to the same secondary socket. */
10762     for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
10763     {
10764 
10765         bsd_socket_ptr = &nx_bsd_socket_array[i];
10766 
10767         if((bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP) &&
10768            (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CLIENT)) &&
10769            (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) &&
10770            (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN) &&
10771            (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND) &&
10772            (bsd_socket_ptr -> nx_bsd_socket_local_port == local_port))
10773         {
10774 
10775             (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = secondary_sockID;
10776         }
10777     }
10778 
10779     /* Check the relisten/listen status. */
10780     if(status == NX_CONNECTION_PENDING)
10781     {
10782 
10783         /* Set the connection pending flag. */
10784         bsd_secondary_socket -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
10785 
10786     }
10787 
10788     return(NX_SOC_OK);
10789 }
10790 
10791 /**************************************************************************/
10792 /*                                                                        */
10793 /*  FUNCTION                                               RELEASE        */
10794 /*                                                                        */
10795 /*    nx_bsd_tcp_pending_connection                       PORTABLE C      */
10796 /*                                                           6.1          */
10797 /*  AUTHOR                                                                */
10798 /*                                                                        */
10799 /*    Yuxin Zhou, Microsoft Corporation                                   */
10800 /*                                                                        */
10801 /*  DESCRIPTION                                                           */
10802 /*                                                                        */
10803 /*    This routine checks if the BSD TCP socket has a listen request      */
10804 /*    queued up on in the specified port.                                 */
10805 /*                                                                        */
10806 /*  INPUT                                                                 */
10807 /*                                                                        */
10808 /*    local_port                           Listening port                 */
10809 /*    socket_ptr                           Socket to check                */
10810 /*                                                                        */
10811 /*  OUTPUT                                                                */
10812 /*                                                                        */
10813 /*    None                                                                */
10814 /*                                                                        */
10815 /*  CALLS                                                                 */
10816 /*                                                                        */
10817 /*    nx_bsd_tcp_syn_received_notify        Match connection request      */
10818 /*                                             (packet) to input socket   */
10819 /*    nx_packet_receive                     Release packet to packet pool */
10820 /*                                                                        */
10821 /*  CALLED BY                                                             */
10822 /*                                                                        */
10823 /*    NetX Duo                                                            */
10824 /*                                                                        */
10825 /*  RELEASE HISTORY                                                       */
10826 /*                                                                        */
10827 /*    DATE              NAME                      DESCRIPTION             */
10828 /*                                                                        */
10829 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10830 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10831 /*                                            resulting in version 6.1    */
10832 /*                                                                        */
10833 /**************************************************************************/
nx_bsd_tcp_pending_connection(UINT local_port,NX_TCP_SOCKET * socket_ptr)10834 static VOID nx_bsd_tcp_pending_connection(UINT local_port, NX_TCP_SOCKET *socket_ptr)
10835 {
10836 
10837 struct NX_TCP_LISTEN_STRUCT *listen_ptr;
10838 NX_PACKET                   *packet_ptr;
10839 NX_TCP_HEADER               *tcp_header_ptr;
10840 UINT                         ret;
10841 
10842 
10843     listen_ptr = nx_bsd_default_ip -> nx_ip_tcp_active_listen_requests;
10844 
10845     if(listen_ptr)
10846     {
10847 
10848         do
10849         {
10850 
10851             if((listen_ptr -> nx_tcp_listen_port == local_port) &&
10852                (listen_ptr -> nx_tcp_listen_queue_current))
10853             {
10854 
10855                 do
10856                 {
10857 
10858                     packet_ptr = listen_ptr -> nx_tcp_listen_queue_head;
10859 
10860                     tcp_header_ptr = (NX_TCP_HEADER*)packet_ptr -> nx_packet_prepend_ptr;
10861 
10862                     if(tcp_header_ptr -> nx_tcp_header_word_3 & NX_TCP_SYN_BIT)
10863                     {
10864 
10865                         ret = nx_bsd_tcp_syn_received_notify(socket_ptr, packet_ptr);
10866 
10867                         /* Yes. We are done. */
10868                         if(ret == NX_TRUE)
10869                         {
10870 
10871                             return;
10872                         }
10873 
10874                         listen_ptr -> nx_tcp_listen_queue_head = packet_ptr -> nx_packet_queue_next;
10875 
10876                         if(packet_ptr == listen_ptr -> nx_tcp_listen_queue_tail)
10877                         {
10878                             listen_ptr -> nx_tcp_listen_queue_tail = NX_NULL;
10879                         }
10880 
10881                         listen_ptr -> nx_tcp_listen_queue_current--;
10882 
10883                         nx_packet_release(packet_ptr);
10884 
10885                     }
10886                 } while(listen_ptr -> nx_tcp_listen_queue_head);
10887             }
10888 
10889             listen_ptr = listen_ptr -> nx_tcp_listen_next;
10890 
10891         }while(listen_ptr != nx_bsd_default_ip -> nx_ip_tcp_active_listen_requests);
10892     }
10893 }
10894 
10895 /**************************************************************************/
10896 /*                                                                        */
10897 /*  FUNCTION                                               RELEASE        */
10898 /*                                                                        */
10899 /*    nx_bsd_find_interface_by_source_addr                PORTABLE C      */
10900 /*                                                           6.1          */
10901 /*  AUTHOR                                                                */
10902 /*                                                                        */
10903 /*    Yuxin Zhou, Microsoft Corporation                                   */
10904 /*                                                                        */
10905 /*  DESCRIPTION                                                           */
10906 /*                                                                        */
10907 /*    This function finds the interface index value of a given IPv4 or    */
10908 /*    IPv6 source address.                                                */
10909 /*                                                                        */
10910 /*  INPUT                                                                 */
10911 /*                                                                        */
10912 /*    addr_family                           Address Family                */
10913 /*    ip_addr                               Pointer to an array of IPv4   */
10914 /*                                            or IPv6 address             */
10915 /*                                                                        */
10916 /*  OUTPUT                                                                */
10917 /*                                                                        */
10918 /*    Index value                                                         */
10919 /*                                                                        */
10920 /*  CALLS                                                                 */
10921 /*                                                                        */
10922 /*    None                                                                */
10923 /*                                                                        */
10924 /*  CALLED BY                                                             */
10925 /*                                                                        */
10926 /*    nx_bsd_send_internal                                                */
10927 /*                                                                        */
10928 /*  RELEASE HISTORY                                                       */
10929 /*                                                                        */
10930 /*    DATE              NAME                      DESCRIPTION             */
10931 /*                                                                        */
10932 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10933 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10934 /*                                            resulting in version 6.1    */
10935 /*                                                                        */
10936 /**************************************************************************/
nx_bsd_find_interface_by_source_addr(UINT addr_family,ULONG * ip_addr)10937 static INT   nx_bsd_find_interface_by_source_addr(UINT addr_family, ULONG* ip_addr)
10938 {
10939 INT i;
10940 #ifndef NX_DISABLE_IPV4
10941 ULONG ipv4_addr;
10942 #endif /* NX_DISABLE_IPV4 */
10943 #ifdef FEATURE_NX_IPV6
10944 ULONG ipv6_addr[4];
10945 #endif
10946 
10947 #ifndef NX_DISABLE_IPV4
10948     if(addr_family == AF_INET)
10949     {
10950         ipv4_addr = *ip_addr;
10951         NX_CHANGE_ULONG_ENDIAN(ipv4_addr);
10952 
10953         for(i = 0; i < NX_MAX_IP_INTERFACES; i++)
10954         {
10955             if((nx_bsd_default_ip -> nx_ip_interface[i].nx_interface_valid) &&
10956                (nx_bsd_default_ip -> nx_ip_interface[i].nx_interface_ip_address == ipv4_addr))
10957                 return i;
10958         }
10959     }
10960 #endif /* NX_DISABLE_IPV4 */
10961 #ifdef FEATURE_NX_IPV6
10962     if(addr_family == AF_INET6)
10963     {
10964         ipv6_addr[0] = *(ip_addr);
10965         ipv6_addr[1] = *(ip_addr + 1);
10966         ipv6_addr[2] = *(ip_addr + 2);
10967         ipv6_addr[3] = *(ip_addr + 3);
10968         NX_IPV6_ADDRESS_CHANGE_ENDIAN(ipv6_addr);
10969 
10970         for(i = 0; i < NX_MAX_IPV6_ADDRESSES; i++)
10971         {
10972 
10973             if((nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address_valid) &&
10974                (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address_attached -> nx_interface_valid) &&
10975                (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address[0] == ipv6_addr[0]) &&
10976                (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address[1] == ipv6_addr[1]) &&
10977                (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address[2] == ipv6_addr[2]) &&
10978                (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address[3] == ipv6_addr[3]))
10979                 return i;
10980         }
10981     }
10982 #endif
10983 
10984     return((INT)(NX_BSD_LOCAL_IF_INADDR_ANY));
10985 
10986 }
10987 
10988 
10989 #ifndef NX_DISABLE_IPV4
10990 /**************************************************************************/
10991 /*                                                                        */
10992 /*  FUNCTION                                               RELEASE        */
10993 /*                                                                        */
10994 /*    _nxd_bsd_ipv4_packet_send                           PORTABLE C      */
10995 /*                                                           6.1          */
10996 /*  AUTHOR                                                                */
10997 /*                                                                        */
10998 /*    Yuxin Zhou, Microsoft Corporation                                   */
10999 /*                                                                        */
11000 /*  DESCRIPTION                                                           */
11001 /*                                                                        */
11002 /*    This function computes the IP header checksum and updates that into */
11003 /*    the ip header ,which is assumed to be already prepended in the      */
11004 /*    input packet buffer, and forwards it to the driver directly.        */
11005 /*                                                                        */
11006 /*  INPUT                                                                 */
11007 /*                                                                        */
11008 /*    packet_ptr                            Pointer to packet to send     */
11009 /*                                                                        */
11010 /*  OUTPUT                                                                */
11011 /*                                                                        */
11012 /*    None                                                                */
11013 /*                                                                        */
11014 /*  CALLS                                                                 */
11015 /*                                                                        */
11016 /*    _nx_ip_checksum_compute               Compute IP checksum           */
11017 /*    (_nx_arp_entry_allocate)              ARP entry allocate service    */
11018 /*    (_nx_arp_packet_send)                 Send an ARP packet            */
11019 /*    _nx_ip_packet_deferred_receive        Receive loopback packet       */
11020 /*    _nx_packet_copy                       Copy packet to input packet   */
11021 /*    _nx_packet_transmit_release           Release transmit packet       */
11022 /*    (nx_ip_fragment_processing)           Fragment processing           */
11023 /*    (ip_link_driver)                      User supplied link driver     */
11024 /*                                                                        */
11025 /*  CALLED BY                                                             */
11026 /*                                                                        */
11027 /*    nx_bsd_send_internal                                                */
11028 /*                                                                        */
11029 /*  RELEASE HISTORY                                                       */
11030 /*                                                                        */
11031 /*    DATE              NAME                      DESCRIPTION             */
11032 /*                                                                        */
11033 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
11034 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
11035 /*                                            resulting in version 6.1    */
11036 /*                                                                        */
11037 /**************************************************************************/
_nxd_bsd_ipv4_packet_send(NX_PACKET * packet_ptr)11038 static VOID  _nxd_bsd_ipv4_packet_send(NX_PACKET *packet_ptr)
11039 {
11040 
11041 TX_INTERRUPT_SAVE_AREA
11042 NX_IP_DRIVER            driver_request;
11043 NX_IPV4_HEADER         *ip_header_ptr;
11044 #ifndef NX_DISABLE_IP_TX_CHECKSUM
11045 ULONG                   checksum;
11046 ULONG                   val;
11047 #endif
11048 UINT                    index;
11049 NX_ARP                 *arp_ptr;
11050 NX_PACKET              *last_packet;
11051 NX_PACKET              *remove_packet;
11052 UINT                    queued_count;
11053 NX_PACKET              *packet_copy;
11054 ULONG                   network_mask;
11055 ULONG                   network;
11056 NX_IP *                 ip_ptr;
11057 ULONG                   destination_ip;
11058 
11059     ip_ptr = nx_bsd_default_ip;
11060 #ifndef NX_DISABLE_IP_INFO
11061 
11062     /* Increment the total send requests counter.  */
11063     ip_ptr -> nx_ip_total_packet_send_requests++;
11064 #endif
11065 
11066 
11067     /* Setup the IP header pointer.  */
11068     ip_header_ptr =  (NX_IPV4_HEADER *) packet_ptr -> nx_packet_prepend_ptr;
11069 
11070     destination_ip = ip_header_ptr -> nx_ip_header_destination_ip;
11071 
11072     /* Swap the destination address to host byte order.*/
11073     NX_CHANGE_ULONG_ENDIAN(destination_ip);
11074 
11075 #ifndef NX_DISABLE_IP_TX_CHECKSUM
11076     checksum = _nx_ip_checksum_compute(packet_ptr, NX_IP_VERSION_V4,
11077                                        /* Length is the size of IP header, including options */
11078                                        (UINT)((*(UCHAR*)ip_header_ptr & 0xf) << 2),
11079                                        /* IPv4 header checksum does not use src/dest addresses */
11080                                        NULL, NULL);
11081 
11082     val = (ULONG)(~checksum);
11083     val = val & NX_LOWER_16_MASK;
11084 
11085     /* Convert to network byte order. */
11086     NX_CHANGE_ULONG_ENDIAN(val);
11087 
11088     /* Now store the checksum in the IP header.  */
11089     ip_header_ptr -> nx_ip_header_word_2 =  ip_header_ptr -> nx_ip_header_word_2 | val;
11090 
11091 #endif
11092 
11093     /* Determine if physical mapping is needed by the link driver.  */
11094     if (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_address_mapping_needed )
11095     {
11096 
11097 
11098         network_mask = packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_network_mask;
11099         network = packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_network;
11100 
11101         /* Determine whether or not the destination address is out of  this local network.  */
11102         if (((destination_ip & network_mask) != network) ||
11103             ((destination_ip & ~network_mask) == ~network_mask) ||
11104              (destination_ip == packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_address))
11105         {
11106 
11107             /* We have an out-of-network destination IP address, check for a variety
11108                of out-of-network destinations.  */
11109 
11110             /* Determine if an IP limited or directed broadcast is requested.  */
11111             if ((destination_ip == NX_IP_LIMITED_BROADCAST) ||
11112                 (((destination_ip & network_mask) == network) &&
11113                  ((destination_ip & ~network_mask) == ~network_mask)))
11114             {
11115 
11116                 /* Build the driver request.  */
11117                 driver_request.nx_ip_driver_ptr =                   ip_ptr;
11118                 driver_request.nx_ip_driver_command =               NX_LINK_PACKET_BROADCAST;
11119                 driver_request.nx_ip_driver_packet =                packet_ptr;
11120                 driver_request.nx_ip_driver_physical_address_msw =  0xFFFFUL;
11121                 driver_request.nx_ip_driver_physical_address_lsw =  0xFFFFFFFFUL;
11122                 driver_request.nx_ip_driver_interface =             packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11123 
11124 #ifndef NX_DISABLE_FRAGMENTATION
11125                 /* Determine if fragmentation is needed.  */
11126                 if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
11127                 {
11128 
11129                     /* Fragmentation is needed, call the fragment routine if available. */
11130                     if (ip_ptr -> nx_ip_fragment_processing)
11131                     {
11132 
11133                         /* Call the IP fragment processing routine.  */
11134                         (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
11135                     }
11136                     else
11137                     {
11138 
11139 #ifndef NX_DISABLE_IP_INFO
11140 
11141                         /* Increment the IP send packets dropped count.  */
11142                         ip_ptr -> nx_ip_send_packets_dropped++;
11143 #endif
11144                         /* Just release the packet.  */
11145                         _nx_packet_transmit_release(packet_ptr);
11146                     }
11147 
11148                     /* In either case, this packet send is complete, just return.  */
11149                     return;
11150                 }
11151 #endif
11152 
11153 #ifndef NX_DISABLE_IP_INFO
11154 
11155                 /* Increment the IP packet sent count.  */
11156                 ip_ptr -> nx_ip_total_packets_sent++;
11157 
11158                 /* Increment the IP bytes sent count.  */
11159                 ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11160 #endif
11161 
11162                 /* Broadcast packet.  */
11163                 (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
11164 
11165                 return;
11166             }
11167 
11168             /* Determine if we have a loopback address.  */
11169             else if ((((destination_ip >= NX_IP_LOOPBACK_FIRST) &&
11170                        (destination_ip <= NX_IP_LOOPBACK_LAST))) ||
11171                        (destination_ip == ip_ptr -> nx_ip_interface[0].nx_interface_ip_address))
11172             {
11173 
11174                 /* Yes, we have an internal loopback address.  */
11175 
11176                 /* Copy the packet so it can be enqueued properly by the receive
11177                    processing.  */
11178                 if (_nx_packet_copy(packet_ptr, &packet_copy, ip_ptr -> nx_ip_default_packet_pool, NX_NO_WAIT) == NX_SUCCESS)
11179                 {
11180 
11181 #ifndef NX_DISABLE_IP_INFO
11182 
11183                     /* Increment the IP packet sent count.  */
11184                     ip_ptr -> nx_ip_total_packets_sent++;
11185 
11186                     /* Increment the IP bytes sent count.  */
11187                     ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11188 #endif
11189 
11190                     /* Send the packet to this IP's receive processing like it came in from the
11191                        driver.  */
11192                     _nx_ip_packet_deferred_receive(ip_ptr, packet_copy);
11193                 }
11194 #ifndef NX_DISABLE_IP_INFO
11195                 else
11196                 {
11197 
11198                     /* Increment the IP send packets dropped count.  */
11199                     ip_ptr -> nx_ip_send_packets_dropped++;
11200 
11201                     /* Increment the IP transmit resource error count.  */
11202                     ip_ptr -> nx_ip_transmit_resource_errors++;
11203                 }
11204 #endif
11205 
11206                 /* Release the transmit packet.  */
11207                 _nx_packet_transmit_release(packet_ptr);
11208                 return;
11209             }
11210 
11211             /* Determine if we have a class D multicast address.  */
11212             else if ((destination_ip & NX_IP_CLASS_D_MASK) == NX_IP_CLASS_D_TYPE)
11213             {
11214 
11215                 /* Yes, we have a class D multicast address.  Derive the physical mapping from
11216                    the class D address.  */
11217                 driver_request.nx_ip_driver_physical_address_msw =  NX_IP_MULTICAST_UPPER;
11218                 driver_request.nx_ip_driver_physical_address_lsw =  NX_IP_MULTICAST_LOWER | (destination_ip & NX_IP_MULTICAST_MASK);
11219                 driver_request.nx_ip_driver_interface =             packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11220 
11221                 /* Determine if the group address has been joined in this IP instance.  */
11222                 index =  0;
11223                 while (index < NX_MAX_MULTICAST_GROUPS)
11224                 {
11225 
11226                     /* Determine if the destination address matches the requested address.  */
11227                     if (ip_ptr -> nx_ipv4_multicast_entry[index].nx_ipv4_multicast_join_list == destination_ip)
11228                     {
11229 
11230                         /* Yes, break the loop!  */
11231                         break;
11232                     }
11233 
11234                     /* Increment the join list index.  */
11235                     index++;
11236                 }
11237 
11238                 /* Determine if the group was joined by this IP instance.  */
11239                 if (index < NX_MAX_MULTICAST_GROUPS)
11240                 {
11241 
11242                     /* Determine if the group has loopback enabled.  */
11243                     if (ip_ptr -> nx_ipv4_multicast_entry[index].nx_ipv4_multicast_loopback_enable)
11244                     {
11245 
11246                         /* Yes, loopback is enabled!  */
11247 
11248                         /* Copy the packet so we can send it via loopback.  */
11249                         if (_nx_packet_copy(packet_ptr, &packet_copy, ip_ptr -> nx_ip_default_packet_pool, NX_NO_WAIT) == NX_SUCCESS)
11250                         {
11251 
11252 #ifndef NX_DISABLE_IP_INFO
11253 
11254                             /* Increment the IP packet sent count.  */
11255                             ip_ptr -> nx_ip_total_packets_sent++;
11256 
11257                             /* Increment the IP bytes sent count.  */
11258                             ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11259 #endif
11260 
11261                             /* Packet copy was successful. Send the packet to this IP's receive processing like it came in from the
11262                                driver.  */
11263                             _nx_ip_packet_deferred_receive(ip_ptr, packet_copy);
11264                         }
11265 #ifndef NX_DISABLE_IP_INFO
11266                         else
11267                         {
11268 
11269                             /* Increment the IP send packets dropped count.  */
11270                             ip_ptr -> nx_ip_send_packets_dropped++;
11271 
11272                             /* Increment the IP transmit resource error count.  */
11273                             ip_ptr -> nx_ip_transmit_resource_errors++;
11274                         }
11275 #endif
11276                     }
11277                 }
11278 
11279                 /* Build the driver request.  */
11280                 driver_request.nx_ip_driver_ptr =      ip_ptr;
11281                 driver_request.nx_ip_driver_command =  NX_LINK_PACKET_SEND;
11282                 driver_request.nx_ip_driver_packet =   packet_ptr;
11283                 driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11284 
11285 #ifndef NX_DISABLE_FRAGMENTATION
11286                 /* Determine if fragmentation is needed.  */
11287                 if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
11288                 {
11289 
11290                     /* Fragmentation is needed, call the fragment routine if available. */
11291                     if (ip_ptr -> nx_ip_fragment_processing)
11292                     {
11293 
11294                         /* Call the IP fragment processing routine.  */
11295                         (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
11296                     }
11297                     else
11298                     {
11299 
11300 #ifndef NX_DISABLE_IP_INFO
11301 
11302                         /* Increment the IP send packets dropped count.  */
11303                         ip_ptr -> nx_ip_send_packets_dropped++;
11304 #endif
11305                         /* Just release the packet.  */
11306                         _nx_packet_transmit_release(packet_ptr);
11307                     }
11308 
11309                     /* In either case, this packet send is complete, just return.  */
11310                     return;
11311                 }
11312 #endif
11313 
11314 #ifndef NX_DISABLE_IP_INFO
11315 
11316                 /* Increment the IP packet sent count.  */
11317                 ip_ptr -> nx_ip_total_packets_sent++;
11318 
11319                 /* Increment the IP bytes sent count.  */
11320                 ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11321 #endif
11322 
11323                 /* Send the IP packet out on the network via the attached driver.  */
11324                 (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
11325 
11326                 /* Return to caller.  */
11327                 return;
11328             }
11329 
11330             /* Use default gateway. */
11331             else
11332             {
11333 
11334                 /* We have an out-of-network destination IP address, check to see if a
11335                    Gateway IP address has been specified.  */
11336                 if (ip_ptr -> nx_ip_gateway_address)
11337                 {
11338 
11339                     /* Remap the destination IP address to the Gateway IP address.  The ARP
11340                        processing below will handle getting the physical address for the
11341                        Gateway.  */
11342                     destination_ip =  ip_ptr -> nx_ip_gateway_address;
11343                 }
11344                 else
11345                 {
11346 
11347 #ifndef NX_DISABLE_IP_INFO
11348 
11349                     /* Increment the number of no route errors.  */
11350                     ip_ptr -> nx_ip_transmit_no_route_errors++;
11351 
11352                     /* Increment the IP send packets dropped count.  */
11353                     ip_ptr -> nx_ip_send_packets_dropped++;
11354 #endif
11355                     /* Just release the packet.  */
11356                     _nx_packet_transmit_release(packet_ptr);
11357 
11358                     /* In either case, this packet send is complete, just return.  */
11359                     return;
11360                 }
11361             }
11362         }
11363 
11364         /* Yes, look into the ARP Routing Table to derive the physical address.  */
11365 
11366         /* Calculate the hash index for the destination IP address.  */
11367         index =  (UINT) ((destination_ip + (destination_ip >> 8)) & NX_ARP_TABLE_MASK);
11368 
11369         /* Disable interrupts temporarily.  */
11370         TX_DISABLE
11371 
11372         /* Determine if there is an entry for this IP address.  */
11373         arp_ptr =  ip_ptr -> nx_ip_arp_table[index];
11374 
11375         /* Determine if this arp entry matches the destination IP address.  */
11376         if ((arp_ptr) && (arp_ptr -> nx_arp_ip_address == destination_ip))
11377         {
11378 
11379             /* Yes, we have an existing ARP mapping entry.  */
11380 
11381             /* Determine if there is a physical address.  */
11382             if (arp_ptr -> nx_arp_physical_address_msw | arp_ptr -> nx_arp_physical_address_lsw)
11383             {
11384 
11385                 /* Yes, we have a physical mapping.  Copy the physical address into the driver
11386                    request structure.  */
11387                 driver_request.nx_ip_driver_physical_address_msw =  arp_ptr -> nx_arp_physical_address_msw;
11388                 driver_request.nx_ip_driver_physical_address_lsw =  arp_ptr -> nx_arp_physical_address_lsw;
11389 
11390                 /* Restore interrupts.  */
11391                 TX_RESTORE
11392 
11393                 /* Build the driver request.  */
11394                 driver_request.nx_ip_driver_ptr =      ip_ptr;
11395                 driver_request.nx_ip_driver_command =  NX_LINK_PACKET_SEND;
11396                 driver_request.nx_ip_driver_packet =   packet_ptr;
11397                 driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11398 
11399 #ifndef NX_DISABLE_FRAGMENTATION
11400                 /* Determine if fragmentation is needed.  */
11401                 if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
11402                 {
11403 
11404                     /* Fragmentation is needed, call the fragment routine if available. */
11405                     if (ip_ptr -> nx_ip_fragment_processing)
11406                     {
11407 
11408                         /* Call the IP fragment processing routine.  */
11409                         (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
11410                     }
11411                     else
11412                     {
11413 
11414 #ifndef NX_DISABLE_IP_INFO
11415 
11416                         /* Increment the IP send packets dropped count.  */
11417                         ip_ptr -> nx_ip_send_packets_dropped++;
11418 #endif
11419 
11420                         /* Just release the packet.  */
11421                         _nx_packet_transmit_release(packet_ptr);
11422                     }
11423 
11424                     /* In either case, this packet send is complete, just return.  */
11425                     return;
11426                 }
11427 #endif
11428 
11429 #ifndef NX_DISABLE_IP_INFO
11430 
11431                 /* Increment the IP packet sent count.  */
11432                 ip_ptr -> nx_ip_total_packets_sent++;
11433 
11434                 /* Increment the IP bytes sent count.  */
11435                 ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11436 #endif
11437 
11438                 /* Send the IP packet out on the network via the attached driver.  */
11439                 (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
11440 
11441                 /* Return to caller.  */
11442                 return;
11443             }
11444             else
11445             {
11446 
11447                 /* Ensure the current packet's queue next pointer to NULL.  */
11448                 packet_ptr -> nx_packet_queue_next =  NX_NULL;
11449 
11450                 /* Determine if the queue is empty.  */
11451                 if (arp_ptr -> nx_arp_packets_waiting == NX_NULL)
11452                 {
11453 
11454                     /* Yes, we have an empty ARP packet queue.  Simply place the
11455                        packet at the head of the list.  */
11456                     arp_ptr -> nx_arp_packets_waiting =  packet_ptr;
11457 
11458                     /* Restore interrupts.  */
11459                     TX_RESTORE
11460                 }
11461                 else
11462                 {
11463 
11464                     /* Determine how many packets are on the ARP entry's packet
11465                        queue and remember the last packet in the queue.  We know
11466                        there is at least one on the queue and another that is
11467                        going to be queued.  */
11468                     last_packet =  arp_ptr -> nx_arp_packets_waiting;
11469                     queued_count = 0;
11470                     while (last_packet -> nx_packet_queue_next)
11471                     {
11472 
11473                         /* Increment the queued count.  */
11474                         queued_count++;
11475 
11476                         /* Move to the next packet in the queue.  */
11477                         last_packet =  last_packet -> nx_packet_queue_next;
11478                     }
11479 
11480                     /* Place the packet at the end of the list.  */
11481                     last_packet -> nx_packet_queue_next =  packet_ptr;
11482 
11483                     /* Default the remove packet pointer to NULL.  */
11484                     remove_packet =  NX_NULL;
11485 
11486                     /* Determine if the packets queued has exceeded the queue
11487                        depth.  */
11488                     if (queued_count >= NX_ARP_MAX_QUEUE_DEPTH)
11489                     {
11490 
11491                         /* Save the packet pointer at the head of the list.  */
11492                         remove_packet =  arp_ptr -> nx_arp_packets_waiting;
11493 
11494                         /* Remove the packet from the ARP queue.  */
11495                         arp_ptr -> nx_arp_packets_waiting =  remove_packet -> nx_packet_queue_next;
11496 
11497                         /* Clear the remove packet queue next pointer.  */
11498                         remove_packet -> nx_packet_queue_next =  NX_NULL;
11499 
11500 #ifndef NX_DISABLE_IP_INFO
11501 
11502                         /* Increment the IP transmit resource error count.  */
11503                         ip_ptr -> nx_ip_transmit_resource_errors++;
11504 
11505                         /* Increment the IP send packets dropped count.  */
11506                         ip_ptr -> nx_ip_send_packets_dropped++;
11507 #endif
11508                     }
11509 
11510                     /* Restore interrupts.  */
11511                     TX_RESTORE
11512 
11513                     /* Determine if there is a packet to remove.  */
11514                     if (remove_packet)
11515                     {
11516 
11517                         /* Yes, the packet queue depth for this ARP entry was exceeded
11518                            so release the packet that was removed from the queue.  */
11519                         _nx_packet_transmit_release(remove_packet);
11520                     }
11521                 }
11522 
11523                 /* Return to caller.  */
11524                 return;
11525             }
11526         }
11527         else
11528         {
11529 
11530             /* At this point, we need to search the ARP list for a match for the
11531                destination IP.  */
11532 
11533             /* First, restore interrupts.  */
11534             TX_RESTORE
11535 
11536             /* Pickup the first ARP entry.  */
11537             arp_ptr =  ip_ptr -> nx_ip_arp_table[index];
11538 
11539             /* Loop to look for an ARP match.  */
11540             while (arp_ptr)
11541             {
11542 
11543                 /* Check for an IP match.  */
11544                 if (arp_ptr -> nx_arp_ip_address == destination_ip)
11545                 {
11546 
11547                     /* Yes, we found a match.  Get out of the loop!  */
11548                     break;
11549                 }
11550 
11551                 /* Move to the next active ARP entry.  */
11552                 arp_ptr =  arp_ptr -> nx_arp_active_next;
11553 
11554                 /* Determine if we are at the end of the ARP list.  */
11555                 if (arp_ptr == ip_ptr -> nx_ip_arp_table[index])
11556                 {
11557                     /* Clear the ARP pointer.  */
11558                     arp_ptr =  NX_NULL;
11559                     break;
11560                 }
11561             }
11562 
11563             /* Determine if we actually found a matching ARP entry.  */
11564             if (arp_ptr)
11565             {
11566 
11567                 /* Yes, we found an ARP entry.  Now check and see if
11568                    it has an actual physical address.  */
11569                 if (arp_ptr -> nx_arp_physical_address_msw | arp_ptr -> nx_arp_physical_address_lsw)
11570                 {
11571 
11572                     /* Yes, we have a physical mapping.  Copy the physical address into the driver
11573                        request structure.  */
11574                     driver_request.nx_ip_driver_physical_address_msw =  arp_ptr -> nx_arp_physical_address_msw;
11575                     driver_request.nx_ip_driver_physical_address_lsw =  arp_ptr -> nx_arp_physical_address_lsw;
11576 
11577                     /* Disable interrupts.  */
11578                     TX_DISABLE
11579 
11580                     /* Move this ARP entry to the head of the list.  */
11581                     ip_ptr -> nx_ip_arp_table[index] =  arp_ptr;
11582 
11583                     /* Restore interrupts.  */
11584                     TX_RESTORE
11585 
11586                     /* Build the driver request message.  */
11587                     driver_request.nx_ip_driver_ptr =      ip_ptr;
11588                     driver_request.nx_ip_driver_command =  NX_LINK_PACKET_SEND;
11589                     driver_request.nx_ip_driver_packet =   packet_ptr;
11590                     driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11591 
11592 #ifndef NX_DISABLE_FRAGMENTATION
11593                     /* Determine if fragmentation is needed.  */
11594                     if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
11595                     {
11596 
11597                         /* Fragmentation is needed, call the fragment routine if available. */
11598                         if (ip_ptr -> nx_ip_fragment_processing)
11599                         {
11600 
11601                             /* Call the IP fragment processing routine.  */
11602                             (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
11603                         }
11604                         else
11605                         {
11606 
11607 #ifndef NX_DISABLE_IP_INFO
11608 
11609                             /* Increment the IP send packets dropped count.  */
11610                             ip_ptr -> nx_ip_send_packets_dropped++;
11611 #endif
11612 
11613                             /* Just release the packet.  */
11614                             _nx_packet_transmit_release(packet_ptr);
11615                         }
11616 
11617                         /* In either case, this packet send is complete, just return.  */
11618                         return;
11619                     }
11620 #endif
11621 
11622 #ifndef NX_DISABLE_IP_INFO
11623 
11624                     /* Increment the IP packet sent count.  */
11625                     ip_ptr -> nx_ip_total_packets_sent++;
11626 
11627                     /* Increment the IP bytes sent count.  */
11628                     ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11629 #endif
11630 
11631                     /* Send the IP packet out on the network via the attached driver.  */
11632                     (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
11633 
11634                     /* Return to caller.  */
11635                     return;
11636                 }
11637                 else
11638                 {
11639 
11640                     /* We don't have physical mapping.  */
11641 
11642                     /* Disable interrupts.  */
11643                     TX_DISABLE
11644 
11645                     /* Ensure the current packet's queue next pointer to NULL.  */
11646                     packet_ptr -> nx_packet_queue_next =  NX_NULL;
11647 
11648                     /* Determine if the queue is empty.  */
11649                     if (arp_ptr -> nx_arp_packets_waiting == NX_NULL)
11650                     {
11651 
11652                         /* Yes, we have an empty ARP packet queue.  Simply place the
11653                            packet at the head of the list.  */
11654                         arp_ptr -> nx_arp_packets_waiting =  packet_ptr;
11655 
11656                         /* Restore interrupts.  */
11657                         TX_RESTORE
11658                     }
11659                     else
11660                     {
11661 
11662 
11663                         /* Determine how many packets are on the ARP entry's packet
11664                            queue and remember the last packet in the queue.  We know
11665                            there is at least one on the queue and another that is
11666                            going to be queued.  */
11667                         last_packet =  arp_ptr -> nx_arp_packets_waiting;
11668                         queued_count = 0;
11669                         while (last_packet -> nx_packet_queue_next)
11670                         {
11671 
11672                             /* Increment the queued count.  */
11673                             queued_count++;
11674 
11675                             /* Move to the next packet in the queue.  */
11676                             last_packet =  last_packet -> nx_packet_queue_next;
11677                         }
11678 
11679                         /* Place the packet at the end of the list.  */
11680                         last_packet -> nx_packet_queue_next =  packet_ptr;
11681 
11682                         /* Default the remove packet pointer to NULL.  */
11683                         remove_packet =  NX_NULL;
11684 
11685                         /* Determine if the packets queued has exceeded the queue
11686                            depth.  */
11687                         if (queued_count >= NX_ARP_MAX_QUEUE_DEPTH)
11688                         {
11689 
11690                             /* Save the packet pointer at the head of the list.  */
11691                             remove_packet =  arp_ptr -> nx_arp_packets_waiting;
11692 
11693                             /* Remove the packet from the ARP queue.  */
11694                             arp_ptr -> nx_arp_packets_waiting =  remove_packet -> nx_packet_queue_next;
11695 
11696                             /* Clear the remove packet queue next pointer.  */
11697                             remove_packet -> nx_packet_queue_next =  NX_NULL;
11698 
11699 #ifndef NX_DISABLE_IP_INFO
11700 
11701                             /* Increment the IP transmit resource error count.  */
11702                             ip_ptr -> nx_ip_transmit_resource_errors++;
11703 
11704                             /* Increment the IP send packets dropped count.  */
11705                             ip_ptr -> nx_ip_send_packets_dropped++;
11706 #endif
11707                         }
11708 
11709                         /* Restore interrupts.  */
11710                         TX_RESTORE
11711 
11712                         /* Determine if there is a packet to remove.  */
11713                         if (remove_packet)
11714                         {
11715 
11716                             /* Yes, the packet queue depth for this ARP entry was exceeded
11717                                so release the packet that was removed from the queue.  */
11718                             _nx_packet_transmit_release(remove_packet);
11719                         }
11720                     }
11721 
11722                     /* Return to caller.  */
11723                     return;
11724                 }
11725             }
11726             else
11727             {
11728 
11729                 /* No ARP entry was found.  We need to allocate a new ARP entry, populate it, and
11730                    initiate an ARP request to get the specific physical mapping.  */
11731 
11732                 /* Allocate a new ARP entry.  */
11733                 if ((!ip_ptr -> nx_ip_arp_allocate) ||
11734                                     ((ip_ptr -> nx_ip_arp_allocate)(ip_ptr, &(ip_ptr -> nx_ip_arp_table[index]), NX_FALSE)))
11735                 {
11736 
11737                     /* Error, release the protection and the packet.  */
11738 
11739 #ifndef NX_DISABLE_IP_INFO
11740 
11741                     /* Increment the IP transmit resource error count.  */
11742                     ip_ptr -> nx_ip_transmit_resource_errors++;
11743 
11744                     /* Increment the IP send packets dropped count.  */
11745                     ip_ptr -> nx_ip_send_packets_dropped++;
11746 #endif
11747 
11748                     /* Release the packet.  */
11749                     _nx_packet_transmit_release(packet_ptr);
11750 
11751                     /* Just return!  */
11752                     return;
11753                 }
11754 
11755                 /* Otherwise, setup a pointer to the new ARP entry.  */
11756                 arp_ptr =  (ip_ptr -> nx_ip_arp_table[index]) -> nx_arp_active_previous;
11757 
11758                 /* Setup the IP address and clear the physical mapping.  */
11759                 arp_ptr -> nx_arp_ip_address =            destination_ip;
11760                 arp_ptr -> nx_arp_physical_address_msw =  0;
11761                 arp_ptr -> nx_arp_physical_address_lsw =  0;
11762                 arp_ptr -> nx_arp_entry_next_update =     NX_ARP_EXPIRATION_RATE;
11763                 arp_ptr -> nx_arp_retries =               0;
11764                 arp_ptr -> nx_arp_ip_interface =          packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11765 
11766                 /* Ensure the queue next pointer is NULL for the packet before it
11767                    is placed on the ARP waiting queue.  */
11768                 packet_ptr -> nx_packet_queue_next =  NX_NULL;
11769 
11770                 /* Queue the packet for output.  */
11771                 arp_ptr -> nx_arp_packets_waiting =  packet_ptr;
11772 
11773                 /* Call ARP send to send an ARP request.  */
11774                 (ip_ptr -> nx_ip_arp_packet_send)(ip_ptr, destination_ip, packet_ptr -> nx_packet_address.nx_packet_interface_ptr);
11775                 return;
11776             }
11777         }
11778     }
11779     else
11780     {
11781 
11782         /* This IP instance does not require any IP-to-physical mapping.  */
11783 
11784         /* Determine if we have a loopback address.  */
11785         if ((((destination_ip >= NX_IP_LOOPBACK_FIRST) &&
11786               (destination_ip <= NX_IP_LOOPBACK_LAST))) ||
11787               (destination_ip == packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_address))
11788         {
11789 
11790             /* Yes, we have an internal loopback address.  */
11791 
11792             /* Copy the packet so it can be enqueued properly by the receive
11793                processing.  */
11794             if (_nx_packet_copy(packet_ptr, &packet_copy, ip_ptr -> nx_ip_default_packet_pool, NX_NO_WAIT) == NX_SUCCESS)
11795             {
11796 
11797 #ifndef NX_DISABLE_IP_INFO
11798 
11799                 /* Increment the IP packet sent count.  */
11800                 ip_ptr -> nx_ip_total_packets_sent++;
11801 
11802                 /* Increment the IP bytes sent count.  */
11803                 ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11804 #endif
11805 
11806                 /* Send the packet to this IP's receive processing like it came in from the
11807                    driver.  */
11808                 _nx_ip_packet_deferred_receive(ip_ptr, packet_copy);
11809             }
11810 #ifndef NX_DISABLE_IP_INFO
11811             else
11812             {
11813 
11814                 /* Increment the IP transmit resource error count.  */
11815                 ip_ptr -> nx_ip_transmit_resource_errors++;
11816 
11817                 /* Increment the IP send packets dropped count.  */
11818                 ip_ptr -> nx_ip_send_packets_dropped++;
11819             }
11820 #endif
11821 
11822             /* Release the transmit packet.  */
11823             _nx_packet_transmit_release(packet_ptr);
11824             return;
11825         }
11826 
11827         /* Build the driver request.  */
11828         driver_request.nx_ip_driver_ptr =      ip_ptr;
11829         driver_request.nx_ip_driver_command =  NX_LINK_PACKET_SEND;
11830         driver_request.nx_ip_driver_packet =   packet_ptr;
11831         driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11832 
11833 #ifndef NX_DISABLE_FRAGMENTATION
11834         /* Determine if fragmentation is needed.  */
11835         if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
11836         {
11837 
11838             /* Fragmentation is needed, call the fragment routine if available. */
11839             if (ip_ptr -> nx_ip_fragment_processing)
11840             {
11841 
11842                 /* Call the IP fragment processing routine.  */
11843                 (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
11844             }
11845             else
11846             {
11847 
11848 #ifndef NX_DISABLE_IP_INFO
11849 
11850                 /* Increment the IP send packets dropped count.  */
11851                 ip_ptr -> nx_ip_send_packets_dropped++;
11852 #endif
11853 
11854                 /* Just release the packet.  */
11855                 _nx_packet_transmit_release(packet_ptr);
11856             }
11857 
11858             /* In either case, this packet send is complete, just return.  */
11859             return;
11860         }
11861 #endif
11862 
11863 #ifndef NX_DISABLE_IP_INFO
11864 
11865         /* Increment the IP packet sent count.  */
11866         ip_ptr -> nx_ip_total_packets_sent++;
11867 
11868         /* Increment the IP bytes sent count.  */
11869         ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11870 
11871 #endif
11872 
11873         /* No mapping driver.  Just send the packet out!  */
11874         (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
11875     }
11876 }
11877 #endif /*NX_DISABLE_IPV4 */
11878 
11879 #ifdef FEATURE_NX_IPV6
11880 /**************************************************************************/
11881 /*                                                                        */
11882 /*  FUNCTION                                               RELEASE        */
11883 /*                                                                        */
11884 /*    _nxd_bsd_ipv6_packet_send                           PORTABLE C      */
11885 /*                                                           6.1          */
11886 /*  AUTHOR                                                                */
11887 /*                                                                        */
11888 /*    Yuxin Zhou, Microsoft Corporation                                   */
11889 /*                                                                        */
11890 /*  DESCRIPTION                                                           */
11891 /*                                                                        */
11892 /*    This function forwards the input packet directly to the appropriate */
11893 /*    link driver.  The caller needs to fill in the correct               */
11894 /*    source and destination addresses into the packet source and         */
11895 /*    destination address.  The caller also makes sure that the packet    */
11896 /*    interface address is valid (not in tentative state), and source     */
11897 /*    address is not unspecified e.g. NULL.                               */
11898 /*                                                                        */
11899 /*  INPUT                                                                 */
11900 /*                                                                        */
11901 /*    packet_ptr                            Pointer to packet to send     */
11902 /*    src_addr                              Pointer to source address     */
11903 /*    dest_addr                             Pointer to dest address       */
11904 /*                                                                        */
11905 /*  OUTPUT                                                                */
11906 /*                                                                        */
11907 /*    None                                                                */
11908 /*                                                                        */
11909 /*  CALLS                                                                 */
11910 /*                                                                        */
11911 /*    _nx_packet_transmit_release           Release transmit packet       */
11912 /*    _nx_nd_cache_add_entry                Add new entry to ND Cache     */
11913 /*    IPv6_Address_Type                     Find IPv6 address type        */
11914 /*    _nx_packet_copy                       Packet copy                   */
11915 /*    _nx_ip_packet_deferred_receive        Places received packets in    */
11916 /*                                             deferred packet queue      */
11917 /*    _nx_icmpv6_send_ns                    Send neighbor solicitation    */
11918 /*    _nxd_ipv6_search_onlink               Find onlink match             */
11919 /*    _nx_ipv6_fragment_processing          Fragment processing           */
11920 /*    (ip_link_driver)                      User supplied link driver     */
11921 /*                                                                        */
11922 /*  CALLED BY                                                             */
11923 /*                                                                        */
11924 /*    nx_bsd_send_internal                                                */
11925 /*                                                                        */
11926 /*  RELEASE HISTORY                                                       */
11927 /*                                                                        */
11928 /*    DATE              NAME                      DESCRIPTION             */
11929 /*                                                                        */
11930 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
11931 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
11932 /*                                            resulting in version 6.1    */
11933 /*                                                                        */
11934 /**************************************************************************/
_nxd_bsd_ipv6_packet_send(NX_PACKET * packet_ptr,ULONG * src_addr,ULONG * dest_addr)11935 static VOID _nxd_bsd_ipv6_packet_send(NX_PACKET *packet_ptr, ULONG *src_addr, ULONG *dest_addr)
11936 {
11937 
11938 UINT            status;
11939 ULONG           address_type;
11940 NX_IP_DRIVER    driver_request;
11941 NX_PACKET      *remove_packet;
11942 NX_PACKET      *packet_copy;
11943 UINT            same_address;
11944 NX_INTERFACE   *if_ptr;
11945 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
11946 NX_IPV6_HEADER *ip_header_ptr;
11947 #endif
11948 NX_IPV6_DESTINATION_ENTRY  *dest_entry_ptr;
11949 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
11950 UINT                        next_hop_path_mtu;
11951 NX_IPV6_DESTINATION_ENTRY  *next_hop_dest_entry_ptr;
11952 #endif
11953 NX_IP          *ip_ptr;
11954 
11955     ip_ptr = nx_bsd_default_ip;
11956 #ifndef NX_DISABLE_IP_INFO
11957 
11958     /* Increment the total send requests counter.  */
11959     ip_ptr -> nx_ip_total_packet_send_requests++;
11960 #endif
11961 
11962     if_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
11963 
11964 
11965     /* If the interface IP address is not valid (in DAD state), only ICMP is allowed */
11966     if(packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_state != NX_IPV6_ADDR_STATE_VALID)
11967     {
11968 
11969 #ifndef NX_DISABLE_IP_INFO
11970 
11971         /* Increment the IP invalid packet error.  */
11972         ip_ptr -> nx_ip_invalid_transmit_packets++;
11973 #endif
11974 
11975         /* Release the packet.  */
11976         _nx_packet_transmit_release(packet_ptr);
11977 
11978         /* Return... nothing more can be done!  */
11979         return;
11980     }
11981 
11982 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
11983     /* Build the IP header.  */
11984     ip_header_ptr = (NX_IPV6_HEADER*)packet_ptr -> nx_packet_prepend_ptr;
11985 #endif
11986 
11987     /* Check if the host is sending itself a packet. */
11988     same_address = (UINT)CHECK_IPV6_ADDRESSES_SAME(dest_addr, src_addr);
11989 
11990     /* If it is, consider this a loopback address. */
11991     if (same_address == 1)
11992     {
11993 
11994         address_type = IPV6_ADDRESS_LOOPBACK;
11995     }
11996     else
11997     {
11998 
11999         /* Otherwise check if this packet sending to a known loopback address. */
12000         address_type = IPv6_Address_Type(dest_addr);
12001     }
12002 
12003     /* Handle the internal loopback case. */
12004     if(address_type == IPV6_ADDRESS_LOOPBACK)
12005     {
12006 
12007         if(_nx_packet_copy(packet_ptr, &packet_copy, ip_ptr -> nx_ip_default_packet_pool, NX_NO_WAIT) == NX_SUCCESS)
12008         {
12009 #ifndef NX_DISABLE_IP_INFO
12010 
12011             /* Increment the IP packet sent count. */
12012             ip_ptr -> nx_ip_total_packets_sent++;
12013 
12014             /* Increment the IP bytes sent count. */
12015             ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV6_HEADER);
12016 #endif
12017 
12018             /* Send the packet to this IP's receive processing like it came in from the driver. */
12019             _nx_ip_packet_deferred_receive(ip_ptr, packet_copy);
12020         }
12021 #ifndef NX_DISABLE_IP_INFO
12022         else
12023         {
12024             /* Increment the IP send packets dropped count. */
12025             ip_ptr -> nx_ip_send_packets_dropped++;
12026 
12027             /* Increment the IP transmit resource error count. */
12028             ip_ptr -> nx_ip_transmit_resource_errors++;
12029         }
12030 #endif
12031         /* Release the transmit packet. */
12032         _nx_packet_transmit_release(packet_ptr);
12033         return;
12034 
12035     }
12036 
12037     /* Is this packet a multicast ? */
12038     if((dest_addr[0] & 0xFF000000) == 0xFF000000)
12039     {
12040 
12041 
12042         /* Set up the driver request. */
12043         driver_request.nx_ip_driver_ptr                  = ip_ptr;
12044         driver_request.nx_ip_driver_command              = NX_LINK_PACKET_SEND;
12045         driver_request.nx_ip_driver_packet               = packet_ptr;
12046         driver_request.nx_ip_driver_physical_address_msw = 0x00003333;
12047         driver_request.nx_ip_driver_physical_address_lsw = dest_addr[3];
12048         driver_request.nx_ip_driver_interface            = if_ptr;
12049 
12050 #ifndef NX_DISABLE_IP_INFO
12051 
12052         /* Increment the IP packet sent count.  */
12053         ip_ptr -> nx_ip_total_packets_sent++;
12054 
12055         /* Increment the IP bytes sent count.  */
12056         ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV6_HEADER);
12057 #endif
12058 
12059         /* Check if fragmentation is enabled. */
12060 #ifndef NX_DISABLE_FRAGMENTATION
12061 
12062         /* It is; is path MTU enabled? */
12063 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
12064 
12065         /* It is. We will check the path MTU for the packet destination to
12066            determine if we need to fragment the packet. */
12067 
12068         /* Get a pointer to the packet IP header. */
12069         ip_header_ptr = (NX_IPV6_HEADER *)packet_ptr -> nx_packet_prepend_ptr;
12070 
12071         /* Lookup the multicast destination in the destination table.  */
12072         status = _nx_icmpv6_dest_table_find(ip_ptr, ip_header_ptr -> nx_ip_header_destination_ip, &dest_entry_ptr, 0, 0);
12073 
12074         /* Did we find it in the table? */
12075         if ((status == NX_SUCCESS) && (dest_entry_ptr != NX_NULL))
12076         {
12077 
12078             /* Yes; Check the destination path MTU if fragmentation is needed.  */
12079             if ((dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu > 0) && (packet_ptr -> nx_packet_length >
12080                                                      dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu))
12081             {
12082 
12083                 /* Yes we must fragment the payload. */
12084                 _nx_ipv6_fragment_process(&driver_request, dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu);
12085 
12086                 /* This packet send is complete, just return.  */
12087                 return;
12088             }
12089 
12090             /* Packet should drop through and be checked against the IP mtu. */
12091         }
12092 
12093 #endif  /* NX_ENABLE_IPV6_PATH_MTU_DISCOVERY */
12094 
12095 
12096         /* Does the packet payload exceed our IP instance MTU?  */
12097         if (packet_ptr -> nx_packet_length > if_ptr -> nx_interface_ip_mtu_size)
12098         {
12099             /* Yes; ok to fragment the packet payload. */
12100             _nx_ipv6_fragment_process(&driver_request, if_ptr -> nx_interface_ip_mtu_size);
12101 
12102             /* This packet send is complete, just return.  */
12103             return;
12104         }
12105 
12106         /* Packet will go out unfragmented. */
12107 
12108 #endif  /* NX_DISABLE_FRAGMENTATION */
12109 
12110 
12111         /* Send the IP packet out on the network via the attached driver.  */
12112         (if_ptr -> nx_interface_link_driver_entry) (&driver_request);
12113 
12114         /* Return to caller.  */
12115         return;
12116     }
12117 
12118     /* Determine if physical mapping is needed by this link driver. */
12119     if( if_ptr && if_ptr -> nx_interface_address_mapping_needed )
12120     {
12121 
12122         /* Obtain MAC address */
12123         ND_CACHE_ENTRY *NDCacheEntry = NX_NULL;
12124         ULONG next_hop_address[4];
12125 
12126         SET_UNSPECIFIED_ADDRESS(next_hop_address);
12127 
12128         /* Lookup the packet destination in the destination table. */
12129         status = _nx_icmpv6_dest_table_find(ip_ptr, dest_addr, &dest_entry_ptr, 0, 0);
12130 
12131         /* Was a matching entry found? */
12132         if(status != NX_SUCCESS)
12133         {
12134 
12135             /* No; If the packet is either onlink or there is no default router,
12136                just copy the packet destination address to the 'next hop' address.  */
12137 
12138             if(_nxd_ipv6_search_onlink(ip_ptr, dest_addr))
12139             {
12140                 COPY_IPV6_ADDRESS(dest_addr, next_hop_address);
12141 
12142                 /* Add the next_hop in destination table. */
12143                 status = _nx_icmpv6_dest_table_add(ip_ptr, dest_addr, &dest_entry_ptr,
12144                                                    next_hop_address, if_ptr -> nx_interface_ip_mtu_size,
12145                                                    NX_WAIT_FOREVER, packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr);
12146 
12147                 /* Get the NDCacheEntry. */
12148                 if(status == NX_SUCCESS)
12149                     NDCacheEntry = dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry;
12150             }
12151 
12152             /* Check whether or not we have a default router. */
12153             else if(_nxd_ipv6_router_lookup(ip_ptr, if_ptr, next_hop_address, (VOID**)&NDCacheEntry) == NX_SUCCESS)
12154             {
12155                /* Add the next_hop in destination table. */
12156                 status = _nx_icmpv6_dest_table_add(ip_ptr, dest_addr, &dest_entry_ptr,
12157                                                    next_hop_address, if_ptr -> nx_interface_ip_mtu_size,
12158                                                    NX_WAIT_FOREVER, packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr);
12159 
12160                 /* If the default router did not has a reachable ND_CACHE_ENTRY. Get the NDCacheEntry. */
12161                 if(!NDCacheEntry)
12162                     NDCacheEntry = dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry;
12163             }
12164 
12165             /* Can not find next_hop or the destination table add failed. */
12166             if(status || ((next_hop_address[0] == 0) && (next_hop_address[1] == 0) && (next_hop_address[2] == 0) && (next_hop_address[3] == 0)))
12167             {
12168 
12169                 /* Release the packet. */
12170                 _nx_packet_release(packet_ptr);
12171 
12172                 /* Can't send it. */
12173                 return;
12174             }
12175 
12176         }
12177 
12178         /* Find a valid destination cache, set the nd cache and next hop address. */
12179         else
12180         {
12181 
12182             /* Check the NDCacheEntry is valid. */
12183             if(dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry -> nx_nd_cache_nd_status == ND_CACHE_STATE_INVALID)
12184             {
12185                 if(_nx_nd_cache_add_entry(ip_ptr, dest_addr, packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr, &dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry))
12186                 {
12187                     /* Release the packet. */
12188                     _nx_packet_release(packet_ptr);
12189 
12190                     /* Can't send it. */
12191                     return;
12192                 }
12193 
12194             }
12195 
12196             /* Get the destination and next hop address. */
12197             NDCacheEntry = dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry;
12198             COPY_IPV6_ADDRESS(dest_entry_ptr -> nx_ipv6_destination_entry_next_hop, next_hop_address);
12199         }
12200 
12201         /* According RFC2461 ch 7.3.3, as long as the entry is valid and not in INCOMPLETE state,
12202            the IP layer should use the cached link layer address.  */
12203         if((NDCacheEntry -> nx_nd_cache_nd_status >= ND_CACHE_STATE_REACHABLE) &&
12204            (NDCacheEntry -> nx_nd_cache_nd_status <= ND_CACHE_STATE_PROBE))
12205         {
12206 
12207             UCHAR *mac_addr;
12208 
12209             mac_addr = NDCacheEntry -> nx_nd_cache_mac_addr;
12210 
12211             /* Assume we find the mac */
12212             driver_request.nx_ip_driver_ptr                  = ip_ptr;
12213             driver_request.nx_ip_driver_command              = NX_LINK_PACKET_SEND;
12214             driver_request.nx_ip_driver_packet               = packet_ptr;
12215             driver_request.nx_ip_driver_physical_address_msw = (ULONG)((mac_addr[0] << 8) | mac_addr[1]);
12216             driver_request.nx_ip_driver_physical_address_lsw =
12217                 (ULONG)((mac_addr[2] << 24) | (mac_addr[3] << 16) | (mac_addr[4] << 8) | mac_addr[5]);
12218             driver_request.nx_ip_driver_interface            = if_ptr;
12219 
12220 #ifndef NX_DISABLE_FRAGMENTATION
12221 
12222             /* If the packet size is bigger than MTU, NetX Duo is enabled to fragment
12223                the packet payload. */
12224 
12225             /* Check if path MTU Discovery is enabled first. */
12226 
12227 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
12228 
12229             /* It is.  To know if we need to fragment this packet we need the path MTU for the packet
12230                destination.  */
12231 
12232             /* If this destination has a non null next hop, we need to ascertain the next hop MTU.  */
12233 
12234             /* Get the path MTU for the actual destination. */
12235             next_hop_path_mtu = dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu;
12236 
12237 
12238             /* Find the next hop in the destination table. */
12239             status = _nx_icmpv6_dest_table_find(ip_ptr, next_hop_address, &next_hop_dest_entry_ptr, 0, 0);
12240 
12241             if (status == NX_SUCCESS)
12242             {
12243 
12244                 /* Now compare the destination path MTU with the next hop path MTU*/
12245                 if ((next_hop_dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu > 0) &&
12246                     (next_hop_path_mtu > next_hop_dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu))
12247                 {
12248 
12249                     /* Update the path mtu to reflect the next hop route. */
12250                     next_hop_path_mtu = next_hop_dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu;
12251                 }
12252             }
12253 
12254             /* Yes; Check the destination path MTU if fragmentation is needed.  */
12255             if ((next_hop_path_mtu > 0) &&
12256                 (packet_ptr -> nx_packet_length > next_hop_path_mtu))
12257             {
12258 
12259                 /* Yes we must fragment the payload. */
12260                 _nx_ipv6_fragment_process(&driver_request, next_hop_path_mtu);
12261 
12262                 /* This packet send is complete, just return.  */
12263                 return;
12264             }
12265 #endif  /* NX_ENABLE_IPV6_PATH_MTU_DISCOVERY */
12266 
12267             /* Send packet unfragmented. */
12268 
12269             /* If we didn't find anything in the destination table, let the packet drop through.  NetX Duo
12270                will check our IP instance MTU if fragmentation is needed before sending. */
12271 
12272 
12273             /* Does the packet payload exceed our IP instance MTU?  */
12274             if (packet_ptr -> nx_packet_length > if_ptr -> nx_interface_ip_mtu_size)
12275             {
12276                 /* Yes; ok to fragment the packet payload. */
12277                 _nx_ipv6_fragment_process(&driver_request, if_ptr -> nx_interface_ip_mtu_size);
12278 
12279                 /* This packet send is complete, just return.  */
12280                 return;
12281             }
12282 
12283             /* The packet requires no fragmentation. Proceed with sending the packet. */
12284 
12285 #endif /* NX_DISABLE_FRAGMENTATION */
12286 
12287 
12288 #ifndef NX_DISABLE_IP_INFO
12289 
12290             /* Increment the IP packet sent count.  */
12291             ip_ptr -> nx_ip_total_packets_sent++;
12292 
12293             /* Increment the IP bytes sent count.  */
12294             ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV6_HEADER);
12295 #endif
12296 
12297             /* Send the IP packet out on the network via the attached driver.  */
12298             (if_ptr -> nx_interface_link_driver_entry) (&driver_request);
12299 
12300             /* If the entry is in STALE state, move it to DELAY state. */
12301             if(NDCacheEntry -> nx_nd_cache_nd_status == ND_CACHE_STATE_STALE)
12302             {
12303                 NDCacheEntry -> nx_nd_cache_nd_status = ND_CACHE_STATE_DELAY;
12304 
12305                 /* Start the Delay first probe timer */
12306                 NDCacheEntry -> nx_nd_cache_timer_tick = NX_DELAY_FIRST_PROBE_TIME;
12307 
12308             }
12309 
12310             /* Return to caller.  */
12311             return;
12312         }
12313 
12314         /* No MAC address was found in our cache table.  Start the Neighbor Discovery (ND)
12315            process to get it. */
12316 
12317         /* Ensure the current packet's queue next pointer to NULL */
12318         packet_ptr -> nx_packet_queue_next = NX_NULL;
12319 
12320         /* Determine if the queue is empty. */
12321         if(NDCacheEntry -> nx_nd_cache_packet_waiting_head == NX_NULL)
12322         {
12323             /* ICMPv6 is enabled */
12324             if(ip_ptr -> nx_ip_icmpv6_packet_process)
12325             {
12326 
12327                 /* Queue up this packet */
12328                 NDCacheEntry -> nx_nd_cache_packet_waiting_head = packet_ptr;
12329                 NDCacheEntry -> nx_nd_cache_packet_waiting_tail = packet_ptr;
12330                 NDCacheEntry -> nx_nd_cache_packet_waiting_queue_length = 1;
12331 
12332                 /* Set the outgoing address and interface to the cache entry.  */
12333                 NDCacheEntry -> nx_nd_cache_outgoing_address = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr;
12334                 NDCacheEntry -> nx_nd_cache_interface_ptr = if_ptr;
12335 
12336                 /* Is this a new entry? */
12337                 if(NDCacheEntry -> nx_nd_cache_nd_status == ND_CACHE_STATE_CREATED)
12338                 {
12339 
12340                     /* Start Neighbor discovery process by advancing to the incomplete state. */
12341                     NDCacheEntry -> nx_nd_cache_nd_status = ND_CACHE_STATE_INCOMPLETE;
12342                 }
12343 
12344                 _nx_icmpv6_send_ns(ip_ptr, next_hop_address,
12345                                    1, packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr, 0, NX_NULL);
12346 
12347                 NDCacheEntry -> nx_nd_cache_num_solicit = NX_MAX_MULTICAST_SOLICIT - 1;
12348                 NDCacheEntry -> nx_nd_cache_timer_tick = ip_ptr -> nx_ipv6_retrans_timer_ticks;
12349 
12350             }
12351             else
12352             {
12353 
12354                 _nx_packet_transmit_release(packet_ptr);
12355 #ifndef NX_DISABLE_IP_INFO
12356 
12357                 /* Increment the IP transmit resource error count.  */
12358                 ip_ptr -> nx_ip_transmit_resource_errors++;
12359 
12360                 /* Increment the IP send packets dropped count.  */
12361                 ip_ptr -> nx_ip_send_packets_dropped++;
12362 #endif
12363             }
12364             return;
12365         }
12366 
12367         /* The ND process already started.  Simply queue up this packet */
12368         NDCacheEntry -> nx_nd_cache_packet_waiting_tail -> nx_packet_queue_next = packet_ptr;
12369         NDCacheEntry -> nx_nd_cache_packet_waiting_tail = packet_ptr;
12370         NDCacheEntry -> nx_nd_cache_packet_waiting_queue_length++;
12371 
12372         /* Check if the number of packets enqueued exceeds the allowed number. */
12373         if(NDCacheEntry -> nx_nd_cache_packet_waiting_queue_length > NX_ND_MAX_QUEUE_DEPTH)
12374         {
12375 
12376             /* Yes, so delete the first packet. */
12377             remove_packet = NDCacheEntry -> nx_nd_cache_packet_waiting_head;
12378 
12379             NDCacheEntry -> nx_nd_cache_packet_waiting_head = remove_packet -> nx_packet_queue_next;
12380 
12381             /* Update the queued packet count for this cache entry. */
12382             NDCacheEntry -> nx_nd_cache_packet_waiting_queue_length--;
12383 
12384             _nx_packet_transmit_release(remove_packet);
12385 #ifndef NX_DISABLE_IP_INFO
12386             /* Increment the IP transmit resource error count.  */
12387             ip_ptr -> nx_ip_transmit_resource_errors++;
12388 
12389             /* Increment the IP send packets dropped count.  */
12390             ip_ptr -> nx_ip_send_packets_dropped++;
12391 #endif
12392         }
12393 
12394         return;
12395     }
12396 
12397     /* For now do nothing. Just release the packet */
12398     _nx_packet_release(packet_ptr);
12399 }
12400 
12401 #endif /* FEATURE_NX_IPV6 */
12402 
12403 #if defined(FEATURE_NX_IPV6) && defined(NX_ENABLE_IP_RAW_PACKET_FILTER)
12404 /**************************************************************************/
12405 /*                                                                        */
12406 /*  FUNCTION                                               RELEASE        */
12407 /*                                                                        */
12408 /*    _nxd_bsd_swap_ipv6_extension_headers                PORTABLE C      */
12409 /*                                                           6.1          */
12410 /*  AUTHOR                                                                */
12411 /*                                                                        */
12412 /*    Yuxin Zhou, Microsoft Corporation                                   */
12413 /*                                                                        */
12414 /*  DESCRIPTION                                                           */
12415 /*                                                                        */
12416 /*    This function performs endian swap operations on the IPv6           */
12417 /*    extension headers.                                                  */
12418 /*                                                                        */
12419 /*  INPUT                                                                 */
12420 /*                                                                        */
12421 /*    packet_ptr                            Pointer to packet             */
12422 /*    header_type                           Type of the first extension   */
12423 /*                                            header                      */
12424 /*                                                                        */
12425 /*  OUTPUT                                                                */
12426 /*                                                                        */
12427 /*    None                                                                */
12428 /*                                                                        */
12429 /*  CALLS                                                                 */
12430 /*                                                                        */
12431 /*    NX_CHANGE_USHORT_ENDIAN               Swap endian-ness on 16-bit    */
12432 /*                                            integer.                    */
12433 /*                                                                        */
12434 /*  CALLED BY                                                             */
12435 /*                                                                        */
12436 /*    NetX Duo BSD Layer Source Code                                      */
12437 /*                                                                        */
12438 /*  RELEASE HISTORY                                                       */
12439 /*                                                                        */
12440 /*    DATE              NAME                      DESCRIPTION             */
12441 /*                                                                        */
12442 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12443 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12444 /*                                            resulting in version 6.1    */
12445 /*                                                                        */
12446 /**************************************************************************/
_nxd_bsd_swap_ipv6_extension_headers(NX_PACKET * packet_ptr,UCHAR header_type)12447 static VOID  _nxd_bsd_swap_ipv6_extension_headers(NX_PACKET *packet_ptr, UCHAR header_type)
12448 {
12449 UCHAR                           *scan_ptr;
12450 ULONG                           remaining_bytes;
12451 ULONG                           header_length = 40;
12452 NX_IPV6_HEADER_OPTION           *option;
12453 
12454 
12455     remaining_bytes = (ULONG)packet_ptr -> nx_packet_prepend_ptr - (ULONG)packet_ptr -> nx_packet_ip_header;
12456 
12457     scan_ptr = packet_ptr -> nx_packet_ip_header;
12458 
12459     remaining_bytes -= header_length;
12460     scan_ptr += header_length;
12461 
12462     while(remaining_bytes)
12463     {
12464         option = (NX_IPV6_HEADER_OPTION*)scan_ptr;
12465         switch(header_type)
12466         {
12467         case NX_PROTOCOL_NEXT_HEADER_HOP_BY_HOP:
12468 
12469             break;
12470 
12471         case NX_PROTOCOL_NEXT_HEADER_DESTINATION:
12472 
12473             break;
12474 
12475         case NX_PROTOCOL_NEXT_HEADER_ROUTING:
12476             break;
12477 
12478 
12479         case NX_PROTOCOL_NEXT_HEADER_FRAGMENT:
12480             NX_CHANGE_USHORT_ENDIAN(((NX_IPV6_HEADER_FRAGMENT_OPTION *)scan_ptr) -> nx_ipv6_header_fragment_option_offset_flag);
12481             break;
12482 
12483         default:
12484 
12485             break;
12486         }
12487 
12488         header_type = option -> nx_ipv6_header_option_next_header;
12489 
12490         if(header_type == NX_PROTOCOL_NEXT_HEADER_AUTHENTICATION)
12491             header_length = (ULONG)((option -> nx_ipv6_header_option_ext_length << 2) + 2);
12492         else
12493             header_length = (ULONG)((option -> nx_ipv6_header_option_ext_length + 1) << 3);
12494 
12495 
12496         remaining_bytes -= header_length;
12497         scan_ptr += header_length;
12498     }
12499 }
12500 #endif  /* defined(FEATURE_NX_IPV6) && defined(NX_ENABLE_IP_RAW_PACKET_FILTER) */
12501 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
12502 
12503 
12504 /**************************************************************************/
12505 /*                                                                        */
12506 /*  FUNCTION                                               RELEASE        */
12507 /*                                                                        */
12508 /*    nx_bsd_pppoe_internal_sendto                        PORTABLE C      */
12509 /*                                                           6.3.0        */
12510 /*  AUTHOR                                                                */
12511 /*                                                                        */
12512 /*    Yuxin Zhou, Microsoft Corporation                                   */
12513 /*                                                                        */
12514 /*  DESCRIPTION                                                           */
12515 /*                                                                        */
12516 /*    This function sends raw PPPOE packet to driver directly.            */
12517 /*                                                                        */
12518 /*  INPUT                                                                 */
12519 /*                                                                        */
12520 /*    bsd_socket_ptr                        Pointer to bsd socket         */
12521 /*    msg                                   Message to send               */
12522 /*    msgLength                             Length of message             */
12523 /*    flags                                 Flags                         */
12524 /*    destAddr                              Pointer to destination address*/
12525 /*    destAddrLen                           Length of destination address */
12526 /*                                                                        */
12527 /*  OUTPUT                                                                */
12528 /*                                                                        */
12529 /*    msgLength                             On success                    */
12530 /*    NX_SOC_ERROR (-1)                     On failure                    */
12531 /*                                                                        */
12532 /*  CALLS                                                                 */
12533 /*                                                                        */
12534 /*    nx_packet_allocate                    Allocate a packet             */
12535 /*    nx_packet_data_append                 Append data to the packet     */
12536 /*    nx_packet_release                     Release the packet on error   */
12537 /*    tx_mutex_get                          Obtain exclusive access to    */
12538 /*    tx_mutex_put                          Release exclusive access      */
12539 /*                                                                        */
12540 /*  CALLED BY                                                             */
12541 /*                                                                        */
12542 /*    Application Code                                                    */
12543 /*                                                                        */
12544 /*  RELEASE HISTORY                                                       */
12545 /*                                                                        */
12546 /*    DATE              NAME                      DESCRIPTION             */
12547 /*                                                                        */
12548 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12549 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12550 /*                                            resulting in version 6.1    */
12551 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
12552 /*                                            used new API/structs naming,*/
12553 /*                                            resulting in version 6.3.0  */
12554 /*                                                                        */
12555 /**************************************************************************/
nx_bsd_pppoe_internal_sendto(NX_BSD_SOCKET * bsd_socket_ptr,CHAR * msg,INT msgLength,INT flags,struct nx_bsd_sockaddr * destAddr,INT destAddrLen)12556 static INT nx_bsd_pppoe_internal_sendto(NX_BSD_SOCKET *bsd_socket_ptr, CHAR *msg, INT msgLength, INT flags,  struct nx_bsd_sockaddr* destAddr, INT destAddrLen)
12557 {
12558 UINT                if_index;
12559 struct nx_bsd_sockaddr_ll
12560                     *destAddr_ll;
12561 #if 0
12562 ULONG               src_mac_msw;
12563 ULONG               src_mac_lsw;
12564 #endif
12565 NX_IP_DRIVER        driver_request;
12566 UINT                status;
12567 NX_PACKET          *packet_ptr = NX_NULL;
12568 
12569     NX_PARAMETER_NOT_USED(bsd_socket_ptr);
12570     NX_PARAMETER_NOT_USED(flags);
12571 
12572     /* Validate the parameters. */
12573     if(destAddr == NX_NULL)
12574     {
12575         /* Set the socket error if extended socket options enabled. */
12576         nx_bsd_set_errno(EINVAL);
12577 
12578         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12579         return(NX_SOC_ERROR);
12580     }
12581 
12582     if(destAddr -> sa_family != AF_PACKET)
12583     {
12584         /* Set the socket error if extended socket options enabled. */
12585         nx_bsd_set_errno(EINVAL);
12586 
12587         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12588         return(NX_SOC_ERROR);
12589     }
12590 
12591     if(destAddrLen != sizeof(struct nx_bsd_sockaddr_ll))
12592     {
12593         /* Set the socket error if extended socket options enabled. */
12594         nx_bsd_set_errno(EINVAL);
12595 
12596         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12597         return(NX_SOC_ERROR);
12598     }
12599 
12600     destAddr_ll = (struct nx_bsd_sockaddr_ll*)destAddr;
12601 
12602     if((destAddr_ll -> sll_protocol != ETHERTYPE_PPPOE_SESS) && (destAddr_ll -> sll_protocol != ETHERTYPE_PPPOE_DISC))
12603     {
12604         /* Set the socket error if extended socket options enabled. */
12605         nx_bsd_set_errno(EINVAL);
12606 
12607         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12608         return(NX_SOC_ERROR);
12609     }
12610 
12611     /* Validate the interface ID */
12612     if_index = (UINT)(destAddr_ll -> sll_ifindex);
12613     if(if_index >= NX_MAX_IP_INTERFACES)
12614     {
12615         /* Set the socket error if extended socket options enabled. */
12616         nx_bsd_set_errno(EINVAL);
12617 
12618         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12619         return(NX_SOC_ERROR);
12620     }
12621 
12622     if(nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_valid == 0)
12623     {
12624         /* Set the socket error if extended socket options enabled. */
12625         nx_bsd_set_errno(EINVAL);
12626 
12627         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12628         return(NX_SOC_ERROR);
12629     }
12630 
12631 #if 0
12632     /* Pickup the source MAC address */
12633     src_mac_msw = nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_physical_address_msw;
12634     src_mac_lsw = nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_physical_address_lsw;
12635 #endif
12636 
12637 
12638 
12639     /* Validate the packet length */
12640     if(msgLength > (INT)(nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_ip_mtu_size + 14))
12641     {
12642         /* Set the socket error if extended socket options enabled. */
12643         nx_bsd_set_errno(EINVAL);
12644 
12645         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12646         return(NX_SOC_ERROR);
12647     }
12648 
12649     /* FIXME:  If the socket is non-blocking, Timeout value should be set to 0 */
12650     status = nx_packet_allocate(nx_bsd_default_packet_pool, &packet_ptr, NX_PHYSICAL_HEADER, NX_NO_WAIT);
12651 
12652     /* Check for errors.   */
12653     if (status != NX_SUCCESS)
12654     {
12655 
12656         /* Set the socket error.  */
12657         nx_bsd_set_errno(ENOBUFS);
12658 
12659         /* Return an error status.*/
12660         NX_BSD_ERROR(status, __LINE__);
12661         return(NX_SOC_ERROR);
12662     }
12663 
12664 
12665 
12666     /* Now copy the data into the NetX packet.  */
12667     status =  nx_packet_data_append(packet_ptr, (VOID *) msg, (ULONG)msgLength, nx_bsd_default_packet_pool, NX_NO_WAIT);
12668 
12669     /* Was the data copy successful?  */
12670     if (status != NX_SUCCESS)
12671     {
12672 
12673         nx_packet_release(packet_ptr);
12674 
12675         /* Set the socket error.  */
12676         nx_bsd_set_errno(ENOBUFS);
12677 
12678         /* Return an error status.*/
12679         NX_BSD_ERROR(status, __LINE__);
12680         return(NX_SOC_ERROR);
12681     }
12682 
12683     /* Now ready to transmit this packet. */
12684     driver_request.nx_ip_driver_ptr =                   nx_bsd_default_ip;
12685     if(destAddr_ll -> sll_protocol == ETHERTYPE_PPPOE_SESS)
12686         driver_request.nx_ip_driver_command =           NX_LINK_PACKET_PPPOE_SESS_SEND;
12687     else
12688         driver_request.nx_ip_driver_command =           NX_LINK_PACKET_PPPOE_DISC_SEND;
12689     driver_request.nx_ip_driver_packet =                packet_ptr;
12690     driver_request.nx_ip_driver_interface =             &nx_bsd_default_ip -> nx_ip_interface[if_index];
12691 
12692     /* Obtain the BSD lock. */
12693     status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
12694 
12695     /* Check the status.  */
12696     if (status != NX_SUCCESS)
12697     {
12698 
12699         nx_packet_release(packet_ptr);
12700 
12701         /* Set the socket error if extended socket options enabled. */
12702         nx_bsd_set_errno(EACCES);
12703 
12704         /* Return an error. */
12705         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
12706         return(NX_SOC_ERROR);
12707     }
12708 
12709     (driver_request.nx_ip_driver_interface -> nx_interface_link_driver_entry)(&driver_request);
12710 
12711     /* Release the mutex. */
12712     tx_mutex_put(nx_bsd_protection_ptr);
12713 
12714     return(msgLength);
12715 }
12716 
12717 
12718 /**************************************************************************/
12719 /*                                                                        */
12720 /*  FUNCTION                                               RELEASE        */
12721 /*                                                                        */
12722 /*    _nx_bsd_pppoe_packet_received                       PORTABLE C      */
12723 /*                                                           6.1          */
12724 /*  AUTHOR                                                                */
12725 /*                                                                        */
12726 /*    Yuxin Zhou, Microsoft Corporation                                   */
12727 /*                                                                        */
12728 /*  DESCRIPTION                                                           */
12729 /*                                                                        */
12730 /*    This function receives raw PPPOE packet from driver directly.       */
12731 /*                                                                        */
12732 /*  INPUT                                                                 */
12733 /*                                                                        */
12734 /*    packet_ptr                            Pointer to received packet    */
12735 /*    frame_type                            Type of frame                 */
12736 /*    interface_id                          Interface ID                  */
12737 /*                                                                        */
12738 /*  OUTPUT                                                                */
12739 /*                                                                        */
12740 /*    NX_SUCCESS                                                          */
12741 /*                                                                        */
12742 /*  CALLS                                                                 */
12743 /*                                                                        */
12744 /*    nx_bsd_select_wakeup                  Wake up any asychronous       */
12745 /*                                            receive call                */
12746 /*    nx_packet_release                     Release the packet on error   */
12747 /*                                                                        */
12748 /*  CALLED BY                                                             */
12749 /*                                                                        */
12750 /*    Application Code                                                    */
12751 /*                                                                        */
12752 /*  RELEASE HISTORY                                                       */
12753 /*                                                                        */
12754 /*    DATE              NAME                      DESCRIPTION             */
12755 /*                                                                        */
12756 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12757 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12758 /*                                            resulting in version 6.1    */
12759 /*                                                                        */
12760 /**************************************************************************/
_nx_bsd_pppoe_packet_received(NX_PACKET * packet_ptr,UINT frame_type,UINT interface_id)12761 UINT _nx_bsd_pppoe_packet_received(NX_PACKET *packet_ptr, UINT frame_type, UINT interface_id)
12762 {
12763 
12764 UINT i;
12765 UINT sockid = NX_BSD_MAX_SOCKETS;
12766 UINT create_id = 0xFFFFFFFF;
12767 NX_BSD_SOCKET *bsd_ptr;
12768 
12769     NX_PARAMETER_NOT_USED(interface_id);
12770 
12771     /* Find the socket with the lowest create-ID.  Put the packet into the socket's recevie queue. */
12772     for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
12773     {
12774         if((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE) &&
12775           /*
12776           (nx_bsd_socket_array[i].nx_bsd_raw_socket_enabled == NX_TRUE) &&
12777           */
12778                 (nx_bsd_socket_array[i].nx_bsd_socket_family == AF_PACKET) &&
12779                 (nx_bsd_socket_array[i].nx_bsd_socket_protocol == frame_type))
12780         {
12781             if(nx_bsd_socket_array[i].nx_bsd_socket_create_id < create_id)
12782             {
12783                 sockid = i;
12784                 create_id = nx_bsd_socket_array[i].nx_bsd_socket_create_id;
12785             }
12786         }
12787     }
12788     if(sockid == NX_BSD_MAX_SOCKETS)
12789     {
12790         /* No BSD sockets are avaialble for this frame type. */
12791         nx_packet_release(packet_ptr);
12792         return(NX_SUCCESS);
12793     }
12794     /* Now we need to put the packet into the socket. */
12795     bsd_ptr = &nx_bsd_socket_array[sockid];
12796 
12797     /* Drop the packet if the receive queue exceeds max depth. */
12798     if(bsd_ptr -> nx_bsd_socket_received_packet_count >=
12799             bsd_ptr -> nx_bsd_socket_received_packet_count_max)
12800     {
12801         nx_packet_release(packet_ptr);
12802         return(NX_SUCCESS);
12803     }
12804 
12805     if(bsd_ptr -> nx_bsd_socket_received_packet)
12806     {
12807         bsd_ptr -> nx_bsd_socket_received_packet_tail -> nx_packet_queue_next = packet_ptr;
12808     }
12809     else
12810     {
12811         bsd_ptr -> nx_bsd_socket_received_packet = packet_ptr;
12812         bsd_ptr -> nx_bsd_socket_received_packet_offset = 0;
12813     }
12814 
12815     bsd_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
12816     bsd_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
12817     bsd_ptr -> nx_bsd_socket_received_packet_count ++;
12818 
12819     nx_bsd_select_wakeup(sockid, FDSET_READ);
12820 
12821     return 0;
12822 }
12823 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
12824 
12825 #ifdef NX_BSD_RAW_SUPPORT
12826 
12827 /**************************************************************************/
12828 /*                                                                        */
12829 /*  FUNCTION                                               RELEASE        */
12830 /*                                                                        */
12831 /*    _nx_bsd_hardware_internal_sendto                    PORTABLE C      */
12832 /*                                                           6.1          */
12833 /*  AUTHOR                                                                */
12834 /*                                                                        */
12835 /*    Yuxin Zhou, Microsoft Corporation                                   */
12836 /*                                                                        */
12837 /*  DESCRIPTION                                                           */
12838 /*                                                                        */
12839 /*    This function sends raw packet to driver directly.                  */
12840 /*                                                                        */
12841 /*  INPUT                                                                 */
12842 /*                                                                        */
12843 /*    bsd_socket_ptr                        Pointer to bsd socket         */
12844 /*    msg                                   Message to send               */
12845 /*    msgLength                             Length of message             */
12846 /*    flags                                 Flags                         */
12847 /*    destAddr                              Pointer to destination address*/
12848 /*    destAddrLen                           Length of destination address */
12849 /*                                                                        */
12850 /*  OUTPUT                                                                */
12851 /*                                                                        */
12852 /*    msgLength                             On success                    */
12853 /*    NX_SOC_ERROR (-1)                     On failure                    */
12854 /*                                                                        */
12855 /*  CALLS                                                                 */
12856 /*                                                                        */
12857 /*    nx_packet_allocate                    Allocate a packet             */
12858 /*    nx_packet_data_append                 Append data to the packet     */
12859 /*    nx_packet_release                     Release the packet on error   */
12860 /*    tx_mutex_get                          Obtain exclusive access to    */
12861 /*    tx_mutex_put                          Release exclusive access      */
12862 /*                                                                        */
12863 /*  CALLED BY                                                             */
12864 /*                                                                        */
12865 /*    Application Code                                                    */
12866 /*                                                                        */
12867 /*  RELEASE HISTORY                                                       */
12868 /*                                                                        */
12869 /*    DATE              NAME                      DESCRIPTION             */
12870 /*                                                                        */
12871 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12872 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12873 /*                                            resulting in version 6.1    */
12874 /*                                                                        */
12875 /**************************************************************************/
_nx_bsd_hardware_internal_sendto(NX_BSD_SOCKET * bsd_socket_ptr,CHAR * msg,INT msgLength,INT flags,struct nx_bsd_sockaddr * destAddr,INT destAddrLen)12876 static INT _nx_bsd_hardware_internal_sendto(NX_BSD_SOCKET *bsd_socket_ptr, CHAR *msg, INT msgLength, INT flags,  struct nx_bsd_sockaddr* destAddr, INT destAddrLen)
12877 {
12878 UINT                if_index;
12879 struct nx_bsd_sockaddr_ll
12880                    *destAddr_ll;
12881 UINT                status;
12882 NX_PACKET          *packet_ptr = NX_NULL;
12883 
12884     NX_PARAMETER_NOT_USED(bsd_socket_ptr);
12885     NX_PARAMETER_NOT_USED(flags);
12886 
12887     /* Validate the parameters. */
12888     if(destAddr == NX_NULL)
12889     {
12890         /* Set the socket error if extended socket options enabled. */
12891         nx_bsd_set_errno(EINVAL);
12892 
12893         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12894         return(NX_SOC_ERROR);
12895     }
12896 
12897     if(destAddr -> sa_family != AF_PACKET)
12898     {
12899         /* Set the socket error if extended socket options enabled. */
12900         nx_bsd_set_errno(EINVAL);
12901 
12902         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12903         return(NX_SOC_ERROR);
12904     }
12905 
12906     if(destAddrLen != sizeof(struct nx_bsd_sockaddr_ll))
12907     {
12908         /* Set the socket error if extended socket options enabled. */
12909         nx_bsd_set_errno(EINVAL);
12910 
12911         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12912         return(NX_SOC_ERROR);
12913     }
12914 
12915     destAddr_ll = (struct nx_bsd_sockaddr_ll*)destAddr;
12916 
12917     /* Validate the interface ID */
12918     if_index = (UINT)(destAddr_ll -> sll_ifindex);
12919     if(if_index >= NX_MAX_IP_INTERFACES)
12920     {
12921         /* Set the socket error if extended socket options enabled. */
12922         nx_bsd_set_errno(EINVAL);
12923 
12924         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12925         return(NX_SOC_ERROR);
12926     }
12927 
12928     if(nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_valid == 0)
12929     {
12930         /* Set the socket error if extended socket options enabled. */
12931         nx_bsd_set_errno(EINVAL);
12932 
12933         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12934         return(NX_SOC_ERROR);
12935     }
12936 
12937     /* Validate the packet length */
12938     if(msgLength > (INT)(nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_ip_mtu_size + 18))
12939     {
12940         /* Set the socket error if extended socket options enabled. */
12941         nx_bsd_set_errno(EINVAL);
12942 
12943         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12944         return(NX_SOC_ERROR);
12945     }
12946 
12947     status = nx_packet_allocate(nx_bsd_default_packet_pool, &packet_ptr, NX_PHYSICAL_HEADER, NX_NO_WAIT);
12948 
12949     /* Check for errors.   */
12950     if (status != NX_SUCCESS)
12951     {
12952 
12953         /* Set the socket error.  */
12954         nx_bsd_set_errno(ENOBUFS);
12955 
12956         /* Return an error status.*/
12957         NX_BSD_ERROR(status, __LINE__);
12958         return(NX_SOC_ERROR);
12959     }
12960 
12961     /* Set IP interface. */
12962     packet_ptr -> nx_packet_ip_interface = &nx_bsd_default_ip -> nx_ip_interface[if_index];
12963 
12964     /* Now copy the data into the NetX packet.  */
12965     status =  nx_packet_data_append(packet_ptr, (VOID *) msg, (ULONG)msgLength, nx_bsd_default_packet_pool, NX_NO_WAIT);
12966 
12967     /* Was the data copy successful?  */
12968     if (status != NX_SUCCESS)
12969     {
12970 
12971         nx_packet_release(packet_ptr);
12972 
12973         /* Set the socket error.  */
12974         nx_bsd_set_errno(ENOBUFS);
12975 
12976         /* Return an error status.*/
12977         NX_BSD_ERROR(status, __LINE__);
12978         return(NX_SOC_ERROR);
12979     }
12980 
12981 #if defined(__PRODUCT_NETXDUO__) && defined(NX_ENABLE_INTERFACE_CAPABILITY)
12982     packet_ptr -> nx_packet_interface_capability_flag = nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_capability_flag;
12983 #endif /* defined(__PRODUCT_NETXDUO__) && defined(NX_ENABLE_INTERFACE_CAPABILITY) */
12984 
12985     /* Obtain the BSD lock. */
12986     status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
12987 
12988     /* Check the status.  */
12989     if (status != NX_SUCCESS)
12990     {
12991 
12992         nx_packet_release(packet_ptr);
12993 
12994         /* Set the socket error if extended socket options enabled. */
12995         nx_bsd_set_errno(EACCES);
12996 
12997         /* Return an error. */
12998         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
12999         return(NX_SOC_ERROR);
13000     }
13001 
13002     _nx_driver_hardware_packet_send(packet_ptr);
13003 
13004     /* Release the mutex. */
13005     tx_mutex_put(nx_bsd_protection_ptr);
13006 
13007     return(msgLength);
13008 }
13009 
13010 
13011 /**************************************************************************/
13012 /*                                                                        */
13013 /*  FUNCTION                                               RELEASE        */
13014 /*                                                                        */
13015 /*    _nx_bsd_hardware_packet_received                    PORTABLE C      */
13016 /*                                                           6.1          */
13017 /*  AUTHOR                                                                */
13018 /*                                                                        */
13019 /*    Yuxin Zhou, Microsoft Corporation                                   */
13020 /*                                                                        */
13021 /*  DESCRIPTION                                                           */
13022 /*                                                                        */
13023 /*    This function receives raw packet from driver directly.             */
13024 /*                                                                        */
13025 /*  INPUT                                                                 */
13026 /*                                                                        */
13027 /*    packet_ptr                            Pointer to received packet    */
13028 /*    consumed                              Return packet consumed or not */
13029 /*                                                                        */
13030 /*  OUTPUT                                                                */
13031 /*                                                                        */
13032 /*    None                                                                */
13033 /*                                                                        */
13034 /*  CALLS                                                                 */
13035 /*                                                                        */
13036 /*    nx_bsd_select_wakeup                  Wake up any asychronous       */
13037 /*                                            receive call                */
13038 /*                                                                        */
13039 /*  CALLED BY                                                             */
13040 /*                                                                        */
13041 /*    Application Code                                                    */
13042 /*                                                                        */
13043 /*  RELEASE HISTORY                                                       */
13044 /*                                                                        */
13045 /*    DATE              NAME                      DESCRIPTION             */
13046 /*                                                                        */
13047 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13048 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13049 /*                                            resulting in version 6.1    */
13050 /*                                                                        */
13051 /**************************************************************************/
_nx_bsd_hardware_packet_received(NX_PACKET * packet_ptr,UCHAR * consumed)13052 static VOID  _nx_bsd_hardware_packet_received(NX_PACKET *packet_ptr, UCHAR *consumed)
13053 {
13054 
13055 UINT i;
13056 UINT sockid = NX_BSD_MAX_SOCKETS;
13057 NX_BSD_SOCKET *bsd_ptr;
13058 
13059     /* Initialize the consumed to be false. */
13060     *consumed = NX_FALSE;
13061 
13062     /* Find the socket with the matching interface.  Put the packet into the socket's recevie queue. */
13063     for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
13064     {
13065         if((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE) &&
13066                 (nx_bsd_socket_array[i].nx_bsd_socket_family == AF_PACKET) &&
13067                 ((nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY) ||
13068                  (nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface == (ULONG)(packet_ptr -> nx_packet_ip_interface))))
13069         {
13070             sockid = i;
13071         }
13072     }
13073     if(sockid == NX_BSD_MAX_SOCKETS)
13074     {
13075         /* No BSD sockets are avaialble for this frame type. */
13076         return;
13077     }
13078     /* Now we need to put the packet into the socket. */
13079     bsd_ptr = &nx_bsd_socket_array[sockid];
13080 
13081     /* Drop the packet if the receive queue exceeds max depth. */
13082     if(bsd_ptr -> nx_bsd_socket_received_packet_count >=
13083             bsd_ptr -> nx_bsd_socket_received_packet_count_max)
13084     {
13085         return;
13086     }
13087 
13088 #ifndef NX_DISABLE_BSD_RAW_PACKET_DUPLICATE
13089     /* Duplicate the packet. */
13090     if (nx_packet_copy(packet_ptr, &packet_ptr, nx_bsd_default_packet_pool, NX_NO_WAIT) != NX_SUCCESS)
13091     {
13092         return;
13093     }
13094 #else
13095     /* Consume the packet. IP layer will not see it. */
13096     *consumed = NX_TRUE;
13097 #endif /* NX_DISABLE_BSD_RAW_PACKET_DUPLICATE */
13098 
13099     if(bsd_ptr -> nx_bsd_socket_received_packet)
13100     {
13101         bsd_ptr -> nx_bsd_socket_received_packet_tail -> nx_packet_queue_next = packet_ptr;
13102     }
13103     else
13104     {
13105         bsd_ptr -> nx_bsd_socket_received_packet = packet_ptr;
13106         bsd_ptr -> nx_bsd_socket_received_packet_offset = 0;
13107     }
13108 
13109     bsd_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
13110     bsd_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
13111     bsd_ptr -> nx_bsd_socket_received_packet_count ++;
13112 
13113     nx_bsd_select_wakeup(sockid, FDSET_READ);
13114 
13115     return;
13116 }
13117 #endif /* NX_BSD_RAW_SUPPORT */
13118 
13119 
13120 
13121 /**************************************************************************/
13122 /*                                                                        */
13123 /*  FUNCTION                                               RELEASE        */
13124 /*                                                                        */
13125 /*    inet_pton                                           PORTABLE C      */
13126 /*                                                           6.3.0        */
13127 /*  AUTHOR                                                                */
13128 /*                                                                        */
13129 /*    Yuxin Zhou, Microsoft Corporation                                   */
13130 /*                                                                        */
13131 /*  DESCRIPTION                                                           */
13132 /*                                                                        */
13133 /*    This function converts an IP address from  presentation to numeric. */
13134 /*                                                                        */
13135 /*  INPUT                                                                 */
13136 /*                                                                        */
13137 /*    af                                    Either AF_INET or AF_INET6    */
13138 /*    src                                   A pointer pointing to the     */
13139 /*                                            presentation of IP address  */
13140 /*    dst                                   A pointer pointing to the     */
13141 /*                                            destination memory          */
13142 /*                                                                        */
13143 /*  OUTPUT                                                                */
13144 /*                                                                        */
13145 /*    status                                1 OK                          */
13146 /*                                          0 invalid presentation        */
13147 /*                                          -1 error                      */
13148 /*                                                                        */
13149 /*  CALLS                                                                 */
13150 /*                                                                        */
13151 /*    inet_aton                             Convert IPv4 address from     */
13152 /*                                          presentation to numeric       */
13153 /*                                                                        */
13154 /*  CALLED BY                                                             */
13155 /*                                                                        */
13156 /*    Application Code                                                    */
13157 /*                                                                        */
13158 /*  RELEASE HISTORY                                                       */
13159 /*                                                                        */
13160 /*    DATE              NAME                      DESCRIPTION             */
13161 /*                                                                        */
13162 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13163 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13164 /*                                            resulting in version 6.1    */
13165 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
13166 /*                                            used new API/structs naming,*/
13167 /*                                            resulting in version 6.3.0  */
13168 /*                                                                        */
13169 /**************************************************************************/
nx_bsd_inet_pton(INT af,const CHAR * src,VOID * dst)13170 INT  nx_bsd_inet_pton(INT af, const CHAR *src, VOID *dst)
13171 {
13172 CHAR    ch;
13173 USHORT  value;
13174 /* A number used to convert a character in '0123456789abcdefABCDEF'  to a number. */
13175 UINT    minuend;
13176 /* A counter used to recoder the number of digits between 2 colons. */
13177 UINT    digit_counter;
13178 
13179 UCHAR   *colon_location;
13180 /* A pointer used to traverse the destination memory. */
13181 UCHAR   *dst_cur_ptr;
13182 /* A pointer to the end of the destination memory. */
13183 UCHAR   *dst_end_ptr;
13184 ULONG   *dst_long_ptr;
13185 
13186 const CHAR    *ipv4_addr_start = src;
13187 UINT    n, i;
13188 
13189 struct  nx_bsd_in_addr ipv4_addr;
13190 
13191     if(af == AF_INET)
13192     {
13193         /* Convert IPv4 address from presentation to numeric. */
13194         if(nx_bsd_inet_aton(src, &ipv4_addr))
13195         {
13196             /* Copy the IPv4 address to the destination. */
13197             *((ULONG *)dst) = ipv4_addr.s_addr;
13198             return 1;
13199         }
13200         return 0;
13201     }
13202     else if(af == AF_INET6)
13203     {
13204         /* If : is at the beginning, the next value must be : .*/
13205         if(*src == ':')
13206             if(*src++ != ':')
13207                 return 0;
13208 
13209         /* Initialization. */
13210         value          = 0;
13211         digit_counter  = 0;
13212         colon_location = NX_NULL;
13213         dst_cur_ptr    = dst;
13214         /* Calculate the end of the destination memory. */
13215         dst_end_ptr    = (UCHAR*)dst + 15;
13216         /* Clear the destination memory. */
13217         memset(dst_cur_ptr, 0, 16);
13218 
13219         while(*src != 0)
13220         {
13221             /* Get the current character. */
13222             ch = *src++;
13223 
13224             /* Judge which minuend to use.
13225              * '0' - 48 == 0
13226              * 'a' - 87 == 10
13227              * 'A' - 55 == 10
13228              */
13229             minuend = 0;
13230             if(ch >= '0' && ch <= '9')
13231                 minuend = 48;
13232             else if(ch >= 'a' && ch <= 'f')
13233                 minuend = 87;
13234             else if(ch >= 'A' && ch <= 'F')
13235                 minuend = 55;
13236 
13237             /* if minuend is not 0, then ch is character in "0123456789abcdefABCDEF" */
13238             if(minuend)
13239             {
13240                 /* Convert the character to number. */
13241                 value = (USHORT)(value << 4);
13242                 value = (USHORT)(value | ((UINT)ch - minuend));
13243 
13244                 /* The max number of digits between 2 colons is 4. */
13245                 if(++digit_counter > 4)
13246                     return 0;
13247 
13248                 continue;
13249             }
13250 
13251             if(ch == ':')
13252             {
13253                 ipv4_addr_start = src;
13254 
13255                 /* Is there a digit before the colon? */
13256                 if(!digit_counter)
13257                 {
13258                     /* There is no digit before the colon. */
13259 
13260                     /* If there are 2 "::", Invalid Presentation Format.
13261                      * IF there is a ":::", Invalid Presention Format. */
13262                     if(colon_location)
13263                         return 0;
13264 
13265                     /* Record the colon location. */
13266                     colon_location = dst_cur_ptr;
13267                     continue;
13268                 }
13269                 else if(*src == '\0')
13270                 {
13271                     /* The colon is at the end of src, Invalid Presention Format. */
13272                     return 0;
13273                 }
13274 
13275                 if(dst_cur_ptr + 1 > dst_end_ptr)
13276                 {
13277                     /* Invalid Presentation Format. */
13278                     return 0;
13279                 }
13280 
13281                 /* Store the value to the dst memory. */
13282                 *(dst_cur_ptr++) = (UCHAR) (value >> 8) & 0xff;
13283                 *(dst_cur_ptr++) = (UCHAR) (value) & 0xff;
13284 
13285                 /* Reset the value and digit counter. */
13286                 digit_counter = 0;
13287                 value = 0;
13288 
13289                 continue;
13290 
13291             }
13292             else if(ch == '.')
13293             {
13294                 /* Process the dotted-decimal string in IPv4-mapped IPv6 address and IPv4-compatible IPv6 address. */
13295 
13296                 if(dst_cur_ptr + 3 > dst_end_ptr)
13297                 {
13298                     /* Invalid Presentation Format. */
13299                     return 0;
13300                 }
13301 
13302                 /* Convert the ipv4 address from presentation to numeric. */
13303                 if(nx_bsd_inet_aton(ipv4_addr_start, &ipv4_addr))
13304                 {
13305 
13306                     /* Make sure the result is in network byte order. */
13307                     ipv4_addr.s_addr = ntohl(ipv4_addr.s_addr);
13308                     NX_CHANGE_ULONG_ENDIAN(ipv4_addr.s_addr);
13309 
13310                     /* Store the value to the dst memory. */
13311                     *(ULONG *)dst_cur_ptr = ipv4_addr.s_addr;
13312 
13313                     dst_cur_ptr += 4;
13314                     digit_counter = 0;
13315 
13316                     break;
13317                 }
13318                 else
13319                     return 0;
13320 
13321 
13322             }
13323             else
13324             {
13325                 return 0;
13326             }
13327         }
13328 
13329         if(digit_counter)
13330         {
13331 
13332             /* Invalid Presentation Format. */
13333             if(dst_cur_ptr + 1 > dst_end_ptr)
13334                 return 0;
13335 
13336             /* Store the value to the dst memory. */
13337             *(dst_cur_ptr++) = (UCHAR) (value >> 8) & 0xff;
13338             *(dst_cur_ptr++) = (UCHAR) (value)      & 0xff;
13339 
13340         }
13341 
13342         if(colon_location)
13343         {
13344             /* There is a :: in the IPv6 address presentation. */
13345 
13346             /* Calculate how many octets should be moved to the end of the dst memory. */
13347             n = (UINT)(dst_cur_ptr  - colon_location);
13348 
13349             if(dst_cur_ptr == dst_end_ptr)
13350                 return 0;
13351 
13352             /* Move the data to the end of dst memory.
13353              *  -----------         -----------
13354              * |aabb0000000| ----> |aa0000000bb|
13355              *  -----------         -----------
13356              */
13357             for(i = 1; i <=n; i++)
13358             {
13359                 *(dst_end_ptr--) = colon_location[n - i];
13360                 colon_location[n-i]  = 0;
13361             }
13362 
13363             dst_cur_ptr = dst_end_ptr + 1;
13364         }
13365 
13366         if(dst_cur_ptr != (dst_end_ptr + 1))
13367             return 0;
13368 
13369         dst_long_ptr = (ULONG *)dst;
13370 
13371         /* First convert it to host byte order. */
13372         NX_CHANGE_ULONG_ENDIAN(dst_long_ptr[0]);
13373         NX_CHANGE_ULONG_ENDIAN(dst_long_ptr[1]);
13374         NX_CHANGE_ULONG_ENDIAN(dst_long_ptr[2]);
13375         NX_CHANGE_ULONG_ENDIAN(dst_long_ptr[3]);
13376 
13377         /* Convert it to network byte order by BSD macros. */
13378         dst_long_ptr[0] = htonl(dst_long_ptr[0]);
13379         dst_long_ptr[1] = htonl(dst_long_ptr[1]);
13380         dst_long_ptr[2] = htonl(dst_long_ptr[2]);
13381         dst_long_ptr[3] = htonl(dst_long_ptr[3]);
13382         return 1;
13383     }
13384     else
13385     {
13386         /* Error. */
13387         return -1;
13388     }
13389 }
13390 
13391 /**************************************************************************/
13392 /*                                                                        */
13393 /*  FUNCTION                                               RELEASE        */
13394 /*                                                                        */
13395 /*    inet_ntop                                           PORTABLE C      */
13396 /*                                                           6.3.0        */
13397 /*  AUTHOR                                                                */
13398 /*                                                                        */
13399 /*    Yuxin Zhou, Microsoft Corporation                                   */
13400 /*                                                                        */
13401 /*  DESCRIPTION                                                           */
13402 /*                                                                        */
13403 /*    This function converts an IP address from  numeric to presentation. */
13404 /*                                                                        */
13405 /*  INPUT                                                                 */
13406 /*                                                                        */
13407 /*    af                                    Either AF_INET or AF_INET6    */
13408 /*    src                                   A void pointer pointing to    */
13409 /*                                           network byte order IP address*/
13410 /*    dst                                   A char pointer pointing to    */
13411 /*                                           the destination buffer       */
13412 /*    size                                  The size of the destination   */
13413 /*                                           buffer                       */
13414 /*                                                                        */
13415 /*  OUTPUT                                                                */
13416 /*                                                                        */
13417 /*    dst                                   The destination buffer        */
13418 /*                                                                        */
13419 /*  CALLS                                                                 */
13420 /*                                                                        */
13421 /*    inet_ntoa_internal                    Convert IPv4 address from     */
13422 /*                                          numeric to presentation       */
13423 /*                                                                        */
13424 /*  CALLED BY                                                             */
13425 /*                                                                        */
13426 /*    Application Code                                                    */
13427 /*                                                                        */
13428 /*  RELEASE HISTORY                                                       */
13429 /*                                                                        */
13430 /*    DATE              NAME                      DESCRIPTION             */
13431 /*                                                                        */
13432 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13433 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13434 /*                                            resulting in version 6.1    */
13435 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
13436 /*                                            used new API/structs naming,*/
13437 /*                                            resulting in version 6.3.0  */
13438 /*                                                                        */
13439 /**************************************************************************/
nx_bsd_inet_ntop(INT af,const VOID * src,CHAR * dst,nx_bsd_socklen_t size)13440 const CHAR *nx_bsd_inet_ntop(INT af, const VOID *src, CHAR *dst, nx_bsd_socklen_t size)
13441 {
13442 
13443 INT    shorthand_index;
13444 INT    shorthand_len;
13445 INT    current_index;
13446 INT    current_len;
13447 
13448 INT    i;
13449 INT    index;
13450 UINT   rt_size;
13451 
13452 
13453     if(af == AF_INET)
13454     {
13455         /* Convert IPv4 address from numeric to presentation. */
13456         if(inet_ntoa_internal(src, dst, size))
13457             return dst;
13458         else
13459             return NX_NULL;
13460     }
13461     else if(af == AF_INET6)
13462     {
13463     USHORT temp[8];
13464         temp[0] = (USHORT)(ntohl(*((ULONG *)src)) >> 16);
13465         temp[1] = (USHORT)(ntohl(*((ULONG *)src)) & 0xFFFF);
13466         temp[2] = (USHORT)(ntohl(*(((ULONG *)src) + 1)) >> 16);
13467         temp[3] = (USHORT)(ntohl(*(((ULONG *)src) + 1)) & 0xFFFF);
13468         temp[4] = (USHORT)(ntohl(*(((ULONG *)src) + 2)) >> 16);
13469         temp[5] = (USHORT)(ntohl(*(((ULONG *)src) + 2)) & 0xFFFF);
13470         temp[6] = (USHORT)(ntohl(*(((ULONG *)src) + 3)) >> 16);
13471         temp[7] = (USHORT)(ntohl(*(((ULONG *)src) + 3)) & 0xFFFF);
13472 
13473         /* Initialization. */
13474         shorthand_index = -1;
13475         shorthand_len = 0;
13476         current_index = -1;
13477         current_len = 0;
13478 
13479         /* Find the longest 0x00 in src for ::
13480          * 16 * 8 == 128  */
13481         for(i = 0; i < 8; i++)
13482         {
13483             if(temp[i] == 0)
13484             {
13485                 if(current_index == -1)
13486                 {
13487                     /* Record the index of 0x00, Initialize the length to 1. */
13488                     current_index = i;
13489                     current_len = 1;
13490                 }
13491                 else
13492                 {
13493                     current_len++;
13494                 }
13495             }
13496             else
13497             {
13498                 /* Not 0x00 . */
13499 
13500                 if(current_index != -1)
13501                 {
13502                     /* Not equal -1, means there is record of 0x00s . */
13503 
13504                     if(shorthand_index == -1 || current_len > shorthand_len)
13505                     {
13506                         /* Record the longest 0x00s. */
13507                         shorthand_index = current_index;
13508                         shorthand_len = current_len;
13509                     }
13510 
13511                     /* Reset the index. */
13512                     current_index = -1;
13513                 }
13514 
13515             }
13516         }
13517 
13518 
13519         if(current_len > shorthand_len)
13520         {
13521             /* Record the longest 0x00s. */
13522             shorthand_index = current_index;
13523             shorthand_len = current_len;
13524         }
13525 
13526         /* If length is less than 2, no need for shorthand. */
13527         if(shorthand_len < 2)
13528         {
13529             shorthand_index = -1;
13530         }
13531 
13532         index = 0;
13533         /* Format the result. */
13534         for(i = 0; i < 8; i++)
13535         {
13536             /* Is i in the range of :: */
13537             if((shorthand_index != -1) &&
13538                (i >= shorthand_index) &&
13539                (i < (shorthand_index + shorthand_len)))
13540             {
13541                 if(i == shorthand_index)
13542                 {
13543                     /* Check if there is enough memory to store a character. */
13544                     if((size - (ULONG)index) < 1)
13545                         return NX_NULL;
13546 
13547                     dst[index++] = ':';
13548                 }
13549                 continue;
13550             }
13551 
13552            if(i != 0)
13553            {
13554                 /* Check if there is enough memory to store a character. */
13555                 if((size - (ULONG)index) < 1)
13556                     return NX_NULL;
13557 
13558                 dst[index++] = ':';
13559            }
13560 
13561            /* Does this address contain IPv4 address. */
13562            if(i == 6 && shorthand_index == 0 &&
13563               (shorthand_len == 6 ||                       /* IPv4-mapped IPv6 address     ----->  ::1.2.3.4 */
13564               (shorthand_len == 5 && temp[5] == 0xffff)))  /* IPv4-compatible IPv6 address ----->  ::ffff:1.2.3.4 */
13565            {
13566                /* Convert ipv4 address to string.  12 == 16 - 4*/
13567                rt_size = (UINT)inet_ntoa_internal((UCHAR*)src + 12, &dst[index], size - (ULONG)index);
13568 
13569                /* Check the return size, 0 means error. */
13570                if(rt_size)
13571                    index += (INT)rt_size;
13572                else
13573                    return NX_NULL;
13574            }
13575 
13576            /* Convert hex number to string */
13577            rt_size = bsd_number_convert(temp[i], &dst[index], size - (ULONG)index, 16);
13578            if(!rt_size)
13579                return NX_NULL;
13580 
13581            /* Increment the index. */
13582            index += (INT)rt_size;
13583 
13584         }
13585 
13586         /* Is there a trailing : */
13587         if((shorthand_index != -1) && (shorthand_index + shorthand_len == 8))
13588         {
13589             /* Check if there is enough memory to store a character. */
13590             if((size - (ULONG)index) < 1)
13591                 return NX_NULL;
13592 
13593             dst[index++] = ':';
13594 
13595         }
13596 
13597         /* Check if there is enough memory to store a character. */
13598         if((size - (ULONG)index) < 1)
13599             return NX_NULL;
13600 
13601         dst[index] = '\0';
13602 
13603         return dst;
13604     }
13605     else
13606     {
13607         return NX_NULL;
13608     }
13609 }
13610 
13611 /**************************************************************************/
13612 /*                                                                        */
13613 /*  FUNCTION                                               RELEASE        */
13614 /*                                                                        */
13615 /*    inet_ntoa_internal                                  PORTABLE C      */
13616 /*                                                           6.1          */
13617 /*  AUTHOR                                                                */
13618 /*                                                                        */
13619 /*    Yuxin Zhou, Microsoft Corporation                                   */
13620 /*                                                                        */
13621 /*  DESCRIPTION                                                           */
13622 /*                                                                        */
13623 /*    This function converts an IPv4 address to a string and returns the  */
13624 /*    size of the string.                                                 */
13625 /*                                                                        */
13626 /*  INPUT                                                                 */
13627 /*                                                                        */
13628 /*    src                                   A void pointer pointing to    */
13629 /*                                            IPv4 address                */
13630 /*    dst                                   A char pointer pointing to    */
13631 /*                                            the destination buffer      */
13632 /*    dst_size                              The size of the destination   */
13633 /*                                            buffer                      */
13634 /*                                                                        */
13635 /*  OUTPUT                                                                */
13636 /*                                                                        */
13637 /*    index                                 The size of the IPv4 address  */
13638 /*                                            string                      */
13639 /*                                                                        */
13640 /*  CALLS                                                                 */
13641 /*                                                                        */
13642 /*    memset                                Set the memory to 0           */
13643 /*    bsd_number_convert                    Convert a number to string    */
13644 /*                                                                        */
13645 /*  CALLED BY                                                             */
13646 /*                                                                        */
13647 /*    NetX Duo BSD Layer Source Code                                      */
13648 /*                                                                        */
13649 /*  RELEASE HISTORY                                                       */
13650 /*                                                                        */
13651 /*    DATE              NAME                      DESCRIPTION             */
13652 /*                                                                        */
13653 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13654 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13655 /*                                            resulting in version 6.1    */
13656 /*                                                                        */
13657 /**************************************************************************/
13658 
inet_ntoa_internal(const VOID * src,CHAR * dst,ULONG dst_size)13659 static INT inet_ntoa_internal(const VOID *src, CHAR *dst, ULONG dst_size)
13660 {
13661 ULONG temp;
13662 UINT size;
13663 UINT index = 0;
13664 
13665 
13666     /* Set a local pointer to move up the buffer. */
13667     temp = ntohl(*((ULONG *)src));
13668 
13669     memset(dst, 0, dst_size);
13670 
13671     /* Convert the first number to a string. */
13672     size = bsd_number_convert((temp >> 24), &dst[0], dst_size - index, 10);
13673 
13674     if(!size)
13675         return 0;
13676 
13677     /* Move up the index and buffer pointer. */
13678     index += size;
13679 
13680     /* Check the rest of the dst buffer. */
13681     if((dst_size - index) < 1)
13682         return 0;
13683 
13684     /* Add the decimal. */
13685     dst[index++] = '.';
13686 
13687     /* And repeat three more times...*/
13688     size = bsd_number_convert((temp >> 16) & 0xff, &dst[index], dst_size - index, 10);
13689 
13690     if(!size)
13691         return 0;
13692 
13693     index += size;
13694 
13695     if((dst_size - index) < 1)
13696         return 0;
13697 
13698     dst[index++] = '.';
13699 
13700     size = bsd_number_convert((temp >> 8) & 0xff, &dst[index], dst_size - index, 10);
13701 
13702     if(!size)
13703         return 0;
13704 
13705     index += size;
13706 
13707     if((dst_size - index) < 1)
13708         return 0;
13709 
13710     dst[index++] = '.';
13711 
13712     size = bsd_number_convert(temp & 0xff, &dst[index], dst_size - index, 10);
13713 
13714     if(!size)
13715         return 0;
13716 
13717     index += size;
13718 
13719     if((dst_size - index) < 1)
13720         return 0;
13721 
13722     dst[index++] = '\0';
13723 
13724     /* Return the size of the dst string. */
13725     return((INT)(index));
13726 }
13727 
13728 
13729 /**************************************************************************/
13730 /*                                                                        */
13731 /*  FUNCTION                                               RELEASE        */
13732 /*                                                                        */
13733 /*    getaddrinfo                                         PORTABLE C      */
13734 /*                                                           6.3.0        */
13735 /*  AUTHOR                                                                */
13736 /*                                                                        */
13737 /*    Yuxin Zhou, Microsoft Corporation                                   */
13738 /*                                                                        */
13739 /*  DESCRIPTION                                                           */
13740 /*                                                                        */
13741 /*    This function returns one or more addrinfo structures according to  */
13742 /*    the specified node and service.                                     */
13743 /*                                                                        */
13744 /*  INPUT                                                                 */
13745 /*                                                                        */
13746 /*   node                                   Node is either a hostname or  */
13747 /*                                           an address string(dotted-    */
13748 /*                                           decimal for IPv4 or a hex    */
13749 /*                                           string for IPv6).            */
13750 /*   service                                Service is either a service   */
13751 /*                                           name or a decimal port number*/
13752 /*                                           string.                      */
13753 /*   hints                                  Hints is either a null pointer*/
13754 /*                                           or a pointer to an addrinfo  */
13755 /*                                           structure that the caller    */
13756 /*                                           fills in with hints about the*/
13757 /*                                           types of information the     */
13758 /*                                           caller wants returned.       */
13759 /*   res                                    Pointer to the returned       */
13760 /*                                           addrinfo list.               */
13761 /*                                                                        */
13762 /*  OUTPUT                                                                */
13763 /*                                                                        */
13764 /*    status                                0 if OK, nonzero on errors    */
13765 /*                                                                        */
13766 /*  CALLS                                                                 */
13767 /*                                                                        */
13768 /*    bsd_string_to_number                  Convert a string to a number  */
13769 /*    htons                                 Host byte order to network    */
13770 /*                                          byte order                    */
13771 /*    memcmp                                Memory compare                */
13772 /*    inet_pton                             Convert IP address from       */
13773 /*                                          presentation to numeric       */
13774 /*    tx_block_allocate                     Allocate memory for address or*/
13775 /*                                          addrinfo                      */
13776 /*    memset                                Set the memory to 0           */
13777 /*    freeaddrinfo                          Release addrinfo memory       */
13778 /*    nx_dns_ipv4_address_by_name_get       Get ipv4 addr by name via dns */
13779 /*    nxd_dns_ipv6_address_by_name_get      Get ipv6 addr by name via dns */
13780 /*                                                                        */
13781 /*  CALLED BY                                                             */
13782 /*                                                                        */
13783 /*    Application Code                                                    */
13784 /*                                                                        */
13785 /*  RELEASE HISTORY                                                       */
13786 /*                                                                        */
13787 /*    DATE              NAME                      DESCRIPTION             */
13788 /*                                                                        */
13789 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13790 /*  09-30-2020     Yuxin Zhou               Modified comment(s), improved */
13791 /*                                            buffer length verification, */
13792 /*                                            verified memcpy use cases,  */
13793 /*                                            fixed compiler errors,      */
13794 /*                                            resulting in version 6.1    */
13795 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
13796 /*                                            fixed compiler warnings,    */
13797 /*                                            resulting in version 6.1.12 */
13798 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
13799 /*                                            used new API/structs naming,*/
13800 /*                                            resulting in version 6.3.0  */
13801 /*                                                                        */
13802 /**************************************************************************/
nx_bsd_getaddrinfo(const CHAR * node,const CHAR * service,const struct nx_bsd_addrinfo * hints,struct nx_bsd_addrinfo ** res)13803 INT  nx_bsd_getaddrinfo(const CHAR *node, const CHAR *service, const struct nx_bsd_addrinfo *hints, struct nx_bsd_addrinfo **res)
13804 {
13805 
13806 UINT            status;
13807 #ifdef NX_BSD_ENABLE_DNS
13808 UINT            status2;
13809 #endif
13810 UINT            pton_flag;
13811 UINT            port;
13812 UINT            i, j;
13813 INT             addr_family;
13814 UINT            ipv4_addr_count = 0;
13815 UINT            ipv6_addr_count = 0;
13816 UINT            match_service_count;
13817 UINT            match_service_socktype[3];
13818 UINT            match_service_protocol[3];
13819 struct nx_bsd_addrinfo
13820                *addrinfo_cur_ptr  = NX_NULL;
13821 struct nx_bsd_addrinfo
13822                *addrinfo_head_ptr = NX_NULL;
13823 struct nx_bsd_addrinfo
13824                *addrinfo_tail_ptr = NX_NULL;
13825 struct nx_bsd_sockaddr
13826                *sockaddr_ptr      = NX_NULL;
13827 UCHAR           *cname_buffer      = NX_NULL;
13828 
13829 /* When hints is a null pointer, use the default value below. */
13830 static struct nx_bsd_addrinfo default_hints = {0, AF_UNSPEC, 0, 0, 0, NX_NULL, NX_NULL, NX_NULL};
13831 
13832 
13833 
13834     /* if node and service are null return an error, invalid input. */
13835     if((node == NX_NULL) && (service == NX_NULL))
13836         return EAI_NONAME;
13837 
13838     if(hints)
13839     {
13840 
13841         /* Check if the address family is valid. */
13842         if((hints -> ai_family != AF_INET)  &&
13843            (hints -> ai_family != AF_INET6) &&
13844            (hints -> ai_family != AF_UNSPEC))
13845             return EAI_FAMILY;
13846 
13847         /* Check if the socket type is valid. */
13848         if((hints -> ai_socktype != SOCK_DGRAM)  &&
13849            (hints -> ai_socktype != SOCK_STREAM) &&
13850            (hints -> ai_socktype != 0))
13851             return EAI_SOCKTYPE;
13852 
13853         /* If socktype and protocol are both specified, check if they are meaningful. */
13854         if((hints -> ai_socktype != 0) && (hints -> ai_protocol != 0))
13855         {
13856             if(((hints -> ai_socktype == SOCK_STREAM) && (hints -> ai_protocol != IPPROTO_TCP)) ||
13857                ((hints -> ai_socktype == SOCK_DGRAM) && (hints -> ai_protocol != IPPROTO_UDP)) ||
13858                ((hints -> ai_socktype == SOCK_RAW) && (hints -> ai_protocol != IPPROTO_RAW)))
13859                 return EAI_SOCKTYPE;
13860         }
13861 
13862     }
13863     else
13864     {
13865         hints = &default_hints;
13866     }
13867 
13868     /* Sock type specified? */
13869     if(hints -> ai_socktype == 0)
13870     {
13871 
13872         /* No; is protocol specified? */
13873         if(hints -> ai_protocol == 0)
13874         {
13875 
13876             /* No, protocol is not specified. */
13877 
13878             /* Set default socktype and protocol. */
13879             match_service_count = 3;
13880             match_service_socktype[0] = SOCK_STREAM;
13881             match_service_protocol[0] = IPPROTO_TCP;
13882             match_service_socktype[1] = SOCK_DGRAM;
13883             match_service_protocol[1] = IPPROTO_UDP;
13884             match_service_socktype[2] = SOCK_RAW;
13885             match_service_protocol[2] = 0;
13886         }
13887         else
13888         {
13889 
13890             /* protocol is specified. */
13891             match_service_count = 1;
13892             match_service_protocol[0] = (UINT)(hints -> ai_protocol);
13893 
13894             /* Set default socktype according to protocol. */
13895             if(hints -> ai_protocol == IPPROTO_TCP)
13896                 match_service_socktype[0] = SOCK_STREAM;
13897             else if(hints -> ai_protocol == IPPROTO_UDP)
13898                 match_service_socktype[0] = SOCK_DGRAM;
13899         }
13900     }
13901     else
13902     {
13903 
13904         /* Socktype is specified. */
13905         match_service_count = 1;
13906         match_service_socktype[0] = (UINT)(hints -> ai_socktype);
13907 
13908         if(hints -> ai_protocol == 0)
13909         {
13910 
13911             /* Protocol is not specified. */
13912 
13913             /* Set default protocol according to socktype. */
13914             if(hints -> ai_socktype == SOCK_STREAM)
13915                 match_service_protocol[0] = IPPROTO_TCP;
13916             else if(hints -> ai_socktype == SOCK_DGRAM)
13917                 match_service_protocol[0] = IPPROTO_UDP;
13918             else if(hints -> ai_socktype == SOCK_RAW)
13919                 match_service_protocol[0] = 0;
13920         }
13921         else
13922         {
13923 
13924             /* Protocol is specififed. */
13925             match_service_protocol[0] = (UINT)(hints -> ai_protocol);
13926         }
13927     }
13928 
13929     if(service)
13930     {
13931 
13932         /* Service is not null. */
13933         if(bsd_string_to_number(service, &port) != NX_SOC_ERROR)
13934         {
13935 
13936             /* Service is a decimal port number string, and has been converted to a numeric port successfully. */
13937 
13938             /* Convert port from host byte order to network byte order. */
13939             port = htons((USHORT)port);
13940         }
13941         else
13942         {
13943 
13944             /* Service is an address name, not a decimal port number string. */
13945 
13946             /* Check if numeric service flag is set. If so this is an invalid string. */
13947             if(hints -> ai_flags & AI_NUMERICSERV)
13948                 return EAI_NONAME;
13949 
13950             match_service_count = 0;
13951 
13952             /* Look for a match of name, protocol and socket type for a match in the service list. */
13953             for(i = 0; i < _nx_bsd_serv_list_len; i++)
13954             {
13955 
13956                 /* Check if there is a match. */
13957                 if(!memcmp(_nx_bsd_serv_list_ptr[i].service_name, service, _nx_bsd_string_length((CHAR *)service)) &&
13958                         ((_nx_bsd_serv_list_ptr[i].service_socktype == hints -> ai_socktype) ||(hints -> ai_socktype == 0)) &&
13959                         ((_nx_bsd_serv_list_ptr[i].service_protocol == hints -> ai_protocol) ||(hints -> ai_protocol == 0)))
13960                 {
13961                     match_service_socktype[match_service_count] = (UINT)(_nx_bsd_serv_list_ptr[i].service_socktype);
13962                     match_service_protocol[match_service_count++] = (UINT)(_nx_bsd_serv_list_ptr[i].service_protocol);
13963 
13964                     /* Convert host byte order to network byte order. */
13965                     port = htons(_nx_bsd_serv_list_ptr[i].service_port);
13966                 }
13967             }
13968 
13969             /* Service is not available. */
13970             if(match_service_count == 0)
13971                 return EAI_SERVICE;
13972         }
13973     }
13974     else
13975     {
13976 
13977         /* Convert host byte order to network byte order. */
13978         port = htons(0);
13979     }
13980 
13981     if(node)
13982     {
13983 
13984         /* Node is not null. */
13985 
13986         /* Determine the address family. */
13987         addr_family = AF_INET;
13988 
13989         for(i = 0; i < _nx_bsd_string_length((CHAR *)node); i++)
13990         {
13991             if(node[i] == ':')
13992             {
13993                 /* There is a colon, so it is an IPv6 address. */
13994                 addr_family = AF_INET6;
13995                 break;
13996             }
13997         }
13998 
13999         /* Initialize to 0, default to pton failing. */
14000         pton_flag = 0;
14001 
14002         if(addr_family == AF_INET)
14003         {
14004 
14005             /* Convert node from a string presentation to a numeric address. */
14006             if(nx_bsd_inet_pton(addr_family, node, &(nx_bsd_ipv4_addr_buffer[0])) == 1)
14007             {
14008                 /* pton has successful completion. */
14009                 pton_flag = 1;
14010 
14011                 /* Check if the address and the specified family match. */
14012                 if((hints -> ai_family != AF_INET) && (hints -> ai_family != AF_UNSPEC))
14013                     return EAI_ADDRFAMILY;
14014 
14015                 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv4_addr_buffer[0]);
14016                 ipv4_addr_count = 1;
14017             }
14018         }
14019         else
14020         {
14021 
14022             /* Convert node from a string presentation to a numeric address. */
14023             if(nx_bsd_inet_pton(addr_family, node, &(nx_bsd_ipv6_addr_buffer[0])) == 1)
14024             {
14025                 /* pton completed successfully. */
14026                 pton_flag = 1;
14027 
14028                 /* Check is the address and the specified family matches. */
14029                 if((hints -> ai_family != AF_INET6) && (hints -> ai_family != AF_UNSPEC))
14030                     return EAI_ADDRFAMILY;
14031 
14032                 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv6_addr_buffer[0]);
14033                 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv6_addr_buffer[1]);
14034                 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv6_addr_buffer[2]);
14035                 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv6_addr_buffer[3]);
14036                 ipv6_addr_count = 1;
14037             }
14038         }
14039 
14040         if(pton_flag == 1)
14041         {
14042 
14043             /* pton completed successfull. Host (node) is an address string. */
14044 
14045 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
14046             /* DNS supports extended services including Canonical name queries. */
14047             if((hints -> ai_flags & AI_CANONNAME) && !(hints -> ai_flags & AI_NUMERICHOST))
14048             {
14049 
14050                 /* Allocate a block for canonical name. */
14051                 status = tx_block_allocate(&nx_bsd_cname_block_pool, (VOID *) &cname_buffer, NX_BSD_TIMEOUT);
14052 
14053                 /* Check for error status.  */
14054                 if (status != TX_SUCCESS)
14055                 {
14056                     /* Set the error. */
14057                     nx_bsd_set_errno(ENOMEM);
14058 
14059                     /* Error getting NetX socket memory.  */
14060                     NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
14061 
14062                     /* Return memory allocation error. */
14063                     return(EAI_MEMORY);
14064                 }
14065 
14066                 /* Verify buffer size. */
14067                 if (_nx_bsd_string_length((CHAR *)node) > NX_DNS_NAME_MAX)
14068                     return(EAI_OVERFLOW);
14069 
14070                 memcpy(cname_buffer, node, _nx_bsd_string_length((CHAR *)node)); /* Use case of memcpy is verified. */
14071 
14072             }
14073 #endif /* NX_BSD_ENABLE_DNS && NX_DNS_ENABLE_EXTENDED_RR_TYPES */
14074 
14075         }
14076         else
14077         {
14078 
14079             /* Presentation to numeric format fails, node may be a hostname, not a numeric IP address. */
14080 
14081             /* Check if numeric host flag is set. */
14082             if(hints -> ai_flags & AI_NUMERICHOST)
14083                 return EAI_NONAME;
14084 
14085 #ifdef NX_BSD_ENABLE_DNS
14086             if(hints -> ai_family == AF_INET)
14087             {
14088 
14089                 /* Get IPv4 address by hostname. */
14090                 status = nx_dns_ipv4_address_by_name_get(_nx_dns_instance_ptr, (UCHAR *)node, &nx_bsd_ipv4_addr_buffer[0],
14091                                                          NX_BSD_IPV4_ADDR_PER_HOST * 4, &ipv4_addr_count, NX_BSD_TIMEOUT);
14092 
14093                 if(status != NX_SUCCESS)
14094                 {
14095 
14096                     /* Just return EAI_FAIL, because we can't discriminate between DNS FAIL and the situation where the specified
14097                        network host exists but does not have any network addresses defined. It would be better to return EAI_FAIL
14098                        for DNS FAIL, and EAI_NODATA for the latter situation. */
14099                     return EAI_FAIL;
14100                 }
14101             }
14102             else if(hints -> ai_family == AF_INET6)
14103             {
14104 
14105                 /* Get IPv6 address by hostname. */
14106                 status = nxd_dns_ipv6_address_by_name_get(_nx_dns_instance_ptr, (UCHAR *)node, &nx_bsd_ipv6_addr_buffer[0],
14107                                                           NX_BSD_IPV6_ADDR_PER_HOST * 16, &ipv6_addr_count, NX_BSD_TIMEOUT);
14108 
14109                 if(status != NX_SUCCESS)
14110                 {
14111                     /* Just return EAI_FAIL, because we can't discriminate between DNS FAIL and the situation where the specified
14112                        network host exists but does not have any network addresses defined. It would be better to return EAI_FAIL
14113                        for DNS FAIL, and EAI_NODATA for the latter situation. */
14114                     return EAI_FAIL;
14115                 }
14116             }
14117             else
14118             {
14119 
14120                 /* Address family is not specified. Query for both IPv4 and IPv6 address. */
14121 
14122                 /* Get IPv4 address by hostname. */
14123                 status = nx_dns_ipv4_address_by_name_get(_nx_dns_instance_ptr, (UCHAR *)node, &nx_bsd_ipv4_addr_buffer[0],
14124                                                          NX_BSD_IPV4_ADDR_PER_HOST * 4, &ipv4_addr_count, NX_BSD_TIMEOUT);
14125 
14126                 /* Get IPv6 address by hostname. */
14127                 status2 = nxd_dns_ipv6_address_by_name_get(_nx_dns_instance_ptr, (UCHAR *)node, &nx_bsd_ipv6_addr_buffer[0],
14128                                                            NX_BSD_IPV6_ADDR_PER_HOST * 16, &ipv6_addr_count, NX_BSD_TIMEOUT);
14129 
14130                 if((status != NX_SUCCESS) && status2 != NX_SUCCESS)
14131                 {
14132                     /* Just return EAI_FAIL, because we can't discriminate between DNS FAIL and the situation that the specified
14133                        network host exists, but does not have any network addresses defined. It would be better to return EAI_FAIL
14134                        for DNS FAIL, and EAI_NODATA for the latter situation. */
14135                     return EAI_FAIL;
14136                 }
14137             }
14138 
14139             if(hints -> ai_flags & AI_CANONNAME)
14140             {
14141 
14142 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14143                 /* Allocate a block for canonical name. */
14144                 status = tx_block_allocate(&nx_bsd_cname_block_pool, (VOID *) &cname_buffer, NX_BSD_TIMEOUT);
14145 
14146                 /* Check for error status.  */
14147                 if (status != TX_SUCCESS)
14148                 {
14149                     /* Set the error. */
14150                     set_errno(ENOMEM);
14151 
14152                     /* Error getting NetX socket memory.  */
14153                     NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
14154 
14155                     /* Return memory allocation error. */
14156                     return(EAI_MEMORY);
14157                 }
14158 
14159                 status = nx_dns_cname_get(_nx_dns_instance_ptr, (UCHAR *)node, cname_buffer,
14160                                           nx_bsd_cname_block_pool.tx_block_pool_block_size, NX_BSD_TIMEOUT);
14161                 if(status != NX_SUCCESS)
14162                 {
14163 
14164                     /* Verify buffer size. */
14165                     if (_nx_bsd_string_length((CHAR *)node) > NX_DNS_NAME_MAX)
14166                         return(EAI_OVERFLOW);
14167 
14168                     memcpy(cname_buffer, node, _nx_bsd_string_length((CHAR *)node)); /* Use case of memcpy is verified. */
14169                 }
14170 
14171 #else
14172                 cname_buffer = (UCHAR *)node;
14173 #endif
14174             }
14175 #else
14176             return EAI_FAIL;
14177 #endif
14178 
14179         }
14180     }
14181     else
14182     {
14183 
14184         /* Node is null. */
14185         if(hints -> ai_flags & AI_PASSIVE)
14186         {
14187             /* The caller wiil use the socket for a passive open. */
14188 
14189             nx_bsd_ipv4_addr_buffer[0] = INADDR_ANY;
14190 
14191             nx_bsd_ipv6_addr_buffer[0] = 0;
14192             nx_bsd_ipv6_addr_buffer[1] = 0;
14193             nx_bsd_ipv6_addr_buffer[2] = 0;
14194             nx_bsd_ipv6_addr_buffer[3] = 0;
14195         }
14196         else
14197         {
14198 
14199             /* Localhost address. */
14200             nx_bsd_ipv4_addr_buffer[0] = 0x7F000001;
14201 
14202             nx_bsd_ipv6_addr_buffer[0] = 0;
14203             nx_bsd_ipv6_addr_buffer[1] = 0;
14204             nx_bsd_ipv6_addr_buffer[2] = 0;
14205             nx_bsd_ipv6_addr_buffer[3] = 1;
14206         }
14207 
14208         if (hints -> ai_family != AF_INET6)
14209         {
14210             ipv4_addr_count = 1;
14211         }
14212         ipv6_addr_count = 1;
14213     }
14214 
14215 
14216     for(i = 0; i < ipv4_addr_count + ipv6_addr_count; i++)
14217     {
14218 
14219         /* Allocate a block for ipv4 address. */
14220         status = tx_block_allocate(&nx_bsd_addrinfo_block_pool, (VOID *) &sockaddr_ptr, NX_BSD_TIMEOUT);
14221 
14222         /* Check for error status.  */
14223         if (status != TX_SUCCESS)
14224         {
14225 
14226             /* Set the error. */
14227             nx_bsd_set_errno(ENOMEM);
14228 
14229             /* If head is not null, free the memory. */
14230             if(addrinfo_head_ptr)
14231                 nx_bsd_freeaddrinfo(addrinfo_head_ptr);
14232 
14233 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14234             if(hints -> ai_flags & AI_CANONNAME)
14235                 tx_block_release((VOID *)cname_buffer);
14236 #endif
14237 
14238             /* Error getting NetX socket memory.  */
14239             NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
14240 
14241             /* Return memory allocation error. */
14242             return(EAI_MEMORY);
14243         }
14244 
14245         /* Clear the  memory.  */
14246         memset((VOID*)sockaddr_ptr, 0, sizeof(struct nx_bsd_addrinfo));
14247 
14248         if(i < ipv4_addr_count)
14249         {
14250 
14251             /* Process IPv4 address. */
14252             ((struct nx_bsd_sockaddr_in*)sockaddr_ptr) -> sin_family = AF_INET;
14253             ((struct nx_bsd_sockaddr_in*)sockaddr_ptr) -> sin_port   = (USHORT)port;
14254             ((struct nx_bsd_sockaddr_in*)sockaddr_ptr) -> sin_addr.s_addr = nx_bsd_ipv4_addr_buffer[i];
14255 
14256             NX_CHANGE_ULONG_ENDIAN(((struct nx_bsd_sockaddr_in*)sockaddr_ptr) -> sin_addr.s_addr);
14257         }
14258         else
14259         {
14260 
14261             /* Process IPv6 address. */
14262             ((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_family = AF_INET6;
14263             ((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_port   = (USHORT)port;
14264             memcpy(&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr), &nx_bsd_ipv6_addr_buffer[(i - ipv4_addr_count)*4], 16); /* Use case of memcpy is verified. */
14265 
14266             NX_CHANGE_ULONG_ENDIAN(*(ULONG*)&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr.s6_addr32[0]));
14267             NX_CHANGE_ULONG_ENDIAN(*(ULONG*)&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr.s6_addr32[1]));
14268             NX_CHANGE_ULONG_ENDIAN(*(ULONG*)&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr.s6_addr32[2]));
14269             NX_CHANGE_ULONG_ENDIAN(*(ULONG*)&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr.s6_addr32[3]));
14270 
14271         }
14272 
14273         for(j = 0; j < match_service_count; j++)
14274         {
14275 
14276             /* Allocate a block from the addrinfo block pool. */
14277             status = tx_block_allocate(&nx_bsd_addrinfo_block_pool, (VOID *) &addrinfo_cur_ptr, NX_BSD_TIMEOUT);
14278 
14279             /* Check for error status.  */
14280             if (status != TX_SUCCESS)
14281             {
14282 
14283                 /* Set the error. */
14284                 nx_bsd_set_errno(ENOMEM);
14285 
14286                 /* If head is not null, free the memory. */
14287                 if(addrinfo_head_ptr)
14288                     nx_bsd_freeaddrinfo(addrinfo_head_ptr);
14289 
14290                 tx_block_release((VOID *)sockaddr_ptr);
14291 
14292 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14293                 if(hints -> ai_flags & AI_CANONNAME)
14294                     tx_block_release((VOID *)cname_buffer);
14295 #endif
14296 
14297                 /* Error getting NetX socket memory.  */
14298                 NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
14299 
14300                 /* Return memory allocation error. */
14301                 return(EAI_MEMORY);
14302             }
14303 
14304             /* Clear the socket memory.  */
14305             memset((VOID*)addrinfo_cur_ptr, 0, sizeof(struct nx_bsd_addrinfo));
14306 
14307             if(i < ipv4_addr_count)
14308             {
14309 
14310                 /* IPv4 */
14311                 addrinfo_cur_ptr -> ai_family  = AF_INET;
14312                 addrinfo_cur_ptr -> ai_addrlen = sizeof(struct nx_bsd_sockaddr_in);
14313             }
14314             else
14315             {
14316 
14317                 /* IPv6 */
14318                 addrinfo_cur_ptr -> ai_family = AF_INET6;
14319                 addrinfo_cur_ptr -> ai_addrlen = sizeof(struct nx_bsd_sockaddr_in6);
14320             }
14321 
14322             addrinfo_cur_ptr -> ai_socktype = (INT)(match_service_socktype[j]);
14323             addrinfo_cur_ptr -> ai_protocol = (INT)(match_service_protocol[j]);
14324             addrinfo_cur_ptr -> ai_addr = sockaddr_ptr;
14325             if((i == 0) && (j == 0) && (hints -> ai_flags & AI_CANONNAME))
14326                 addrinfo_cur_ptr -> ai_canonname = (CHAR *)cname_buffer;
14327             else
14328                 addrinfo_cur_ptr -> ai_canonname = NX_NULL;
14329             addrinfo_cur_ptr -> ai_next = NX_NULL;
14330 
14331             /* Make a list. */
14332             if(addrinfo_head_ptr == NX_NULL)
14333                 addrinfo_head_ptr = addrinfo_cur_ptr;
14334             else
14335                 addrinfo_tail_ptr -> ai_next = addrinfo_cur_ptr;
14336 
14337             addrinfo_tail_ptr = addrinfo_cur_ptr;
14338 
14339         }
14340     }
14341 
14342     *res = addrinfo_head_ptr;
14343 
14344     return 0;
14345 }
14346 
14347 /**************************************************************************/
14348 /*                                                                        */
14349 /*  FUNCTION                                               RELEASE        */
14350 /*                                                                        */
14351 /*    freeaddrinfo                                        PORTABLE C      */
14352 /*                                                           6.3.0        */
14353 /*  AUTHOR                                                                */
14354 /*                                                                        */
14355 /*    Yuxin Zhou, Microsoft Corporation                                   */
14356 /*                                                                        */
14357 /*  DESCRIPTION                                                           */
14358 /*                                                                        */
14359 /*    This function releases the memory allocated by getaddrinfo.         */
14360 /*                                                                        */
14361 /*  INPUT                                                                 */
14362 /*                                                                        */
14363 /*    res                                   Pointer to a addrinfo struct  */
14364 /*                                                                        */
14365 /*  OUTPUT                                                                */
14366 /*                                                                        */
14367 /*    None                                                                */
14368 /*                                                                        */
14369 /*  CALLS                                                                 */
14370 /*                                                                        */
14371 /*    tx_block_release                      Release socket memory         */
14372 /*                                                                        */
14373 /*  CALLED BY                                                             */
14374 /*                                                                        */
14375 /*    Application Code                                                    */
14376 /*                                                                        */
14377 /*  RELEASE HISTORY                                                       */
14378 /*                                                                        */
14379 /*    DATE              NAME                      DESCRIPTION             */
14380 /*                                                                        */
14381 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14382 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
14383 /*                                            resulting in version 6.1    */
14384 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
14385 /*                                            used new API/structs naming,*/
14386 /*                                            resulting in version 6.3.0  */
14387 /*                                                                        */
14388 /**************************************************************************/
nx_bsd_freeaddrinfo(struct nx_bsd_addrinfo * res)14389 VOID nx_bsd_freeaddrinfo(struct nx_bsd_addrinfo *res)
14390 {
14391 
14392 struct nx_bsd_addrinfo *next_addrinfo;
14393 struct nx_bsd_sockaddr *ai_addr_ptr = NX_NULL;
14394 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14395 CHAR *ai_canonname_ptr = NX_NULL;
14396 #endif
14397 
14398     while(res)
14399     {
14400 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14401         if((res -> ai_canonname) &&
14402            (res -> ai_canonname != ai_canonname_ptr))
14403         {
14404 
14405             /* Release  the CNAME memory. */
14406             tx_block_release((VOID *)res -> ai_canonname);
14407 
14408             ai_canonname_ptr = res -> ai_canonname;
14409         }
14410 #endif
14411         if((res -> ai_addr) &&
14412            (res -> ai_addr != ai_addr_ptr))
14413         {
14414 
14415             /* Release the address memory. */
14416             tx_block_release((VOID *)res -> ai_addr);
14417 
14418             ai_addr_ptr = res -> ai_addr;
14419         }
14420 
14421         /* Move next. */
14422         next_addrinfo = res -> ai_next;
14423 
14424         /* Release the addrinfo memory. */
14425         tx_block_release((VOID *)res);
14426 
14427         res = next_addrinfo;
14428     }
14429 }
14430 
14431 
14432 /**************************************************************************/
14433 /*                                                                        */
14434 /*  FUNCTION                                               RELEASE        */
14435 /*                                                                        */
14436 /*    bsd_string_to_number                                PORTABLE C      */
14437 /*                                                           6.1          */
14438 /*  AUTHOR                                                                */
14439 /*                                                                        */
14440 /*    Yuxin Zhou, Microsoft Corporation                                   */
14441 /*                                                                        */
14442 /*  DESCRIPTION                                                           */
14443 /*                                                                        */
14444 /*    This function converts string to number.                            */
14445 /*                                                                        */
14446 /*  INPUT                                                                 */
14447 /*                                                                        */
14448 /*    string                                Pointer to a string           */
14449 /*    number                                Pointer to a number           */
14450 /*                                                                        */
14451 /*  OUTPUT                                                                */
14452 /*                                                                        */
14453 /*    status                                                              */
14454 /*                                                                        */
14455 /*  CALLS                                                                 */
14456 /*                                                                        */
14457 /*    nx_bsd_isdigit                        Indicate char is a number     */
14458 /*                                                                        */
14459 /*  CALLED BY                                                             */
14460 /*                                                                        */
14461 /*    Application Code                                                    */
14462 /*                                                                        */
14463 /*  RELEASE HISTORY                                                       */
14464 /*                                                                        */
14465 /*    DATE              NAME                      DESCRIPTION             */
14466 /*                                                                        */
14467 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14468 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
14469 /*                                            resulting in version 6.1    */
14470 /*                                                                        */
14471 /**************************************************************************/
bsd_string_to_number(const CHAR * string,UINT * number)14472 static INT bsd_string_to_number(const CHAR *string, UINT *number)
14473 {
14474 
14475     /* Initialize the numbet to zero. */
14476     *number = 0;
14477 
14478     while(*string != '\0')
14479     {
14480 
14481         /* Check if the current character is a digit character. */
14482         if(!nx_bsd_isdigit((UCHAR)(*string)))
14483             return NX_SOC_ERROR;
14484 
14485         *number = (*number * 10) + (UINT)(*string - 0x30);
14486 
14487         string++;
14488     }
14489 
14490     return NX_SOC_OK;
14491 }
14492 
14493 /**************************************************************************/
14494 /*                                                                        */
14495 /*  FUNCTION                                               RELEASE        */
14496 /*                                                                        */
14497 /*    getnameinfo                                         PORTABLE C      */
14498 /*                                                           6.3.0        */
14499 /*  AUTHOR                                                                */
14500 /*                                                                        */
14501 /*    Yuxin Zhou, Microsoft Corporation                                   */
14502 /*                                                                        */
14503 /*  DESCRIPTION                                                           */
14504 /*                                                                        */
14505 /*    This function converts a socket address to a corresponding host and */
14506 /*    service.                                                            */
14507 /*                                                                        */
14508 /*  INPUT                                                                 */
14509 /*                                                                        */
14510 /*    sa                                   Pointer to a generic socket    */
14511 /*                                           address structure            */
14512 /*    salen                                Length of sa structure         */
14513 /*    host                                 Pointer to caller-allocated    */
14514 /*                                           buffer for hostname          */
14515 /*    hostlen                              Host buffer size               */
14516 /*    serv                                 Pointer to caller-allocated    */
14517 /*                                           buffer for service name      */
14518 /*    servlen                              Service buffer size            */
14519 /*                                                                        */
14520 /*  OUTPUT                                                                */
14521 /*                                                                        */
14522 /*    status                               0 if OK, nonzero on errors     */
14523 /*                                                                        */
14524 /*  CALLS                                                                 */
14525 /*                                                                        */
14526 /*    nx_dns_host_by_address_get           Get hostname by IPv4 address   */
14527 /*    nxd_dns_host_by_address_get          Get hostname by IPv6 address   */
14528 /*                                                                        */
14529 /*  CALLED BY                                                             */
14530 /*                                                                        */
14531 /*    Application Code                                                    */
14532 /*                                                                        */
14533 /*  RELEASE HISTORY                                                       */
14534 /*                                                                        */
14535 /*    DATE              NAME                      DESCRIPTION             */
14536 /*                                                                        */
14537 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14538 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
14539 /*                                            verified memcpy use cases,  */
14540 /*                                            resulting in version 6.1    */
14541 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
14542 /*                                            used new API/structs naming,*/
14543 /*                                            resulting in version 6.3.0  */
14544 /*                                                                        */
14545 /**************************************************************************/
nx_bsd_getnameinfo(const struct nx_bsd_sockaddr * sa,nx_bsd_socklen_t salen,char * host,size_t hostlen,char * serv,size_t servlen,int flags)14546 INT  nx_bsd_getnameinfo(const struct nx_bsd_sockaddr *sa, nx_bsd_socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
14547 {
14548 
14549 UINT        i = 0;
14550 /* Flag used to identify whether host/service is numeric, 0 no, 1 yes. */
14551 UINT        numeric_flag;
14552 USHORT     *temp;
14553 #ifdef NX_BSD_ENABLE_DNS
14554 UINT        status;
14555 #ifdef FEATURE_NX_IPV6
14556 NXD_ADDRESS nxd_ipv6_addr;
14557 #endif
14558 #endif
14559 const CHAR  *rt_ptr;
14560 
14561     if(!sa)
14562     {
14563 
14564         /* sa is NULL. */
14565         return EAI_FAMILY;
14566     }
14567     else
14568     {
14569         if((sa -> sa_family != AF_INET)  &&
14570            (sa -> sa_family != AF_INET6))
14571         {
14572 
14573             /* sa isn't NULL, but family type is invalid. */
14574             return EAI_FAMILY;
14575         }
14576         else if((sa -> sa_family == AF_INET && salen != sizeof(struct nx_bsd_sockaddr_in)) ||
14577                 (sa -> sa_family == AF_INET6 && salen != sizeof(struct nx_bsd_sockaddr_in6)))
14578         {
14579 
14580             /* Address length is invalid. */
14581             return EAI_FAMILY;
14582         }
14583     }
14584 
14585     /* Both host and service null are invalid */
14586     if((host == NX_NULL) && (serv == NX_NULL) && ((flags & NI_NAMEREQD) == 0))
14587         return EAI_NONAME;
14588 
14589     if(serv && servlen > 0)
14590     {
14591         numeric_flag = 1;
14592 
14593         /* If NUMERICSERV bit is set, set to 1. */
14594         if(flags & NI_NUMERICSERV)
14595         {
14596             numeric_flag = 1;
14597         }
14598         else if(flags & NI_DGRAM)
14599         {
14600             /* Socket type must be SOCK_DGRAM. */
14601 
14602             for(i = 0; i < _nx_bsd_serv_list_len; i++)
14603             {
14604                 temp = (USHORT *)(sa -> sa_data);
14605                 if((_nx_bsd_serv_list_ptr[i].service_port == *temp) &&
14606                    (_nx_bsd_serv_list_ptr[i].service_socktype == SOCK_DGRAM))
14607                 {
14608 
14609                     /* Found a matched service, set numeric flag to 0. */
14610                     numeric_flag = 0;
14611                     break;
14612                 }
14613             }
14614         }
14615         else
14616         {
14617 
14618             /* Socket type is SOCK_STREAM. */
14619             for(i = 0; i < _nx_bsd_serv_list_len; i++)
14620             {
14621                 temp = (USHORT *)(sa -> sa_data);
14622                 if((_nx_bsd_serv_list_ptr[i].service_port == *temp) &&
14623                    (_nx_bsd_serv_list_ptr[i].service_socktype == SOCK_STREAM))
14624                 {
14625 
14626                     /* Found a matched service, set numeric flag to 0. */
14627                     numeric_flag = 0;
14628                     break;
14629                 }
14630             }
14631         }
14632 
14633         if(numeric_flag)
14634         {
14635 
14636             /* Service is numeric, copy the service port. Then convert host byte order to network byte order. */
14637             temp = (USHORT *)(sa -> sa_data);
14638             if(bsd_number_convert(htons(*temp), (CHAR *)serv, servlen, 10) == 0)
14639                 return EAI_OVERFLOW;
14640         }
14641         else
14642         {
14643 
14644             /* Service isn't numeric, copy the service name. */
14645             if(_nx_bsd_string_length(_nx_bsd_serv_list_ptr[i].service_name) > servlen)
14646                 return EAI_OVERFLOW;
14647 
14648             memcpy(serv, _nx_bsd_serv_list_ptr[i].service_name, /* Use case of memcpy is verified. */
14649                    _nx_bsd_string_length(_nx_bsd_serv_list_ptr[i].service_name));
14650         }
14651     }
14652 
14653     if(host && hostlen > 0)
14654     {
14655         numeric_flag = 1;
14656 
14657         /* If NUMERIC bit is set, set flag to 1. */
14658         if(flags & NI_NUMERICHOST)
14659             numeric_flag = 1;
14660         else
14661         {
14662 
14663 #ifdef NX_BSD_ENABLE_DNS
14664             if(sa -> sa_family == AF_INET)
14665             {
14666 
14667 #ifndef NX_DISABLE_IPV4
14668                 /* Get host name by IPv4 address via DNS. */
14669                 status = nx_dns_host_by_address_get(_nx_dns_instance_ptr, ntohl(((struct nx_bsd_sockaddr_in *)sa) -> sin_addr.s_addr),
14670                                                     (UCHAR *)host, hostlen, NX_BSD_TIMEOUT);
14671 #else
14672                 status = NX_DNS_NO_SERVER;
14673 #endif /* NX_DISABLE_IPV4 */
14674             }
14675             else
14676             {
14677 #ifdef FEATURE_NX_IPV6
14678                 /* copy data from sockaddr structure to NXD_ADDRESS structure. */
14679                 nxd_ipv6_addr.nxd_ip_version = NX_IP_VERSION_V6;
14680                 nxd_ipv6_addr.nxd_ip_address.v6[0] = ntohl(((struct nx_bsd_sockaddr_in6 *)sa) -> sin6_addr.s6_addr32[0]);
14681                 nxd_ipv6_addr.nxd_ip_address.v6[1] = ntohl(((struct nx_bsd_sockaddr_in6 *)sa) -> sin6_addr.s6_addr32[1]);
14682                 nxd_ipv6_addr.nxd_ip_address.v6[2] = ntohl(((struct nx_bsd_sockaddr_in6 *)sa) -> sin6_addr.s6_addr32[2]);
14683                 nxd_ipv6_addr.nxd_ip_address.v6[3] = ntohl(((struct nx_bsd_sockaddr_in6 *)sa) -> sin6_addr.s6_addr32[3]);
14684 
14685                 /* Get host name by IPv6 address via DNS. */
14686                 status = nxd_dns_host_by_address_get(_nx_dns_instance_ptr, &nxd_ipv6_addr,
14687                                                      (UCHAR *) host, hostlen, NX_BSD_TIMEOUT);
14688 #else
14689                 status = NX_DNS_NO_SERVER;
14690 #endif
14691             }
14692 
14693 
14694             if(status == NX_DNS_SIZE_ERROR)
14695                 return EAI_OVERFLOW;
14696             else if(status != NX_SUCCESS)
14697             {
14698 
14699                 /* DNS query fails. */
14700                 if(flags & NI_NAMEREQD)
14701                     return EAI_NONAME;
14702             }
14703             else
14704             {
14705 
14706                 /* DNS query succeeds. */
14707                 numeric_flag = 0;
14708             }
14709 #else
14710             if(flags & NI_NAMEREQD)
14711                 return EAI_NONAME;
14712 #endif
14713         }
14714 
14715         if(numeric_flag)
14716         {
14717 
14718             /* Host must be numeric string. Convert IP address from numeric to presentation. */
14719             if(sa -> sa_family == AF_INET)
14720                 rt_ptr = nx_bsd_inet_ntop(AF_INET, &((struct nx_bsd_sockaddr_in*)sa) -> sin_addr, (CHAR *)host, hostlen);
14721             else
14722                 rt_ptr = nx_bsd_inet_ntop(AF_INET6, &((struct nx_bsd_sockaddr_in6*)sa) -> sin6_addr, (CHAR *)host, hostlen);
14723 
14724             if(!rt_ptr)
14725                 return EAI_OVERFLOW;
14726         }
14727 
14728     }
14729 
14730     return 0;
14731 }
14732 
14733 /**************************************************************************/
14734 /*                                                                        */
14735 /*  FUNCTION                                               RELEASE        */
14736 /*                                                                        */
14737 /*    nx_bsd_set_service_list                             PORTABLE C      */
14738 /*                                                           6.1          */
14739 /*  AUTHOR                                                                */
14740 /*                                                                        */
14741 /*    Yuxin Zhou, Microsoft Corporation                                   */
14742 /*                                                                        */
14743 /*  DESCRIPTION                                                           */
14744 /*                                                                        */
14745 /*    This function lets user set the service list used by getaddrinfo    */
14746 /*                                                                        */
14747 /*  INPUT                                                                 */
14748 /*                                                                        */
14749 /*    serv_list_ptr                        Pointer to a service list      */
14750 /*    serv_list_len                        Service list length            */
14751 /*                                                                        */
14752 /*  OUTPUT                                                                */
14753 /*                                                                        */
14754 /*    None                                                                */
14755 /*                                                                        */
14756 /*  CALLS                                                                 */
14757 /*                                                                        */
14758 /*    None                                                                */
14759 /*                                                                        */
14760 /*  CALLED BY                                                             */
14761 /*                                                                        */
14762 /*    Application Code                                                    */
14763 /*                                                                        */
14764 /*  RELEASE HISTORY                                                       */
14765 /*                                                                        */
14766 /*    DATE              NAME                      DESCRIPTION             */
14767 /*                                                                        */
14768 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14769 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
14770 /*                                            resulting in version 6.1    */
14771 /*                                                                        */
14772 /**************************************************************************/
nx_bsd_set_service_list(struct NX_BSD_SERVICE_LIST * serv_list_ptr,ULONG serv_list_len)14773 VOID nx_bsd_set_service_list(struct NX_BSD_SERVICE_LIST *serv_list_ptr, ULONG serv_list_len)
14774 {
14775     _nx_bsd_serv_list_ptr = serv_list_ptr;
14776     _nx_bsd_serv_list_len = serv_list_len;
14777 }
14778 
14779 
14780 /**************************************************************************/
14781 /*                                                                        */
14782 /*  FUNCTION                                               RELEASE        */
14783 /*                                                                        */
14784 /*    _nx_bsd_string_length                               PORTABLE C      */
14785 /*                                                           6.1          */
14786 /*  AUTHOR                                                                */
14787 /*                                                                        */
14788 /*    Yuxin Zhou, Microsoft Corporation                                   */
14789 /*                                                                        */
14790 /*  DESCRIPTION                                                           */
14791 /*                                                                        */
14792 /*    This function returns the length of string.                         */
14793 /*                                                                        */
14794 /*  INPUT                                                                 */
14795 /*                                                                        */
14796 /*    string                               Pointer to a string            */
14797 /*                                                                        */
14798 /*  OUTPUT                                                                */
14799 /*                                                                        */
14800 /*    ULONG                                String length                  */
14801 /*                                                                        */
14802 /*  CALLS                                                                 */
14803 /*                                                                        */
14804 /*    None                                                                */
14805 /*                                                                        */
14806 /*  CALLED BY                                                             */
14807 /*                                                                        */
14808 /*    NetX Duo BSD Layer Source Code                                      */
14809 /*                                                                        */
14810 /*  RELEASE HISTORY                                                       */
14811 /*                                                                        */
14812 /*    DATE              NAME                      DESCRIPTION             */
14813 /*                                                                        */
14814 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14815 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
14816 /*                                            resulting in version 6.1    */
14817 /*                                                                        */
14818 /**************************************************************************/
_nx_bsd_string_length(CHAR * string)14819 static ULONG _nx_bsd_string_length(CHAR * string)
14820 {
14821 int length = 0;
14822 
14823     while(*string != '\0')
14824     {
14825         length++;
14826         string++;
14827     }
14828 
14829     return((ULONG)length);
14830 
14831 }
14832 
14833 
14834 /**************************************************************************/
14835 /*                                                                        */
14836 /*  FUNCTION                                               RELEASE        */
14837 /*                                                                        */
14838 /*    _nx_bsd_fast_periodic_timer_entry                   PORTABLE C      */
14839 /*                                                           6.1          */
14840 /*  AUTHOR                                                                */
14841 /*                                                                        */
14842 /*    Yuxin Zhou, Microsoft Corporation                                   */
14843 /*                                                                        */
14844 /*  DESCRIPTION                                                           */
14845 /*                                                                        */
14846 /*    This function handles BSD system clock. When the timer expires, the */
14847 /*    BSD system clock is updated and then default IP fast periodic entry */
14848 /*    routine is invoked.                                                 */
14849 /*                                                                        */
14850 /*  INPUT                                                                 */
14851 /*                                                                        */
14852 /*    id                                   Argument of default timer entry*/
14853 /*                                                                        */
14854 /*  OUTPUT                                                                */
14855 /*                                                                        */
14856 /*    None                                                                */
14857 /*                                                                        */
14858 /*  CALLS                                                                 */
14859 /*                                                                        */
14860 /*    None                                                                */
14861 /*                                                                        */
14862 /*  CALLED BY                                                             */
14863 /*                                                                        */
14864 /*    None                                                                */
14865 /*                                                                        */
14866 /*  RELEASE HISTORY                                                       */
14867 /*                                                                        */
14868 /*    DATE              NAME                      DESCRIPTION             */
14869 /*                                                                        */
14870 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14871 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
14872 /*                                            resulting in version 6.1    */
14873 /*                                                                        */
14874 /**************************************************************************/
_nx_bsd_fast_periodic_timer_entry(ULONG id)14875 static VOID  _nx_bsd_fast_periodic_timer_entry(ULONG id)
14876 {
14877 
14878     /* Update the BSD system clock. */
14879     nx_bsd_system_clock += nx_bsd_timer_rate;
14880 
14881     /* Call default IP fast periodic timer entry. */
14882     nx_bsd_ip_fast_periodic_timer_entry(id);
14883 }
14884 
14885 
14886 /**************************************************************************/
14887 /*                                                                        */
14888 /*  FUNCTION                                               RELEASE        */
14889 /*                                                                        */
14890 /*    poll                                                PORTABLE C      */
14891 /*                                                           6.3.0        */
14892 /*  AUTHOR                                                                */
14893 /*                                                                        */
14894 /*    Chaoqiong Xiao, Microsoft Corporation                               */
14895 /*                                                                        */
14896 /*  DESCRIPTION                                                           */
14897 /*                                                                        */
14898 /*    This function allows for list of sockets to be checked for incoming */
14899 /*    events.                                                             */
14900 /*                                                                        */
14901 /*    Before invoked, each item inside fds array should be initialized,   */
14902 /*    pollfd::fd must be the descriptor ID to check and pollfd::events    */
14903 /*    must be the events (bits) to check.                                 */
14904 /*                                                                        */
14905 /*    Returned, the pollfd::revents of each item is updated, to indicate  */
14906 /*    if the checked events happen.                                       */
14907 /*                                                                        */
14908 /*    The event (bit) currently supported:                                */
14909 /*    - POLLIN : checking socket read FD                                  */
14910 /*    - POLLOUT: checking socket write FD                                 */
14911 /*    - POLLPRI: checking socket exception FD                             */
14912 /*                                                                        */
14913 /*    NOTE:  ****** When select returns NX_SOC_ERROR it won't update      */
14914 /*           the fds descriptor.                                          */
14915 /*                                                                        */
14916 /*  INPUT                                                                 */
14917 /*                                                                        */
14918 /*    fds                                  Socket descriptor list to poll */
14919 /*                                           and report actual status     */
14920 /*    nfds                                 Number of socket descriptors   */
14921 /*    timeOut                              Timeout in microseconds, set   */
14922 /*                                         to below 0 to wait infinitely  */
14923 /*                                                                        */
14924 /*  OUTPUT                                                                */
14925 /*                                                                        */
14926 /*    NX_SUCCESS                            Descriptors check ends        */
14927 /*                                           (successful completion)      */
14928 /*    NX_SOC_ERROR (-1)                     Error occured                 */
14929 /*                                                                        */
14930 /*  CALLS                                                                 */
14931 /*                                                                        */
14932 /*    FD_ZERO                               Clear a socket ready list     */
14933 /*    FD_ISSET                              Check a socket is ready       */
14934 /*    FD_SET                                Set a socket                  */
14935 /*    select                                Perform checks, see select()  */
14936 /*    set_errno                             Set the error code            */
14937 /*                                                                        */
14938 /*  CALLED BY                                                             */
14939 /*                                                                        */
14940 /*    Application Code                                                    */
14941 /*                                                                        */
14942 /*  RELEASE HISTORY                                                       */
14943 /*                                                                        */
14944 /*    DATE              NAME                      DESCRIPTION             */
14945 /*                                                                        */
14946 /*  10-31-2023     Chaoqiong Xiao           Initial Version 6.3.0         */
14947 /*                                                                        */
14948 /**************************************************************************/
nx_bsd_poll(struct nx_bsd_pollfd * fds,ULONG nfds,INT timeout)14949 INT  nx_bsd_poll(struct nx_bsd_pollfd *fds, ULONG nfds, INT timeout)
14950 {
14951 nx_bsd_fd_set           read_fds;
14952 nx_bsd_fd_set           write_fds;
14953 nx_bsd_fd_set           except_fds;
14954 struct nx_bsd_timeval   stime;
14955 struct nx_bsd_timeval   *ptime;
14956 INT                     n_ready_fds;
14957 INT                     max_fd;
14958 ULONG                   i;
14959 struct nx_bsd_pollfd    *poll_fd;
14960 
14961     /* Check input parameter.  */
14962     if (fds == NX_NULL)
14963     {
14964         nx_bsd_set_errno(EFAULT);
14965         return(NX_SOC_ERROR);
14966     }
14967     if (nfds == 0)
14968     {
14969         nx_bsd_set_errno(EFAULT);
14970         return(NX_SOC_ERROR);
14971     }
14972 
14973     /* Initialize local FDs.  */
14974     NX_BSD_FD_ZERO(&read_fds);
14975     NX_BSD_FD_ZERO(&write_fds);
14976     NX_BSD_FD_ZERO(&except_fds);
14977 
14978     /* Map the poll() FD to select() FDs.  */
14979     max_fd = 0;
14980     for(i = 0; i < nfds; i ++)
14981     {
14982         poll_fd = &fds[i];
14983 
14984         /* Skip bad FDs.  */
14985         if (poll_fd -> fd < 0)
14986             continue;
14987 
14988         /* POLLIN.  */
14989         if (poll_fd -> events & POLLIN)
14990         {
14991             NX_BSD_FD_SET(poll_fd -> fd, &read_fds);
14992         }
14993 
14994         /* POLLOUT.  */
14995         if (poll_fd -> events & POLLOUT)
14996         {
14997             NX_BSD_FD_SET(poll_fd -> fd, &write_fds);
14998         }
14999 
15000         /* POLLPRI.  */
15001         if (poll_fd -> events & POLLPRI)
15002         {
15003             NX_BSD_FD_SET(poll_fd -> fd, &except_fds);
15004         }
15005 
15006         /* Update max FD.  */
15007         if (poll_fd -> fd > max_fd)
15008             max_fd = poll_fd -> fd;
15009     }
15010 
15011     /* Map the select() timeout.  */
15012     if (timeout < 0)
15013     {
15014 
15015         /* select() wait infinitely.  */
15016         ptime = NX_NULL;
15017     }
15018     else
15019     {
15020 
15021         /* select() uses timeval option.  */
15022         ptime = &stime;
15023 
15024         if (timeout == 0)
15025         {
15026 
15027             /* select() no wait.  */
15028             ptime -> tv_sec = 0;
15029             ptime -> tv_usec = 0;
15030         }
15031         else
15032         {
15033 
15034             /* select() wait specific time in ms.  */
15035             ptime -> tv_sec = (timeout / 1000);
15036             ptime -> tv_usec = (timeout % 1000);
15037         }
15038 
15039     }
15040 
15041     /* Invoke select().  */
15042     n_ready_fds = nx_bsd_select(max_fd + 1, &read_fds, &write_fds, &except_fds, ptime);
15043 
15044     /* Parse result events if FDs updated.  */
15045     if (n_ready_fds)
15046     {
15047 
15048         for (i = 0; i < nfds; i ++)
15049         {
15050             poll_fd = &fds[i];
15051 
15052             /* Skip bad FDs.  */
15053             if (poll_fd -> fd < 0)
15054                 continue;
15055 
15056             /* Exceptions.  */
15057             if (NX_BSD_FD_ISSET(poll_fd -> fd, &except_fds))
15058                 poll_fd -> revents |= POLLPRI;
15059 
15060             else
15061             {
15062 
15063                 /* Inputs.  */
15064                 if (NX_BSD_FD_ISSET(poll_fd -> fd, &read_fds))
15065                     poll_fd -> revents |= POLLIN;
15066             }
15067 
15068             /* Outputs.  */
15069             if (NX_BSD_FD_ISSET(poll_fd -> fd, &write_fds))
15070                 poll_fd -> revents |= POLLOUT;
15071         }
15072     }
15073 
15074     return(n_ready_fds);
15075 }
15076