1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 /**************************************************************************/
12 /**************************************************************************/
13 /**                                                                       */
14 /** BSD 4.3 Socket API Compatible Interface to NetX Duo                   */
15 /**                                                                       */
16 /**************************************************************************/
17 /**************************************************************************/
18 
19 
20 /* Include necessary files.  */
21 #include "nx_api.h"
22 #include "nx_packet.h"
23 #include "nx_tcp.h"
24 #include "nx_ip.h"
25 
26 #include "nx_ipv6.h"
27 #include "nx_ipv4.h"
28 #include "nxd_bsd.h"
29 #include "nx_link.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 #if (defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)) && defined(NX_ENABLE_VLAN)
126 NX_LINK_RECEIVE_QUEUE  nx_bsd_socket_link_receive_queue[NX_MAX_IP_INTERFACES];
127 #endif
128 
129 /* Buffer used to store IP address get from DNS. */
130 static ULONG           nx_bsd_ipv4_addr_buffer[NX_BSD_IPV4_ADDR_PER_HOST];
131 static ULONG           nx_bsd_ipv6_addr_buffer[NX_BSD_IPV6_ADDR_PER_HOST * 4];
132 
133 /* Utility character type functions*/
134 static UINT nx_bsd_isspace(UCHAR c);
135 static UINT nx_bsd_islower(UCHAR c);
136 static UINT nx_bsd_isdigit(UCHAR c);
137 static UINT nx_bsd_isxdigit(UCHAR c);
138 
139 /* Standard BSD callback functions to register with NetX Duo. */
140 
141 static VOID  nx_bsd_tcp_receive_notify(NX_TCP_SOCKET *socket_ptr);
142 static VOID  nx_bsd_tcp_socket_disconnect_notify(NX_TCP_SOCKET *socket_ptr);
143 static VOID  nx_bsd_udp_receive_notify(NX_UDP_SOCKET *socket_ptr);
144 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
145 static UINT  nx_bsd_raw_packet_filter(NX_IP *ip_ptr, ULONG protocol, NX_PACKET *packet_ptr);
146 #ifdef FEATURE_NX_IPV6
147 static VOID  _nxd_bsd_swap_ipv6_extension_headers(NX_PACKET *packet_ptr, UCHAR header_type);
148 #endif /* FEATURE_NX_IPV6 */
149 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
150 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
151 static VOID  nx_bsd_tcp_establish_notify(NX_TCP_SOCKET *socket_ptr);
152 #endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */
153 static VOID  nx_bsd_select_wakeup(UINT sock_id, UINT fdsets);
154 static VOID  nx_bsd_set_error_code(NX_BSD_SOCKET *bsd_socket_ptr, UINT status_code);
155 static VOID  nx_bsd_udp_packet_received(INT sockID, NX_PACKET *packet_ptr);
156 static UINT  nx_bsd_tcp_syn_received_notify(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr);
157 static INT   nx_bsd_tcp_create_listen_socket(INT master_sockid, INT backlog);
158 static VOID  nx_bsd_tcp_pending_connection(UINT local_port, NX_TCP_SOCKET *socket_ptr);
159 static INT   nx_bsd_find_interface_by_source_addr(UINT addr_family, ULONG* ip_addr);
160 #ifndef NX_DISABLE_IPV4
161 static VOID  _nxd_bsd_ipv4_packet_send(NX_PACKET *packet_ptr);
162 #endif /* NX_DISABLE_IPV4 */
163 static INT   nx_bsd_send_internal(INT sockID, const CHAR *msg, INT msgLength, INT flags,
164                                   NXD_ADDRESS *dst_address, USHORT dst_port, UINT local_interface_index);
165 static INT   nx_bsd_recv_internal(INT sockID, struct nx_bsd_iovec *iov, size_t iovlen, INT flags,
166                                   struct nx_bsd_sockaddr *fromAddr, INT *fromAddrLen);
167 #ifdef FEATURE_NX_IPV6
168 static VOID  _nxd_bsd_ipv6_packet_send(NX_PACKET *packet_ptr, ULONG *src_addr, ULONG *dest_addr);
169 #endif /* FEATURE_NX_IPV6 */
170 
171 static INT   inet_ntoa_internal(const VOID *src, CHAR *dst, ULONG dst_size);
172 static INT   bsd_string_to_number(const CHAR *string, UINT *number);
173 static ULONG _nx_bsd_string_length(CHAR * string);
174 
175 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
176 static INT   nx_bsd_pppoe_internal_sendto(NX_BSD_SOCKET *bsd_socket_ptr, CHAR *msg, INT msgLength,
177                                           INT flags,  struct nx_bsd_sockaddr* destAddr, INT destAddrLen);
178 static UINT  nx_bsd_socket_create_id = 0;
179 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
180 
181 #ifdef NX_BSD_RAW_SUPPORT
182 static INT   _nx_bsd_hardware_internal_sendto(NX_BSD_SOCKET *bsd_socket_ptr, CHAR *msg, INT msgLength,
183                                               INT flags,  struct nx_bsd_sockaddr* destAddr, INT destAddrLen);
184 static VOID  _nx_bsd_hardware_packet_received(NX_PACKET *packet_ptr, UCHAR *consumed);
185 #ifdef NX_ENABLE_VLAN
186 static UINT  _nx_bsd_ethernet_receive_notify(NX_IP *ip_ptr, UINT interface_index, NX_PACKET *packet_ptr,
187                                              ULONG physical_address_msw, ULONG physical_address_lsw,
188                                              UINT packet_type, UINT header_size, VOID *context,
189                                              struct NX_LINK_TIME_STRUCT *time_ptr);
190 #endif /* NX_ENABLE_VLAN */
191 #endif /* NX_BSD_RAW_SUPPORT */
192 static VOID  _nx_bsd_fast_periodic_timer_entry(ULONG id);
193 
194 #ifndef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
195 TX_THREAD               nx_bsd_task_thread;
196 static VOID             nx_bsd_thread_entry(ULONG info);
197 #else
198 static TX_TIMER         nx_bsd_timer;
199 static VOID             nx_bsd_timer_entry(ULONG info);
200 #endif
201 UINT  bsd_number_convert(UINT number, CHAR *string, ULONG buffer_len, UINT base);
202 VOID  nx_bsd_socket_timed_wait_callback(NX_TCP_SOCKET *tcp_socket_ptr);
203 
204 #define FDSET_READ       1
205 #define FDSET_WRITE      2
206 #define FDSET_EXCEPTION  4
207 
208 extern TX_THREAD       *_tx_thread_current_ptr;
209 
210 static ULONG  _nx_bsd_serv_list_len;
211 static struct NX_BSD_SERVICE_LIST  *_nx_bsd_serv_list_ptr;
212 
213 
214 /**************************************************************************/
215 /*                                                                        */
216 /*  FUNCTION                                               RELEASE        */
217 /*                                                                        */
218 /*    bsd_initialize                                      PORTABLE C      */
219 /*                                                           6.3.0        */
220 /*  AUTHOR                                                                */
221 /*                                                                        */
222 /*    Yuxin Zhou, Microsoft Corporation                                   */
223 /*                                                                        */
224 /*  DESCRIPTION                                                           */
225 /*                                                                        */
226 /*    This function sets up all data structures and NetX, and ThreadX     */
227 /*    resources needed by the BSD compatibility layer. It is recommended  */
228 /*    to call this routine from tx_application_define.                    */
229 /*                                                                        */
230 /*  INPUTS                                                                */
231 /*                                                                        */
232 /*    *default_ip                           NX_IP created for BSD API     */
233 /*    *default_pool                         Packet Pool used by BSD API   */
234 /*    *bsd_thread_stack_area                Stack memory pointer for the  */
235 /*                                            BSD thread stack space      */
236 /*     bsd_thread_stack_size                Size of thread stack          */
237 /*     bsd_thread_priority                  BSD thread priority           */
238 /*                                                                        */
239 /*  OUTPUT                                                                */
240 /*                                                                        */
241 /*    NX_SUCCESS                            Successful completion         */
242 /*    NX_BSD_BLOCK_POOL_ERROR               Error creating socket block   */
243 /*                                            pool                        */
244 /*    NX_BSD_EVENT_ERROR                    Error creating the event flag */
245 /*                                            group                       */
246 /*    NX_BSD_MUTEX_ERROR                    Error creating mutex          */
247 /*    NX_BSD_ENVIRONMENT_ERROR              Error environment             */
248 /*                                                                        */
249 /*  CALLS                                                                 */
250 /*                                                                        */
251 /*    memset                                Set memory                    */
252 /*    tx_block_pool_create                  Create a block pool           */
253 /*    tx_block_pool_delete                  Delete a block pool           */
254 /*    tx_event_flags_create                 Create event flag group       */
255 /*    tx_mutex_create                       Create protection mutex       */
256 /*    tx_mutex_delete                       Delete protection mutex       */
257 /*                                                                        */
258 /*  CALLED BY                                                             */
259 /*                                                                        */
260 /*    Start-up code                                                       */
261 /*                                                                        */
262 /*  RELEASE HISTORY                                                       */
263 /*                                                                        */
264 /*    DATE              NAME                      DESCRIPTION             */
265 /*                                                                        */
266 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
267 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
268 /*                                            resulting in version 6.1    */
269 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
270 /*                                            used new API/structs naming,*/
271 /*                                            resulting in version 6.3.0  */
272 /*  12-31-2023     Yanwu Cai                Modified comment(s), and      */
273 /*                                            added nx_link layer,        */
274 /*                                            resulting in version 6.4.0  */
275 /*                                                                        */
276 /**************************************************************************/
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)277 INT  nx_bsd_initialize(NX_IP *default_ip, NX_PACKET_POOL *default_pool, CHAR *bsd_thread_stack_area,
278                     ULONG bsd_thread_stack_size, UINT bsd_thread_priority)
279 {
280 
281 INT         i;
282 UINT        status;
283 ULONG       info;
284 
285 #ifndef NX_ENABLE_EXTENDED_NOTIFY_SUPPORT
286 
287     /* Error, return the error message.  */
288     /* BSD doesn't work with out NX_ENABLE_EXTENDED_NOTIFY_SUPPORT option. */
289     NX_BSD_ERROR(NX_BSD_ENVIRONMENT_ERROR, __LINE__);
290     return(NX_BSD_ENVIRONMENT_ERROR);
291 #endif /* NX_ENABLE_EXTENDED_NOTIFY_SUPPORT */
292 
293     /* Create a block pool for dynamically allocating sockets.  */
294     status =  tx_block_pool_create(&nx_bsd_socket_block_pool, "NetX BSD Socket Block Pool", sizeof(NX_TCP_SOCKET),
295                                    nx_bsd_socket_pool_memory, sizeof(nx_bsd_socket_pool_memory));
296 
297     /* Determine if the pool was created.  */
298     if (status)
299     {
300 
301         /* Error, return the error message.  */
302         NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
303         return(NX_BSD_BLOCK_POOL_ERROR);
304     }
305 
306     /* Create a block pool for dynamically allocating addrinfo. */
307     status = tx_block_pool_create(&nx_bsd_addrinfo_block_pool, "NetX BSD Addrinfo Block Pool", sizeof(struct nx_bsd_addrinfo),
308                                   nx_bsd_addrinfo_pool_memory, sizeof(nx_bsd_addrinfo_pool_memory));
309 
310     /* Determine if the pool was created. */
311     if(status)
312     {
313 
314         /* Error, return the error messafe. */
315         NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
316 
317         /* Delete the block pool.  */
318         tx_block_pool_delete(&nx_bsd_socket_block_pool);
319         return(NX_BSD_BLOCK_POOL_ERROR);
320 
321     }
322 
323 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
324     /* Create a block pool for dynamically allocating canonical name buffer. */
325     status = tx_block_pool_create(&nx_bsd_cname_block_pool, "NetX BSD CNAME Block Pool", (NX_DNS_NAME_MAX + 1),
326                                   nx_bsd_cname_pool_memory, sizeof(nx_bsd_cname_pool_memory));
327 
328     /* Determine if the pool was created. */
329     if(status)
330     {
331 
332         /* Error, return the error messafe. */
333         NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
334 
335         /* Delete the block pool.  */
336         tx_block_pool_delete(&nx_bsd_socket_block_pool);
337         tx_block_pool_delete(&nx_bsd_addrinfo_block_pool);
338         return(NX_BSD_BLOCK_POOL_ERROR);
339 
340     }
341 #endif
342 
343     nx_bsd_protection_ptr = &default_ip -> nx_ip_protection;
344 
345     /* Create the BSD event flag group.   */
346     status =  tx_event_flags_create(&nx_bsd_events, "NetX BSD Events");
347 
348     /* Check the return status.  */
349     if (status)
350     {
351         /* Delete the block pool.  */
352         tx_block_pool_delete(&nx_bsd_socket_block_pool);
353         tx_block_pool_delete(&nx_bsd_addrinfo_block_pool);
354 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
355         tx_block_pool_delete(&nx_bsd_cname_block_pool);
356 #endif
357 
358         /* Error present, return error code.  */
359         NX_BSD_ERROR(NX_BSD_EVENT_ERROR, __LINE__);
360         return(NX_BSD_EVENT_ERROR);
361     }
362 
363     /* Set the array index to 0.  */
364     nx_bsd_socket_array_index =  0;
365 
366     /* Loop through the BSD socket array and clear it out!  */
367     for (i = 0; i < NX_BSD_MAX_SOCKETS; i++)
368     {
369 
370         /* Clear the BSD socket structure.  */
371         memset((VOID*) &nx_bsd_socket_array[i], 0, sizeof(NX_BSD_SOCKET));
372     }
373 
374     /* Save the IP instance and NX_PACKET_POOL for BSD Socket API.  */
375     nx_bsd_default_ip =           default_ip;
376     nx_bsd_default_packet_pool =  default_pool;
377 
378 
379     if ((bsd_thread_stack_area == TX_NULL) || (bsd_thread_stack_size == 0))
380     {
381         /* Return error.  */
382         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
383         return(NX_SOC_ERROR);
384     }
385 
386 #ifndef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
387     /* Create a thread for BSD socket features requiring periodic tasks.  */
388     info = 0 ;
389     status = tx_thread_create(&nx_bsd_task_thread, "BSD thread task", nx_bsd_thread_entry, info,
390                               bsd_thread_stack_area, bsd_thread_stack_size, bsd_thread_priority,
391                               bsd_thread_priority, 1, TX_AUTO_START);
392 
393      if (status != TX_SUCCESS)
394      {
395          /* Delete the event flag group.  */
396          tx_event_flags_delete(&nx_bsd_events);
397 
398          /* Delete the block pool.  */
399          tx_block_pool_delete(&nx_bsd_socket_block_pool);
400          tx_block_pool_delete(&nx_bsd_addrinfo_block_pool);
401 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
402         tx_block_pool_delete(&nx_bsd_cname_block_pool);
403 #endif
404 
405          /* Error, return the error message.  */
406          NX_BSD_ERROR(NX_BSD_THREAD_ERROR, __LINE__);
407 
408          /* Return an error.  */
409          return(NX_IP_INTERNAL_ERROR);
410      }
411 #else
412 
413     info = 0 ;
414 
415     /* Create a one shot timer. Do not activate it. We will use it if
416        a socket being disconnected is NOT enabled for REUSEADDR socket option. */
417     status = tx_timer_create(&nx_bsd_timer, "BSD Timer",
418                              nx_bsd_timer_entry, info,
419                              NX_BSD_TIMER_RATE, NX_BSD_TIMER_RATE, TX_AUTO_START);
420 
421     if (status != TX_SUCCESS)
422     {
423 
424         /* Delete the event flag group.  */
425         tx_event_flags_delete(&nx_bsd_events);
426 
427         /* Delete the block pool.  */
428         tx_block_pool_delete(&nx_bsd_socket_block_pool);
429         tx_block_pool_delete(&nx_bsd_addrinfo_block_pool);
430 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
431         tx_block_pool_delete(&nx_bsd_cname_block_pool);
432 #endif
433 
434 #ifndef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
435         /* Delete the thread. */
436         tx_thread_delete(&nx_bsd_task_thread);
437 #endif
438         /* Error, return the error message.  */
439         NX_BSD_ERROR(NX_BSD_THREAD_ERROR, __LINE__);
440 
441         /* Return an error.  */
442         return(NX_IP_INTERNAL_ERROR);
443     }
444 #endif
445 
446 #ifdef NX_BSD_RAW_SUPPORT
447 #ifdef NX_ENABLE_VLAN
448 
449     /* set link layer receive notification */
450     for(i = 0; i< NX_MAX_IP_INTERFACES; i++)
451     {
452 
453         status = nx_link_packet_receive_callback_add(default_ip,
454                                                      i,
455                                                      &nx_bsd_socket_link_receive_queue[i],
456                                                      NX_LINK_PACKET_TYPE_ALL,
457                                                      _nx_bsd_ethernet_receive_notify,
458                                                      NX_NULL);
459         if (status != NX_SUCCESS)
460         {
461             return(status);
462         }
463     }
464 #else
465     _nx_driver_hardware_packet_received_callback = _nx_bsd_hardware_packet_received;
466 #endif /* NX_ENABLE_VLAN */
467 #endif /* NX_BSD_RAW_SUPPORT */
468 
469     /* Calculate BSD system timer rate. */
470     nx_bsd_timer_rate = (NX_IP_PERIODIC_RATE + (NX_IP_FAST_TIMER_RATE - 1)) / NX_IP_FAST_TIMER_RATE;
471 
472     /* Return success!  */
473     return(NX_SOC_OK);
474 }
475 
476 
477 /**************************************************************************/
478 /*                                                                        */
479 /*  FUNCTION                                               RELEASE        */
480 /*                                                                        */
481 /*    nx_bsd_timeout_process                              PORTABLE C      */
482 /*                                                           6.1          */
483 /*  AUTHOR                                                                */
484 /*                                                                        */
485 /*    Yuxin Zhou, Microsoft Corporation                                   */
486 /*                                                                        */
487 /*  DESCRIPTION                                                           */
488 /*                                                                        */
489 /*    This function checks for sockets waiting to make a TCP connection.  */
490 /*                                                                        */
491 /*  INPUT                                                                 */
492 /*                                                                        */
493 /*    None                                                                */
494 /*                                                                        */
495 /*  OUTPUT                                                                */
496 /*                                                                        */
497 /*    None                                                                */
498 /*                                                                        */
499 /*  CALLS                                                                 */
500 /*                                                                        */
501 /*    tx_mutex_get                         Obtain exclusive access to     */
502 /*    tx_mutex_put                         Release exclusive access       */
503 /*    nx_tcp_server_socket_unaccept        Remove socket from listen list */
504 /*    nx_tcp_server_socket_relisten        Restore socket to listening    */
505 /*    nx_tcp_server_socket_accept          Accept to connection request   */
506 /*                                                                        */
507 /*  CALLED BY                                                             */
508 /*                                                                        */
509 /*    ThreadX                                                             */
510 /*                                                                        */
511 /*  RELEASE HISTORY                                                       */
512 /*                                                                        */
513 /*    DATE              NAME                      DESCRIPTION             */
514 /*                                                                        */
515 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
516 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
517 /*                                            resulting in version 6.1    */
518 /*                                                                        */
519 /**************************************************************************/
nx_bsd_timeout_process()520 static VOID nx_bsd_timeout_process()
521 {
522 
523 INT             i;
524 ULONG           status;
525 INT             master_socket_index;
526 NX_BSD_SOCKET  *bsd_socket_ptr;
527 
528 
529    /* Obtain the BSD lock. */
530    status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
531 
532    if(status)
533    {
534        /* Mutex operation failed.  This should be fatal. */
535        return;
536    }
537 
538    for( i = 0; i < NX_BSD_MAX_SOCKETS; i++)
539    {
540 
541        /* Skip the unused sockets. */
542        if(!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
543        {
544 
545            continue;
546        }
547 
548        /* Skip if it is not TCP server socket. */
549        if((nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket == NX_NULL) ||
550           ((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CLIENT)))
551        {
552            continue;
553        }
554 
555        /* Check for sockets trying to make a TCP connection.
556           Detect that the socket state is CLOSED, which is an indication
557           that the attempted connection failed, and we shall signal any pending
558           select on the socket. */
559        if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_INPROGRESS)
560        {
561 
562            /* Is the NetX socket closed? */
563            if(nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket -> nx_tcp_socket_state == NX_TCP_CLOSED)
564            {
565 
566                /* Yes. Set up a local pointer to the BSD socket. */
567                bsd_socket_ptr = &nx_bsd_socket_array[i];
568 
569                /* Is this a secondary socket (passive open)? */
570                if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET)
571                {
572 
573                    /* Yes; Is the socket is connected yet? */
574                    if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED))
575                    {
576 
577                        /* No; Turn off the disconnection_request flag. */
578                        bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_DISCONNECTION_REQUEST);
579 
580                        /* Remove the underlying NetX socket from the listen state. */
581                        nx_tcp_server_socket_unaccept(bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
582 
583                        /* Check if a listen request is queued up for this socket. */
584                        nx_bsd_tcp_pending_connection(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port,
585                                                      bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
586 
587                        /* Relisten on this socket. */
588                        status = nx_tcp_server_socket_relisten(nx_bsd_default_ip,
589                                                               bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port,
590                                                               bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
591                        /* Set the socket to accept the connection. */
592                        nx_tcp_server_socket_accept(bsd_socket_ptr -> nx_bsd_socket_tcp_socket, NX_NO_WAIT);
593 
594                        /* Check the result of the relisten call. */
595                        if(status == NX_CONNECTION_PENDING)
596                        {
597 
598                            bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
599                        }
600                        else if(status != NX_SUCCESS)
601                        {
602 
603 
604                            /* Failed the relisten on the secondary socket.  Set the error code on the
605                               master socket, and wake it up. */
606 
607                            master_socket_index = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id;
608 
609                            nx_bsd_socket_array[master_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
610                            nx_bsd_set_error_code(&nx_bsd_socket_array[master_socket_index], status);
611 
612                            nx_bsd_select_wakeup((UINT)master_socket_index, (FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION));
613                        }
614                    }
615                }
616                else
617                {
618                    /* The underlying socket is closed.  This indicates an error, and since is a non-blocking
619                       socket, we need to wake up the corresponding thread. */
620 
621                    /* Mark this socket as error, and remove the CONNECT and INPROGRESS flags */
622                    nx_bsd_socket_array[i].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
623                    nx_bsd_socket_array[i].nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
624                    nx_bsd_socket_array[i].nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTED);
625                    nx_bsd_socket_array[i].nx_bsd_socket_error_code = ECONNREFUSED;
626 
627                    /* Wake up the socket that could be listening on it. */
628                    /* Notice that on error the both read and write are selectable. */
629                    nx_bsd_select_wakeup((UINT)i, FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION);
630                }
631            }
632        }
633    }
634 
635    /* Release the mutex. */
636    tx_mutex_put(nx_bsd_protection_ptr);
637 }
638 
639 /**************************************************************************/
640 /*                                                                        */
641 /*  FUNCTION                                               RELEASE        */
642 /*                                                                        */
643 /*    nx_bsd_thread_entry                                 PORTABLE C      */
644 /*                                                           6.1          */
645 /*  AUTHOR                                                                */
646 /*                                                                        */
647 /*    Yuxin Zhou, Microsoft Corporation                                   */
648 /*                                                                        */
649 /*  DESCRIPTION                                                           */
650 /*                                                                        */
651 /*    This function checks for events indicating BSD TCP socket tasks are */
652 /*    waiting to  be performed.                                           */
653 /*                                                                        */
654 /*  INPUT                                                                 */
655 /*                                                                        */
656 /*    None                                                                */
657 /*                                                                        */
658 /*  OUTPUT                                                                */
659 /*                                                                        */
660 /*    None                                                                */
661 /*                                                                        */
662 /*  CALLS                                                                 */
663 /*                                                                        */
664 /*    tx_event_flags_get                   Check for registered events    */
665 /*    nx_bsd_timeout_process               Process BSD tasks              */
666 /*                                                                        */
667 /*  CALLED BY                                                             */
668 /*                                                                        */
669 /*    ThreadX                                                             */
670 /*                                                                        */
671 /*  RELEASE HISTORY                                                       */
672 /*                                                                        */
673 /*    DATE              NAME                      DESCRIPTION             */
674 /*                                                                        */
675 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
676 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
677 /*                                            resulting in version 6.1    */
678 /*                                                                        */
679 /**************************************************************************/
680 
681 #ifndef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
nx_bsd_thread_entry(ULONG info)682 VOID nx_bsd_thread_entry(ULONG info)
683 {
684     NX_PARAMETER_NOT_USED(info);
685 
686     while(1)
687     {
688 
689         /* Wait for timeout. */
690         tx_thread_sleep(NX_BSD_TIMER_RATE);
691 
692         /* Timeout process. */
693         nx_bsd_timeout_process();
694     }
695 }
696 #endif
697 
698 /**************************************************************************/
699 /*                                                                        */
700 /*  FUNCTION                                               RELEASE        */
701 /*                                                                        */
702 /*    socket                                              PORTABLE C      */
703 /*                                                           6.3.0        */
704 /*  AUTHOR                                                                */
705 /*                                                                        */
706 /*    Yuxin Zhou, Microsoft Corporation                                   */
707 /*                                                                        */
708 /*  DESCRIPTION                                                           */
709 /*                                                                        */
710 /*    Creates a TCP or UDP socket, which may then be used as an end point */
711 /*    of communication for sending and receiving data using the specified */
712 /*    protocol.                                                           */
713 /*                                                                        */
714 /*  INPUT                                                                 */
715 /*                                                                        */
716 /*    protocolFamily                        Protocol family e.g AF_INET   */
717 /*    type                                  Type of the socket TCP or UDP */
718 /*    protocol                              Socket protocol               */
719 /*                                                                        */
720 /*  OUTPUT                                                                */
721 /*                                                                        */
722 /*    socket descriptor                     On success                    */
723 /*    NX_SOC_ERROR (-1)                     On failure                    */
724 /*                                                                        */
725 /*  CALLS                                                                 */
726 /*                                                                        */
727 /*    memset                                Clears memory                 */
728 /*    nx_tcp_socket_create                  Create TCP BSD Socket         */
729 /*    nx_udp_socket_create                  Create UDP BSD Socket         */
730 /*    nx_tcp_socket_receive_notify          TCP receive notify function   */
731 /*    nx_udp_socket_receive_notify          UDP receive notify function   */
732 /*    tx_block_allocate                     Allocate socket memory        */
733 /*    tx_block_release                      Release socket memory         */
734 /*    tx_mutex_get                          Get protection                */
735 /*    tx_mutex_put                          Release protection            */
736 /*                                                                        */
737 /*  CALLED BY                                                             */
738 /*                                                                        */
739 /*    Application Code                                                    */
740 /*                                                                        */
741 /*  RELEASE HISTORY                                                       */
742 /*                                                                        */
743 /*    DATE              NAME                      DESCRIPTION             */
744 /*                                                                        */
745 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
746 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
747 /*                                            resulting in version 6.1    */
748 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
749 /*                                            used new API/structs naming,*/
750 /*                                            resulting in version 6.3.0  */
751 /*                                                                        */
752 /**************************************************************************/
nx_bsd_socket(INT protocolFamily,INT type,INT protocol)753 INT  nx_bsd_socket(INT protocolFamily, INT type, INT protocol)
754 {
755 
756 INT             i;
757 UINT            status;
758 NX_TCP_SOCKET   *tcp_socket_ptr;
759 NX_UDP_SOCKET   *udp_socket_ptr;
760 VOID            *socket_memory = NX_NULL;
761 NX_BSD_SOCKET   *bsd_socket_ptr;
762 
763 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
764 UINT            index;
765 #else
766 
767     NX_PARAMETER_NOT_USED(protocol);
768 #endif
769 
770     /* Check for a supported protocol family.  */
771 #ifndef NX_DISABLE_IPV4
772     if (protocolFamily == AF_INET)
773     {
774     }
775     else
776 #endif /* NX_DISABLE_IPV4 */
777 #ifdef FEATURE_NX_IPV6
778     if (protocolFamily == AF_INET6)
779     {
780     }
781     else
782 #endif /* FEATURE_NX_IPV6 */
783 #if defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)
784     if (protocolFamily == AF_PACKET)
785     {
786     }
787     else
788 #endif /* defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT) */
789     {
790 
791         /* Set the socket error. */
792         nx_bsd_set_errno(EAFNOSUPPORT);
793 
794         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
795         return(NX_SOC_ERROR);
796     }
797 
798     /* Check for a supported socket type.   */
799 #if defined(NX_ENABLE_IP_RAW_PACKET_FILTER) || defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT)
800     if ((type != SOCK_STREAM) && (type != SOCK_DGRAM) && (type != SOCK_RAW))
801 #else
802     if ((type != SOCK_STREAM) && (type != SOCK_DGRAM))
803 #endif
804     {
805 
806         /* Set the socket error. */
807         nx_bsd_set_errno(EPROTOTYPE);
808 
809         /* Invalid type.  */
810         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
811         return(NX_SOC_ERROR);
812     }
813 
814 #if defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)
815     /* An extra check when BSD RAW Packet type is enabled:
816        Only RAW_SOCKET type is supported in AF_PACKET family. */
817     if((protocolFamily == AF_PACKET) && (type != SOCK_RAW))
818     {
819         /* Set the socket error. */
820         nx_bsd_set_errno(EPROTOTYPE);
821 
822         /* Invalid type.  */
823         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
824         return(NX_SOC_ERROR);
825     }
826 #endif /* defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT) */
827 
828 
829     /* Obtain the BSD protection socket.  */
830     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
831 
832     /* Check the status.  */
833     if (status)
834     {
835 
836         /* Set the socket error. */
837         nx_bsd_set_errno(EACCES);
838 
839         /* Error getting the protection mutex.  */
840         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
841         return(NX_SOC_ERROR);
842     }
843 
844     /* Check whether IP fast timer is created or not. */
845     if ((nx_bsd_ip_fast_periodic_timer_entry == NX_NULL) ||
846         (nx_bsd_default_ip -> nx_ip_fast_periodic_timer.tx_timer_internal.tx_timer_internal_timeout_function != _nx_bsd_fast_periodic_timer_entry))
847     {
848 
849         /* BSD socket requires a fast periodic timer to calculate wait option in recv() function. */
850         /* Create IP fast periodic timer. */
851         _nx_ip_fast_periodic_timer_create(nx_bsd_default_ip);
852 
853         /* Replace timer expiration function entry. */
854         nx_bsd_ip_fast_periodic_timer_entry = nx_bsd_default_ip -> nx_ip_fast_periodic_timer.tx_timer_internal.tx_timer_internal_timeout_function;
855         nx_bsd_default_ip -> nx_ip_fast_periodic_timer.tx_timer_internal.tx_timer_internal_timeout_function = _nx_bsd_fast_periodic_timer_entry;
856     }
857 
858     /* Now find a free slot in the BSD socket array.  */
859     for (i = 0; i < NX_BSD_MAX_SOCKETS; i++)
860     {
861 
862         /* See if this entry is available.  Check the in use flag. */
863         if (!(nx_bsd_socket_array[nx_bsd_socket_array_index].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
864         {
865 
866             /* Yes, Ok to use this socket. */
867 
868             /* Clear the entire structure.  */
869             memset((VOID*) &nx_bsd_socket_array[nx_bsd_socket_array_index], 0, sizeof(NX_BSD_SOCKET));
870             nx_bsd_socket_array[nx_bsd_socket_array_index].nx_bsd_socket_id = (INT)nx_bsd_socket_array_index;
871 
872             /* Mark this socket as in-use.  */
873             nx_bsd_socket_array[nx_bsd_socket_array_index].nx_bsd_socket_status_flags |=  NX_BSD_SOCKET_IN_USE;
874 
875             /* Get out of the loop.  */
876             break;
877         }
878         else
879         {
880 
881             /* Try the next socket.  */
882             nx_bsd_socket_array_index++;
883 
884             /* Check if we need to wrap around to the start of the socket table.  */
885             if (nx_bsd_socket_array_index >= NX_BSD_MAX_SOCKETS)
886             {
887 
888                 /* Reset the index to 0.  */
889                 nx_bsd_socket_array_index =  0;
890             }
891         }
892     }
893 
894     /* Check if a free socket was found.  */
895     if (i >= NX_BSD_MAX_SOCKETS)
896     {
897 
898         /* No, set the error status and return. */
899 
900         /* Set the socket error. */
901         nx_bsd_set_errno(ENFILE);
902 
903         /* Release the mutex.  */
904         tx_mutex_put(nx_bsd_protection_ptr);
905 
906         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
907         return(NX_SOC_ERROR);
908     }
909 
910     /* Mark the location of the free socket. */
911     i = (INT)nx_bsd_socket_array_index;
912 
913     /* Update the socket index to the next entry.  */
914     nx_bsd_socket_array_index++;
915 
916     /* Check if we need to wrap around to the start of the table.  */
917     if (nx_bsd_socket_array_index >= NX_BSD_MAX_SOCKETS)
918     {
919 
920         /* Reset the index to 0.  */
921         nx_bsd_socket_array_index =  0;
922     }
923 
924     /* Set up a pointer to the BSD socket to use. */
925     bsd_socket_ptr =  &nx_bsd_socket_array[i];
926 
927     /* For TCP or UDP sockets we need to allocate memory to create the NetX Duo socket
928        (not necessary for raw socket). */
929 
930     if ((type == SOCK_STREAM) || (type == SOCK_DGRAM))
931     {
932 
933         /* Allocate a socket from the block pool.  */
934         status =  tx_block_allocate(&nx_bsd_socket_block_pool, &socket_memory, NX_BSD_TIMEOUT);
935 
936         /* Check for error status.  */
937         if (status != TX_SUCCESS)
938         {
939 
940             /* Set the socket error. */
941             nx_bsd_set_errno(ENOMEM);
942 
943             /* Clear the allocated internal BSD socket.  */
944             bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_IN_USE);
945 
946             /* Release the mutex.  */
947             tx_mutex_put(nx_bsd_protection_ptr);
948 
949             /* Error getting NetX socket memory.  */
950             NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
951             return(NX_SOC_ERROR);
952         }
953 
954         /* Clear the socket memory.  */
955         memset((VOID*) socket_memory, 0, sizeof(NX_TCP_SOCKET));
956 
957     }
958 
959     /* Is this a stream socket e.g. TCP?  */
960     if (type == SOCK_STREAM)
961     {
962         bsd_socket_ptr -> nx_bsd_socket_protocol = NX_PROTOCOL_TCP;
963 
964         /* Mark the master/secondary socket id as invalid. */
965         (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id = NX_BSD_MAX_SOCKETS;
966         (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = NX_BSD_MAX_SOCKETS;
967 
968         /* Yes, allocate memory for a TCP socket.  */
969         tcp_socket_ptr =  (NX_TCP_SOCKET *) socket_memory;
970 
971         /* Create a NetX TCP socket. */
972         /* Note that the nx_bsd_tcp_socket_disconnect_notify is invoked when an
973            established connection is disconnected.
974            The disconnect_complete_notify is called for all types of disconnect,
975            including the ones covered by tcp_socket_disconnect_notify. */
976 
977         status =  nx_tcp_socket_create(nx_bsd_default_ip, tcp_socket_ptr, "NetX BSD TCP Socket",
978                                        NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, NX_BSD_TCP_WINDOW, NX_NULL,
979                                        nx_bsd_tcp_socket_disconnect_notify);
980 
981         /* Check for a successful status.  */
982         if (status == NX_SUCCESS)
983         {
984 
985             /* Register a receive notify callback.  */
986             status =  nx_tcp_socket_receive_notify(tcp_socket_ptr, nx_bsd_tcp_receive_notify);
987 
988             /* Check for invalid input. */
989             if (status != NX_SUCCESS)
990             {
991 
992                 /* Set the socket error if extended socket options enabled. */
993                 nx_bsd_set_errno(EINVAL);
994 
995                 /* Release the allocated socket memory block.  */
996                 tx_block_release(socket_memory);
997 
998                 /* Release the mutex.  */
999                 tx_mutex_put(nx_bsd_protection_ptr);
1000 
1001                 /* Error getting NetX socket memory.  */
1002                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1003                 return(NX_SOC_ERROR);
1004             }
1005 
1006 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
1007 
1008             /* Set the SYN received notify function */
1009             tcp_socket_ptr -> nx_tcp_socket_syn_received_notify = nx_bsd_tcp_syn_received_notify;
1010 #endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */
1011 
1012 #ifdef NX_ENABLE_TCP_KEEPALIVE
1013             /* Set the keep alive feature to disabled. */
1014             tcp_socket_ptr -> nx_tcp_socket_keepalive_enabled = NX_FALSE;
1015 #endif /* NX_ENABLE_TCP_KEEPALIVE */
1016 
1017             /* Set the socket reuse feature to enabled. This is the default NetX socket behavior. */
1018             bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR;
1019 
1020 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
1021             /* Register an establish notify callback for the specified server socket with NetX.  */
1022             nx_tcp_socket_establish_notify(tcp_socket_ptr, nx_bsd_tcp_establish_notify);
1023 
1024             /* Register a disconnect complete notify callback for the specified server socket with NetX.  */
1025             /* The callback function is the same as the one used for TCP disconnect callback. */
1026             status += nx_tcp_socket_disconnect_complete_notify(tcp_socket_ptr, nx_bsd_tcp_socket_disconnect_notify);
1027 #endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */
1028 
1029             /* Return successful completion.  */
1030 
1031             /* Save the TCP pointer in the appropriate place.  */
1032             bsd_socket_ptr -> nx_bsd_socket_tcp_socket =  tcp_socket_ptr;
1033 
1034             /* Set up pointer in the NetX socket back to the BSD socket.   */
1035             tcp_socket_ptr -> nx_tcp_socket_reserved_ptr =  (VOID *) i;
1036 
1037 
1038         }
1039     }
1040     else if (type == SOCK_DGRAM)
1041     {
1042 
1043         bsd_socket_ptr -> nx_bsd_socket_protocol = NX_PROTOCOL_UDP;
1044 
1045         /* Make a double circular list. */
1046         bsd_socket_ptr -> nx_bsd_socket_next = bsd_socket_ptr;
1047         bsd_socket_ptr -> nx_bsd_socket_previous = bsd_socket_ptr;
1048 
1049         /* Allocate memory for a UDP socket.  */
1050         udp_socket_ptr =  (NX_UDP_SOCKET *) socket_memory;
1051 
1052         /* Create a NetX UDP socket */
1053         status =  nx_udp_socket_create(nx_bsd_default_ip, udp_socket_ptr, "NetX BSD UDP Socket",
1054                                        NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE,
1055                                        (nx_bsd_default_packet_pool -> nx_packet_pool_total)/8+1);
1056 
1057         /* Check for successful result. */
1058         if (status == NX_SUCCESS)
1059         {
1060 
1061             /* Register a receive notify callback.  */
1062             status = nx_udp_socket_receive_notify(udp_socket_ptr, nx_bsd_udp_receive_notify);
1063 
1064             /* Check for errors.  */
1065             if (status != NX_SUCCESS)
1066             {
1067 
1068                 /* Release the allocated socket memory block.  */
1069                 tx_block_release(socket_memory);
1070 
1071                 /* Release the mutex.  */
1072                 tx_mutex_put(nx_bsd_protection_ptr);
1073 
1074                 /* Set the socket error if extended socket options enabled. */
1075                 nx_bsd_set_errno(EINVAL);
1076 
1077                 /* Error getting NetX socket memory.  */
1078                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1079                 return(NX_SOC_ERROR);
1080             }
1081 
1082             /* Save the UDP pointer in the BSD socket.  */
1083             bsd_socket_ptr -> nx_bsd_socket_udp_socket =  udp_socket_ptr;
1084 
1085             /* Set the reserved UDP socket pointer back to the BSD socket.  */
1086             udp_socket_ptr -> nx_udp_socket_reserved_ptr =  (VOID *) (i + 0x00010000);
1087         }
1088     }
1089 #if defined(NX_ENABLE_IP_RAW_PACKET_FILTER) || defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT)
1090     else if (type == SOCK_RAW)
1091     {
1092 
1093 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
1094         /* Check if raw sockets are enabled in NetX Duo. */
1095         if (((protocolFamily == AF_INET) ||
1096              (protocolFamily == AF_INET6)) &&
1097              (nx_bsd_default_ip -> nx_ip_raw_ip_processing == NX_NULL))
1098         {
1099             /* No, Enable raw socket handling in NetX Duo. */
1100             status = nx_ip_raw_packet_enable(nx_bsd_default_ip);
1101 
1102             if (status != NX_SUCCESS)
1103             {
1104 
1105                 /* Release the mutex.  */
1106                 tx_mutex_put(nx_bsd_protection_ptr);
1107 
1108                 nx_bsd_set_errno(EPROTONOSUPPORT);
1109 
1110                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1111                 return NX_SOC_ERROR;
1112             }
1113         }
1114 
1115         /* Check if we set the packet filter already. */
1116          if (((protocolFamily == AF_INET) ||
1117              (protocolFamily == AF_INET6)) &&
1118              (nx_bsd_default_ip -> nx_ip_raw_packet_filter == NX_NULL))
1119         {
1120 
1121             /*  We have not. Do so now. Set the raw packet filter to the IP instance. */
1122             status = nx_ip_raw_packet_filter_set(nx_bsd_default_ip, nx_bsd_raw_packet_filter);
1123 
1124             /* Has a raw packet filter been successfully set? */
1125             if (status != NX_SUCCESS)
1126             {
1127 
1128                 /* Release the mutex.  */
1129                 tx_mutex_put(nx_bsd_protection_ptr);
1130 
1131                 nx_bsd_set_errno(EPROTONOSUPPORT);
1132 
1133                 /* No, return error status. */
1134                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1135                 return NX_SOC_ERROR;
1136             }
1137         }
1138 
1139         /*  For IPv6 raw socket, by default the header is not included in the received packet. */
1140         if(protocolFamily == AF_INET6)
1141         {
1142             bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_RX_NO_HDR;
1143         }
1144 
1145         /* Set the raw socket protocol to the BSD raw socket. */
1146         bsd_socket_ptr -> nx_bsd_socket_protocol = (USHORT)protocol;
1147         bsd_socket_ptr -> nx_bsd_socket_option_flags |=  NX_BSD_SOCKET_ENABLE_RAW_SOCKET;
1148 
1149         /* Calculate the hash index in the raw socket protocol table. */
1150         index = (UINT) ((protocol + (protocol >> 8)) & NX_BSD_SOCKET_RAW_PROTOCOL_TABLE_MASK);
1151 
1152         /* Determine if the list is NULL. */
1153         if(nx_bsd_socket_raw_protocol_table[index])
1154         {
1155             /* There are already sockets on the list... just add this one to the end. */
1156             bsd_socket_ptr -> nx_bsd_socket_next = nx_bsd_socket_raw_protocol_table[index];
1157             bsd_socket_ptr -> nx_bsd_socket_previous = (nx_bsd_socket_raw_protocol_table[index]) -> nx_bsd_socket_previous;
1158             ((nx_bsd_socket_raw_protocol_table[index]) -> nx_bsd_socket_previous) -> nx_bsd_socket_next = bsd_socket_ptr;
1159             (nx_bsd_socket_raw_protocol_table[index]) -> nx_bsd_socket_previous = bsd_socket_ptr;
1160         }
1161         else
1162         {
1163             /* Nothing is on the list. Add this one to an empty list. */
1164             bsd_socket_ptr -> nx_bsd_socket_next = bsd_socket_ptr;
1165             bsd_socket_ptr -> nx_bsd_socket_previous = bsd_socket_ptr;
1166             nx_bsd_socket_raw_protocol_table[index] = bsd_socket_ptr;
1167         }
1168 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
1169 
1170         if(protocolFamily == AF_PACKET)
1171         {
1172 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
1173             bsd_socket_ptr -> nx_bsd_socket_create_id = nx_bsd_socket_create_id;
1174             nx_bsd_socket_create_id++;
1175 #elif defined(NX_BSD_RAW_SUPPORT)
1176             bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
1177             bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
1178 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
1179         }
1180 
1181     }
1182 #endif  /* NX_ENABLE_IP_RAW_PACKET_FILTER || NX_BSD_RAW_PPPOE_SUPPORT || NX_BSD_RAW_SUPPORT */
1183 
1184     else
1185     {
1186         /* Not a supported socket type.   */
1187        nx_bsd_set_errno(EOPNOTSUPP);
1188 
1189         /* Invalid type.  */
1190         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1191         return(NX_SOC_ERROR);
1192     }
1193 
1194     /* Set the protocol family: AF_INET or AF_INET6.   */
1195     bsd_socket_ptr -> nx_bsd_socket_family = (ULONG)protocolFamily;
1196 
1197     /* For UDP and RAW sockets, set the maximum receive queue depth. */
1198     if(bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
1199     {
1200 
1201         bsd_socket_ptr -> nx_bsd_socket_received_packet_count_max = NX_BSD_SOCKET_QUEUE_MAX;
1202     }
1203 
1204     /* Check for error creating the NetX Duo socket.  */
1205     if (status != NX_SUCCESS)
1206     {
1207 
1208         /* Release the BSD protection.  */
1209 
1210         /* Clear the BSD socket in use flag.  */
1211         bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_IN_USE);
1212 
1213         if ((type == SOCK_DGRAM) || (type == SOCK_STREAM))
1214         {
1215             /* Release the socket memory block allocated for TCP or UDP socket.  */
1216             tx_block_release(socket_memory);
1217         }
1218 
1219         /* Release the mutex.  */
1220         tx_mutex_put(nx_bsd_protection_ptr);
1221 
1222         /* Set the socket error if extended socket options enabled. */
1223         nx_bsd_set_errno(EINVAL);
1224 
1225         /* Error present, return error code.  */
1226         NX_BSD_ERROR(status, __LINE__);
1227         return(NX_SOC_ERROR);
1228     }
1229 
1230     /* Release the mutex.  */
1231     tx_mutex_put(nx_bsd_protection_ptr);
1232 
1233     /* Return success!  */
1234     return(i + NX_BSD_SOCKFD_START);
1235 }
1236 
1237 
1238 /**************************************************************************/
1239 /*                                                                        */
1240 /*  FUNCTION                                               RELEASE        */
1241 /*                                                                        */
1242 /*    connect                                             PORTABLE C      */
1243 /*                                                           6.3.0        */
1244 /*  AUTHOR                                                                */
1245 /*                                                                        */
1246 /*    Yuxin Zhou, Microsoft Corporation                                   */
1247 /*                                                                        */
1248 /*  DESCRIPTION                                                           */
1249 /*                                                                        */
1250 /*    Establishes a connection between a client socket and a remote server*/
1251 /*    socket associated with the remote address, if any. Upon returning   */
1252 /*    successfully, the given socket's local and remote IP address and    */
1253 /*    port information are filled in. If the socket was not previously    */
1254 /*    bound to a local port, one is assigned randomly.                    */
1255 /*                                                                        */
1256 /*    For TCP sockets, connect() completes with a connection handshake is */
1257 /*    complete, or if an error occurs.   A TCP negotiation is performed   */
1258 /*    to open a connection and success implies the existence of a reliable*/
1259 /*    channel to that socket.                                             */
1260 /*                                                                        */
1261 /*    For UDP sockets, the connection is established simply by setting the*/
1262 /*    supplied destination (remote) IP address and port for the remote    */
1263 /*    host.                                                               */
1264 /*                                                                        */
1265 /*    For non blocking sockets, the function returns immediately if a     */
1266 /*    connection is not possible.  The socket thread error is set to      */
1267 /*    EINPROGRESS to distinguish from blocking sockets.                   */
1268 /*                                                                        */
1269 /*  INPUT                                                                 */
1270 /*                                                                        */
1271 /*     sockID                               Socket descriptor             */
1272 /*    *remoteAddress                        Remote address structure      */
1273 /*     addressLength                        Address structure length      */
1274 /*                                                                        */
1275 /*  OUTPUT                                                                */
1276 /*                                                                        */
1277 /*    NX_SOC_OK (0)                         If success                    */
1278 /*    NX_SOC_ERROR (-1)                     If failure or if called with  */
1279 /*                                            an UDP socket               */
1280 /*                                                                        */
1281 /*  CALLS                                                                 */
1282 /*                                                                        */
1283 /*    nx_ip_status_check                    Check to make sure link is up */
1284 /*    nx_tcp_client_socket_bind             Bind a TCP socket to a port   */
1285 /*    nxd_tcp_client_socket_connect         Connect to a TCP server       */
1286 /*    tx_mutex_get                          Get protection                */
1287 /*    tx_mutex_put                          Release protection            */
1288 /*    tx_thread_identify                    Get current thread pointer    */
1289 /*                                                                        */
1290 /*  CALLED BY                                                             */
1291 /*                                                                        */
1292 /*    Application Code                                                    */
1293 /*                                                                        */
1294 /*  RELEASE HISTORY                                                       */
1295 /*                                                                        */
1296 /*    DATE              NAME                      DESCRIPTION             */
1297 /*                                                                        */
1298 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1299 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1300 /*                                            resulting in version 6.1    */
1301 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
1302 /*                                            used new API/structs naming,*/
1303 /*                                            resulting in version 6.3.0  */
1304 /*                                                                        */
1305 /**************************************************************************/
nx_bsd_connect(INT sockID,struct nx_bsd_sockaddr * remoteAddress,INT addressLength)1306 INT  nx_bsd_connect(INT sockID, struct nx_bsd_sockaddr *remoteAddress, INT addressLength)
1307 {
1308 UINT                status;
1309 NX_TCP_SOCKET       *tcp_socket_ptr;
1310 NX_UDP_SOCKET       *udp_socket_ptr;
1311 NX_BSD_SOCKET       *bsd_socket_ptr;
1312 ULONG               timeout;
1313 ULONG               actual_status;
1314 
1315     /* Check for a valid socket ID.  */
1316     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
1317     {
1318 
1319         /* Set the socket error. */
1320         nx_bsd_set_errno(EBADF);
1321 
1322         /* Return an error. */
1323         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1324         return(NX_SOC_ERROR);
1325     }
1326 
1327     /* Adjust the sockID to index into the BSD socket table.  */
1328     sockID =  sockID - NX_BSD_SOCKFD_START;
1329 
1330     /* Ensure the IP instance has been initialized.  */
1331     status =  nx_ip_status_check(nx_bsd_default_ip, NX_IP_INITIALIZE_DONE, &actual_status, NX_BSD_TIMEOUT);
1332 
1333     /* Check the status.  */
1334     if (status != NX_SUCCESS)
1335     {
1336 
1337         /* Set the socket error. */
1338         nx_bsd_set_errno(EFAULT);
1339 
1340         /* Return an error. */
1341         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1342         return(NX_SOC_ERROR);
1343     }
1344 
1345     /* Set a pointer to the BSD socket.  */
1346     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
1347 
1348     /* Make sure the socket is valid. */
1349     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
1350     {
1351 
1352         /* Socket is no longer in use.   */
1353 
1354         /* Set the socket error if extended socket options enabled. */
1355         nx_bsd_set_errno(EBADF);
1356 
1357         /* Return an error.  */
1358         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1359         return(NX_SOC_ERROR);
1360     }
1361 
1362     /* Obtain the BSD protection.  */
1363     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
1364 
1365     /* Check the status.  */
1366     if (status != NX_SUCCESS)
1367     {
1368 
1369         /* Set the socket error if extended socket options enabled. */
1370         nx_bsd_set_errno(EACCES);
1371 
1372         /* Return an error. */
1373         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
1374         return(NX_SOC_ERROR);
1375     }
1376 
1377     /* Check whether supplied address structure and length is valid */
1378     if (remoteAddress == NX_NULL )
1379     {
1380 
1381         /* For UDP socket or RAW socket, a NULL remoteAddress dis-associate
1382            a remote address bound to the socket. */
1383         if (bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
1384         {
1385             memset(&bsd_socket_ptr -> nx_bsd_socket_peer_ip, 0, sizeof(NXD_ADDRESS));
1386             bsd_socket_ptr -> nx_bsd_socket_peer_port = 0;
1387 
1388             /* Clear the connect flag. */
1389             bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTED);
1390 
1391             /* All done.  Return. */
1392 
1393             /* Release the mutex.  */
1394             tx_mutex_put(nx_bsd_protection_ptr);
1395 
1396             return(NX_SOC_OK);
1397 
1398         }
1399         else
1400         {
1401             /* For TCP socket, each socket can only be connected once, and
1402                the remote address must be set correctly. */
1403 
1404             /* Release the mutex.  */
1405             tx_mutex_put(nx_bsd_protection_ptr);
1406             /* Set the socket error if extended socket options enabled. */
1407             nx_bsd_set_errno(EAFNOSUPPORT);
1408 
1409             /* Return an error. */
1410             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1411             return(NX_SOC_ERROR);
1412         }
1413     }
1414 
1415 
1416     /* Check if the remote address family matches the local BSD socket address family. */
1417     if((remoteAddress -> sa_family != bsd_socket_ptr -> nx_bsd_socket_family) ||
1418        ((remoteAddress -> sa_family == AF_INET) && (addressLength != sizeof(struct nx_bsd_sockaddr_in))) ||
1419        ((remoteAddress -> sa_family == AF_INET6) && (addressLength != sizeof(struct nx_bsd_sockaddr_in6))))
1420     {
1421 
1422         /* Mismatch! */
1423 
1424         /* Release the mutex.  */
1425         tx_mutex_put(nx_bsd_protection_ptr);
1426 
1427         /* Set the socket error if extended socket options enabled. */
1428         nx_bsd_set_errno(EAFNOSUPPORT);
1429 
1430         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1431         return(ERROR);
1432     }
1433 
1434 #ifndef NX_DISABLE_IPV4
1435     /* Check the socket family type.  */
1436     if(remoteAddress -> sa_family == AF_INET)
1437     {
1438 
1439         /* This is an IPv4 socket type. */
1440 
1441         /* Set the UDP remote host IP address and port for the UDP 'connection'; for NetX Duo
1442            set the IP version. */
1443         /* NetX API expects multi byte values to be in host byte order.
1444            Therefore ntohl/s are used to make the conversion. */
1445         bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_version = NX_IP_VERSION_V4;
1446         bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v4 =  htonl(((struct nx_bsd_sockaddr_in *) remoteAddress ) -> sin_addr.s_addr);
1447         bsd_socket_ptr -> nx_bsd_socket_peer_port =  htons(((struct nx_bsd_sockaddr_in *) remoteAddress ) -> sin_port);
1448     }
1449     else
1450 #endif /* NX_DISABLE_IPV4 */
1451 
1452 #ifdef FEATURE_NX_IPV6
1453     if(remoteAddress -> sa_family == AF_INET6)
1454     {
1455 
1456         /* This is an IPv6 enabled socket family type). */
1457         bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_version = NX_IP_VERSION_V6;
1458         /* NetX API expects multi byte values to be in host byte order.
1459            Therefore ntohl/s are used to make the conversion. */
1460         /* Get remote address and port. */
1461         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]);
1462         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]);
1463         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]);
1464         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]);
1465 
1466         bsd_socket_ptr -> nx_bsd_socket_peer_port =  htons(((struct nx_bsd_sockaddr_in6 *) remoteAddress ) -> sin6_port);
1467 
1468     }
1469     else
1470 #endif /* FEATURE_NX_IPV6 */
1471     {
1472 
1473         /* Address family not supported. */
1474 
1475         /* Release the mutex.  */
1476         tx_mutex_put(nx_bsd_protection_ptr);
1477 
1478         /* Set the socket error if extended socket options enabled. */
1479         nx_bsd_set_errno(EAFNOSUPPORT);
1480 
1481         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1482         return(ERROR);
1483     }
1484 
1485 
1486     /* Handle the UDP 'connection' request.  */
1487     if (bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
1488     {
1489 
1490         udp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_udp_socket;
1491 
1492         /* Check to see if the UDP socket is already bound.  */
1493         if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND))
1494         {
1495 
1496             /* Not yet, bind to a randomly selected available free port.  */
1497             status =  nx_udp_socket_bind(udp_socket_ptr, NX_ANY_PORT, NX_BSD_TIMEOUT);
1498 
1499             /* Check for error.  */
1500             if (status != NX_SUCCESS)
1501             {
1502 
1503                 /* Release the mutex.  */
1504                 tx_mutex_put(nx_bsd_protection_ptr);
1505 
1506                 /* Set the socket error based on NetX error status return. */
1507                 nx_bsd_set_error_code(bsd_socket_ptr, status);
1508 
1509                 /* Return an error.  */
1510                 NX_BSD_ERROR(ERROR, __LINE__);
1511                 return(ERROR);
1512             }
1513 
1514             /* Bind is successful. Obtain the port number. */
1515             bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)udp_socket_ptr -> nx_udp_socket_port;
1516             bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
1517             bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
1518             bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
1519        }
1520 
1521        /* Mark the socket as connected. */
1522        bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
1523 
1524        /* Release the mutex.  */
1525        tx_mutex_put(nx_bsd_protection_ptr);
1526 
1527        /* Return successful status.  */
1528        return(NX_SOC_OK);
1529     }
1530     else if (bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
1531     {
1532 
1533         /* This is not UDP or TCP socket.  So it must be raw socket. */
1534         /* We treat raw socket the same as UDP socket.  For connec, raw socket
1535            associates the remote address as its default destination address when
1536            transmit, and also limit the reception of data from that remote address. */
1537 
1538         /* Mark the socket as connected. */
1539         bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
1540 
1541         /* Release the mutex.  */
1542         tx_mutex_put(nx_bsd_protection_ptr);
1543 
1544         /* Return successful status.  */
1545         return(NX_SOC_OK);
1546     }
1547 
1548     /* This is a TCP BSD socket. */
1549 
1550     /* If the socket is already connected. */
1551     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
1552     {
1553 
1554         /* If INPROGRESS is set, clear the INPROGRESS flag and return OK.
1555            The INPROGRESS flag needs to be cleared so the next connect call would return EISCONN */
1556         if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_INPROGRESS)
1557         {
1558 
1559             bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
1560 
1561             /* Release the protection mutex.  */
1562             tx_mutex_put(nx_bsd_protection_ptr);
1563 
1564             return(NX_SOC_OK);
1565         }
1566 
1567         /* Already connected. */
1568         nx_bsd_set_errno(EISCONN);
1569 
1570         tx_mutex_put(nx_bsd_protection_ptr);
1571 
1572         /* Return an error.  */
1573         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1574         return(NX_SOC_ERROR);
1575 
1576     }
1577 
1578     /* If the socket is marked as EINPROGRESS, return EALREADY. */
1579     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_INPROGRESS)
1580     {
1581 
1582 
1583         nx_bsd_set_errno(EALREADY);
1584 
1585         /* Release the protection mutex.  */
1586         tx_mutex_put(nx_bsd_protection_ptr);
1587 
1588         /* Return an error.  */
1589         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1590         return(NX_SOC_ERROR);
1591 
1592     }
1593     /* If the socket has an error */
1594     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
1595     {
1596         INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
1597 
1598         /* Now clear the error code. */
1599         bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
1600 
1601         /* Clear the error flag.  The application is expected to close the socket at this point.*/
1602         bsd_socket_ptr -> nx_bsd_socket_status_flags =
1603             bsd_socket_ptr -> nx_bsd_socket_status_flags & ((ULONG)(~NX_BSD_SOCKET_ERROR));
1604 
1605         nx_bsd_set_errno(errcode);
1606 
1607         /* Release the protection mutex.  */
1608         tx_mutex_put(nx_bsd_protection_ptr);
1609 
1610         /* Return an error.  */
1611         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1612 
1613         /* At this point the error flag is cleared.  Application should
1614            detect and handle the error codition. This socket is still bound
1615            to the port (either the application called bind(), or a bind
1616            operation was executed as part of the connect call) is able to
1617            handle another "connect" call, or be closed. */
1618         return(NX_SOC_ERROR);
1619     }
1620 
1621     /* Set a NetX tcp pointer.  */
1622     tcp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
1623 
1624     /* Mark this as a client TCP socket. */
1625     bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CLIENT;
1626 
1627     /* Is the TCP socket already bound?  */
1628     if (tcp_socket_ptr -> nx_tcp_socket_port == 0)
1629     {
1630 
1631         /* Not yet; bind to a randomly selected available free port. */
1632 
1633         /* Call NetX TCP bind service with NX_NO_WAIT.  */
1634         status =  nx_tcp_client_socket_bind(tcp_socket_ptr, NX_ANY_PORT, NX_NO_WAIT);
1635 
1636         /* Check for error.  */
1637         if (status != NX_SUCCESS)
1638         {
1639 
1640             /* Clear the client socket flag.  */
1641             bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CLIENT);
1642 
1643             /* Set the socket error depending on NetX error status return. */
1644             nx_bsd_set_error_code(bsd_socket_ptr, status);
1645 
1646             /* Return an error.  */
1647             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1648 
1649             /* Release the protection mutex.  */
1650             tx_mutex_put(nx_bsd_protection_ptr);
1651 
1652             return(NX_SOC_ERROR);
1653         }
1654 
1655         /* Mark the socket as bound. */
1656         bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
1657         bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)tcp_socket_ptr -> nx_tcp_socket_port;
1658         bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
1659         bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
1660 
1661     }
1662 
1663     /* Mark this BSD socket as busy.  */
1664     bsd_socket_ptr -> nx_bsd_socket_busy = tx_thread_identify();
1665 
1666     /* Attempt to make the connection.  If the socket is non-blocking,
1667        set the timeout to 0.  Otherwise, use wait-forever */
1668     if (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING)
1669     {
1670 
1671         /* Yes, the socket is enabled for non blocking. Do not wait.  */
1672         timeout = 0;
1673     }
1674     else
1675     {
1676         /* This call may be blocked internally. Release the mutex
1677            so the nx_tcp_client_socket_connect can suspend waiting
1678            for a connection. */
1679         timeout = NX_WAIT_FOREVER;
1680         tx_mutex_put(nx_bsd_protection_ptr);
1681     }
1682 
1683     /* Make the connection. */
1684     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);
1685     if(timeout != 0)
1686     {
1687         /* The mutex was released prior to the call.  Accquire the mutex
1688            again. */
1689         tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
1690 
1691         /* Verify that the socket is still valid. */
1692         if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
1693         {
1694             /* The socket is no longer in use. */
1695 
1696             /* Set the socket error code. */
1697             nx_bsd_set_errno(EBADF);
1698 
1699             /* Release the protection mutex.  */
1700             tx_mutex_put(nx_bsd_protection_ptr);
1701 
1702             /* Return error code.  */
1703             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1704             return(NX_SOC_ERROR);
1705         }
1706 
1707         if (status == NX_NOT_CONNECTED)
1708         {
1709 
1710             if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR) ||
1711                 (tcp_socket_ptr -> nx_tcp_socket_timeout_retries >= tcp_socket_ptr -> nx_tcp_socket_timeout_max_retries))
1712             {
1713 
1714                 /* Connect timeouts since NX_BSD_SOCKET_ERROR is not set or
1715                  * number of timeout retry has been exceeded. */
1716                 status = NX_WAIT_ABORTED;
1717             }
1718 
1719             bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
1720             bsd_socket_ptr -> nx_bsd_socket_error_code = ENOTCONN;
1721         }
1722     }
1723 
1724     /* Check for an error.  */
1725     if (status != NX_SUCCESS)
1726     {
1727 
1728         /* Set the socket error depending on NetX error status return. */
1729         nx_bsd_set_error_code(bsd_socket_ptr, status);
1730 
1731 
1732         /* Make sure this thread is still the owner.  */
1733         if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
1734         {
1735 
1736             /* Clear the busy flag.  */
1737             bsd_socket_ptr -> nx_bsd_socket_busy =  TX_NULL;
1738         }
1739 
1740         /* Release the protection mutex.  */
1741         tx_mutex_put(nx_bsd_protection_ptr);
1742 
1743         /* Return error code.  */
1744         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1745         return(NX_SOC_ERROR);
1746     }
1747 
1748     /* At this point NX TCP connect service returns success, so the connection is established. */
1749 
1750     /* Mark the socket as connected. */
1751     bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
1752 
1753     /* Clear the CONNECTION_INPROGRESS flag. */
1754     bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
1755 
1756     /* Mark the connection_request flag */
1757     bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_REQUEST;
1758 
1759     /* Make sure thread making the bind call is the current thread.  */
1760     if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
1761     {
1762 
1763         /* OK to clear the busy flag.  */
1764         bsd_socket_ptr -> nx_bsd_socket_busy =  TX_NULL;
1765 
1766         /* Check if the connect call was successful.  */
1767         if (status == NX_SUCCESS)
1768         {
1769 
1770             /* It was. Release the protection mutex.  */
1771             tx_mutex_put(nx_bsd_protection_ptr);
1772 
1773             /* Successful connection. Return the success status.  */
1774             return(NX_SOC_OK);
1775         }
1776     }
1777 
1778     /* Error condition: the thread that was executing connect is not the current thread. */
1779 
1780     /* Clear the connected flags and peer infomration .*/
1781     bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTED);
1782     bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_REQUEST);
1783     memset(&bsd_socket_ptr -> nx_bsd_socket_source_ip_address, 0, sizeof(NXD_ADDRESS));
1784     bsd_socket_ptr -> nx_bsd_socket_source_port = 0;
1785 
1786     /* Release the protection mutex.  */
1787     tx_mutex_put(nx_bsd_protection_ptr);
1788 
1789     /* Set the socket error. */
1790     nx_bsd_set_errno(EINTR);
1791 
1792     /* Return an error.  */
1793     NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1794     return(NX_SOC_ERROR);
1795 }
1796 
1797 /**************************************************************************/
1798 /*                                                                        */
1799 /*  FUNCTION                                               RELEASE        */
1800 /*                                                                        */
1801 /*    bind                                                PORTABLE C      */
1802 /*                                                           6.3.0        */
1803 /*  AUTHOR                                                                */
1804 /*                                                                        */
1805 /*    Yuxin Zhou, Microsoft Corporation                                   */
1806 /*                                                                        */
1807 /*  DESCRIPTION                                                           */
1808 /*                                                                        */
1809 /*    This function binds a socket to a local port. The port in the struct*/
1810 /*    in the struct sockaddr structure may be wildcarded, in which case   */
1811 /*    NetX will select a port number.                                     */
1812 /*                                                                        */
1813 /*    To wildcard the port, set the sin_port field of the address to 0.   */
1814 /*                                                                        */
1815 /*  INPUT                                                                 */
1816 /*                                                                        */
1817 /*    sockID                                Socket descriptor             */
1818 /*    *localAddress                         Populated socket address      */
1819 /*    addressLength                         Socket address length         */
1820 /*                                                                        */
1821 /*  OUTPUT                                                                */
1822 /*                                                                        */
1823 /*    NX_SOC_OK (0)                         If success                    */
1824 /*    NX_SOC_ERROR (-1)                     If failure                    */
1825 /*                                                                        */
1826 /*  CALLS                                                                 */
1827 /*                                                                        */
1828 /*    nx_ip_status_check                    Check for link up             */
1829 /*    nx_tcp_client_socket_bind             Binds a TCP socket to a port  */
1830 /*    nx_udp_client_socket_bind             Binds a UDP socket to a port  */
1831 /*    tx_mutex_get                          Get protection                */
1832 /*    tx_mutex_put                          Release protection            */
1833 /*    tx_thread_identify                    Gets the current thread       */
1834 /*                                                                        */
1835 /*  CALLED BY                                                             */
1836 /*                                                                        */
1837 /*    Application Code                                                    */
1838 /*                                                                        */
1839 /*  RELEASE HISTORY                                                       */
1840 /*                                                                        */
1841 /*    DATE              NAME                      DESCRIPTION             */
1842 /*                                                                        */
1843 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
1844 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
1845 /*                                            resulting in version 6.1    */
1846 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
1847 /*                                            used new API/structs naming,*/
1848 /*                                            resulting in version 6.3.0  */
1849 /*                                                                        */
1850 /**************************************************************************/
nx_bsd_bind(INT sockID,const struct nx_bsd_sockaddr * localAddress,INT addressLength)1851 INT  nx_bsd_bind(INT sockID, const struct nx_bsd_sockaddr *localAddress, INT addressLength)
1852 {
1853 
1854 INT                 local_port = 0;
1855 UINT                status;
1856 NX_TCP_SOCKET       *tcp_socket_ptr;
1857 NX_UDP_SOCKET       *udp_socket_ptr;
1858 NX_BSD_SOCKET       *bsd_socket_ptr;
1859 INT                 i;
1860 INT                 address_conflict;
1861 
1862 
1863     /* Check for invalid socket ID.  */
1864     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
1865     {
1866 
1867         /* Set the socket error. */
1868         nx_bsd_set_errno(EBADF);
1869 
1870         /* Error, invalid socket ID.  */
1871         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1872         return(NX_SOC_ERROR);
1873     }
1874 
1875     /* Check for a valid input local address and address length input buffer.  */
1876     if ((localAddress == NX_NULL ) || (addressLength == 0))
1877     {
1878 
1879         /* Set the socket error if extended socket options enabled. */
1880         nx_bsd_set_errno(EFAULT);
1881 
1882         /* Error, invalid local address. */
1883         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1884         return(NX_SOC_ERROR);
1885     }
1886 
1887     if (((localAddress -> sa_family == AF_INET) && (addressLength != sizeof(struct nx_bsd_sockaddr_in))) ||
1888         ((localAddress -> sa_family == AF_INET6) && (addressLength != sizeof(struct nx_bsd_sockaddr_in6))))
1889     {
1890         nx_bsd_set_errno(EAFNOSUPPORT);
1891 
1892         /* Return an error.  */
1893         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1894         return(NX_SOC_ERROR);
1895     }
1896 
1897     /* Normalize the socket ID.  */
1898     sockID =  sockID - NX_BSD_SOCKFD_START;
1899 
1900     /* Get the protection mutex.  */
1901     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
1902 
1903     /* Check the status.  */
1904     if (status != NX_SUCCESS)
1905     {
1906 
1907         /* Set the socket error if extended socket options enabled. */
1908         nx_bsd_set_errno(EACCES);
1909 
1910         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
1911         return(NX_SOC_ERROR);
1912     }
1913 
1914     /* Set up a pointer to the BSD socket.  */
1915     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
1916 
1917     /* See if the socket is still in use.  */
1918     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
1919     {
1920 
1921         /* Socket is no longer in use.   */
1922 
1923         /* Release the protection mutex.  */
1924         tx_mutex_put(nx_bsd_protection_ptr);
1925 
1926         /* Set the socket error if extended socket options enabled. */
1927         nx_bsd_set_errno(EBADF);
1928 
1929         /* Return an error.  */
1930         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1931         return(NX_SOC_ERROR);
1932     }
1933 
1934     /* If the socket has an error */
1935     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
1936     {
1937 
1938         /* Clear the error flag.  The application is expected to close the socket at this point.*/
1939         bsd_socket_ptr -> nx_bsd_socket_status_flags =
1940             bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
1941 
1942         nx_bsd_set_errno(bsd_socket_ptr -> nx_bsd_socket_error_code);
1943 
1944         /* Clear the error code. */
1945         bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
1946 
1947         /* Release the protection mutex.  */
1948         tx_mutex_put(nx_bsd_protection_ptr);
1949 
1950         /* Return an error.  */
1951         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1952 
1953         /* At this point the error flag is cleared.  Application should
1954            detect and handle the error codition. This socket is still bound
1955            to the port (either the application called bind(), or a bind
1956            operation was executed as part of the connect call) is able to
1957            handle another "connect" call, or be closed. */
1958         return(NX_SOC_ERROR);
1959     }
1960 
1961     /* Check the address family. */
1962     if (bsd_socket_ptr -> nx_bsd_socket_family != localAddress -> sa_family)
1963     {
1964         nx_bsd_set_errno(EAFNOSUPPORT);
1965         /* Release the protection mutex.  */
1966         tx_mutex_put(nx_bsd_protection_ptr);
1967 
1968         /* Return an error.  */
1969         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1970         return(NX_SOC_ERROR);
1971     }
1972 
1973     /* Check to see if the socket is already bound.  */
1974     if (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND)
1975     {
1976 
1977         /* It is. */
1978 
1979         /* Set the socket error if extended socket options enabled. */
1980         nx_bsd_set_errno(EINVAL);
1981 
1982         /* Release the protection mutex.  */
1983         tx_mutex_put(nx_bsd_protection_ptr);
1984 
1985         /* Return an error.  */
1986         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1987         return(NX_SOC_ERROR);
1988     }
1989 
1990     /* Zero out the local bind info */
1991     bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = 0;
1992 
1993 #ifndef NX_DISABLE_IPV4
1994     if(localAddress -> sa_family == AF_INET)
1995     {
1996 
1997     ULONG local_addr;
1998     INT if_index;
1999 
2000         /* Pickup the local port.  */
2001         local_port = ntohs(((struct nx_bsd_sockaddr_in *) localAddress) -> sin_port);
2002 
2003         /* Pick up the local IP address */
2004         local_addr = ntohl(((struct nx_bsd_sockaddr_in*)localAddress) -> sin_addr.s_addr);
2005 
2006         if(local_addr == INADDR_ANY)
2007         {
2008 
2009             bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
2010             bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
2011         }
2012         else
2013         {
2014 
2015             for(if_index = 0; if_index < NX_MAX_IP_INTERFACES; if_index++)
2016             {
2017 
2018                 if((nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_valid) &&
2019                    (nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_ip_address == local_addr))
2020                 {
2021 
2022                     bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = (ULONG)(&nx_bsd_default_ip -> nx_ip_interface[if_index]);
2023                     bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = (UINT)if_index;
2024                     break;
2025                 }
2026             }
2027         }
2028     }
2029 #endif /* NX_DISABLE_IPV4 */
2030 #ifdef FEATURE_NX_IPV6
2031     if(localAddress -> sa_family == AF_INET6)
2032     {
2033 
2034     ULONG ipv6_addr[4];
2035     INT if_index;
2036 
2037         /* Pickup the local port.  */
2038         local_port = ntohs(((struct nx_bsd_sockaddr_in6 *) localAddress) -> sin6_port);
2039 
2040         ipv6_addr[0] = ntohl((((struct nx_bsd_sockaddr_in6*)localAddress)) -> sin6_addr._S6_un._S6_u32[0]);
2041         ipv6_addr[1] = ntohl((((struct nx_bsd_sockaddr_in6*)localAddress)) -> sin6_addr._S6_un._S6_u32[1]);
2042         ipv6_addr[2] = ntohl((((struct nx_bsd_sockaddr_in6*)localAddress)) -> sin6_addr._S6_un._S6_u32[2]);
2043         ipv6_addr[3] = ntohl((((struct nx_bsd_sockaddr_in6*)localAddress)) -> sin6_addr._S6_un._S6_u32[3]);
2044 
2045         if((ipv6_addr[0] | ipv6_addr[1] | ipv6_addr[2] | ipv6_addr[3]) == 0)
2046         {
2047 
2048             bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
2049             bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
2050         }
2051         else
2052         {
2053 
2054             for(if_index = 0; if_index < NX_MAX_IPV6_ADDRESSES; if_index++)
2055             {
2056 
2057                 if((nx_bsd_default_ip -> nx_ipv6_address[if_index].nxd_ipv6_address[0] == ipv6_addr[0]) &&
2058                    (nx_bsd_default_ip -> nx_ipv6_address[if_index].nxd_ipv6_address[1] == ipv6_addr[1]) &&
2059                    (nx_bsd_default_ip -> nx_ipv6_address[if_index].nxd_ipv6_address[2] == ipv6_addr[2]) &&
2060                    (nx_bsd_default_ip -> nx_ipv6_address[if_index].nxd_ipv6_address[3] == ipv6_addr[3]))
2061                 {
2062 
2063                     bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = (ULONG)(&nx_bsd_default_ip -> nx_ipv6_address[if_index]);
2064 
2065                     bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = (UINT)if_index;
2066                     break;
2067                 }
2068             }
2069         }
2070     }
2071 #endif
2072 #ifdef NX_BSD_RAW_SUPPORT
2073     if ((localAddress -> sa_family == AF_PACKET) && (addressLength == sizeof(struct nx_bsd_sockaddr_ll)))
2074     {
2075     UINT if_index;
2076 
2077         if_index = (UINT)(((struct nx_bsd_sockaddr_ll *)localAddress) -> sll_ifindex);
2078         bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = (ULONG)(&nx_bsd_default_ip -> nx_ip_interface[if_index]);
2079         bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = if_index;
2080     }
2081 #endif /* NX_BSD_RAW_SUPPORT */
2082 
2083     /* Check if the bind information is correctly set. */
2084     if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == 0)
2085     {
2086 
2087         /* Release the protection mutex.  */
2088         tx_mutex_put(nx_bsd_protection_ptr);
2089 
2090         /* Set the socket error if extended socket options enabled. */
2091         nx_bsd_set_errno(EADDRNOTAVAIL);
2092 
2093         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
2094         return(NX_SOC_ERROR);
2095     }
2096 
2097     /* At this point the local bind interface and port are known.
2098        If port number is specified, we need to go through the existing sockets
2099        and make sure there is no conflict. */
2100     address_conflict = 0;
2101 
2102     if(local_port)
2103     {
2104 
2105         for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
2106         {
2107 
2108             /* Skip its own entry. */
2109             if((i == sockID) ||
2110                /* Skip invalid entries. */
2111                (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE)) ||
2112                /* Skip the entries with different protocol ID */
2113                (nx_bsd_socket_array[i].nx_bsd_socket_protocol != bsd_socket_ptr -> nx_bsd_socket_protocol) ||
2114                /* Skip the unbound entries */
2115                (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND)))
2116             {
2117 
2118                 continue;
2119             }
2120 
2121             /* Check for port number and interface ID */
2122             if(nx_bsd_socket_array[i].nx_bsd_socket_local_port == (USHORT)local_port)
2123             {
2124 
2125                 address_conflict = 1;
2126 
2127                 if((nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface == bsd_socket_ptr -> nx_bsd_socket_local_bind_interface) &&
2128                    (nx_bsd_socket_array[i].nx_bsd_socket_family == bsd_socket_ptr -> nx_bsd_socket_family))
2129                 {
2130 
2131                     /* This is completely duplicate binding.  */
2132 
2133                     /* If it is a TCP non-listen socket (in other words a TCP server socket that is
2134                        already in connection, and the REUSEADDR is set, it is OK. */
2135                     if((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED) &&
2136                        (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CLIENT)) &&
2137                        (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR))
2138                     {
2139 
2140                         address_conflict = 0;
2141                     }
2142                 }
2143                 else
2144                 {
2145 
2146                     /* If the REUSEADDR option is set, the socket can be bound to its specififed local address. */
2147                     if(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR)
2148                     {
2149 
2150                         address_conflict = 0;
2151 
2152                         if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
2153                         {
2154 
2155                             UINT counter;
2156 
2157                             /* For UDP socket, it needs to share the underlying NetX UDP socket. */
2158                             nx_udp_socket_delete(bsd_socket_ptr -> nx_bsd_socket_udp_socket);
2159 
2160                             /* Free the memory. */
2161                             memset((VOID*)bsd_socket_ptr -> nx_bsd_socket_udp_socket, 0, sizeof(NX_UDP_SOCKET));
2162 
2163                             tx_block_release((VOID*)bsd_socket_ptr -> nx_bsd_socket_udp_socket);
2164 
2165                             /* Add this bsd udp socket to the list that map to the same NetX udp socket. */
2166 
2167                             /* See if this is the only bsd udp socket on the list. */
2168                             if ((&nx_bsd_socket_array[i]) == nx_bsd_socket_array[i].nx_bsd_socket_next)
2169                             {
2170 
2171                                 /* Yes, the only bsd udp socket on the list. */
2172                                 /* Update the list. */
2173                                 bsd_socket_ptr -> nx_bsd_socket_next = &nx_bsd_socket_array[i];
2174                                 bsd_socket_ptr -> nx_bsd_socket_previous = &nx_bsd_socket_array[i];
2175                                 nx_bsd_socket_array[i].nx_bsd_socket_next = bsd_socket_ptr;
2176                                 nx_bsd_socket_array[i].nx_bsd_socket_previous = bsd_socket_ptr;
2177 
2178                             }
2179                             else
2180                             {
2181 
2182                                 /* At least one more bsd udp socket on this list. */
2183                                 /* Update the list. */
2184                                 bsd_socket_ptr -> nx_bsd_socket_next = nx_bsd_socket_array[i].nx_bsd_socket_next;
2185                                 bsd_socket_ptr -> nx_bsd_socket_previous = &nx_bsd_socket_array[i];
2186                                 (nx_bsd_socket_array[i].nx_bsd_socket_next) -> nx_bsd_socket_previous = bsd_socket_ptr;
2187                                 nx_bsd_socket_array[i].nx_bsd_socket_next = bsd_socket_ptr;
2188                             }
2189 
2190 
2191                             bsd_socket_ptr -> nx_bsd_socket_udp_socket = nx_bsd_socket_array[i].nx_bsd_socket_udp_socket;
2192 
2193                             /* Increase the counter. */
2194                             counter = (UINT)bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_reserved_ptr;
2195                             counter = ((counter & 0xFFFF0000) + 0x00010000 + (counter & 0x0000FFFF)) & 0xFFFFFFFF;
2196 
2197                             bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_reserved_ptr = (VOID*)counter;
2198 
2199                             bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)local_port;
2200                             bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
2201 
2202                             /* Release the protection mutex.  */
2203                             tx_mutex_put(nx_bsd_protection_ptr);
2204 
2205                             return(NX_SOC_OK);
2206                         }
2207                         else if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
2208                         {
2209 
2210                             /* Just point this BSD TCP socket to the same secondary socket. */
2211                             (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;
2212 
2213                             bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
2214 
2215                             bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)local_port;
2216 #if defined(__PRODUCT_NETXDUO__) && !defined(NX_DISABLE_IPV4)
2217                             /* Handle client sockets differently. Share the port here for sockets with different IP/IPv6 addresses. */
2218                             if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_client_type == NX_TRUE)
2219                             {
2220 
2221                                 /* Handle client sockets differently. Share the port here for sockets with different IP/IPv6 addresses. */
2222                                 if (((bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6) && (nx_bsd_socket_array[i].nx_bsd_socket_family == AF_INET)) ||
2223                                     ((bsd_socket_ptr -> nx_bsd_socket_family == AF_INET) && (nx_bsd_socket_array[i].nx_bsd_socket_family == AF_INET6)))
2224 
2225                                 {
2226 
2227                                 NX_IP *ip_ptr = nx_bsd_default_ip;
2228                                 NX_TCP_SOCKET *socket_ptr = bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
2229 
2230 
2231                                     /* Calculate the hash index in the TCP port array of the associated IP instance.  */
2232                                     UINT index =  (UINT) ((local_port + (local_port >> 8)) & NX_TCP_PORT_TABLE_MASK);
2233 
2234                                     /* This non server socket needs to share a port with the other client socket. */
2235                                     socket_ptr -> nx_tcp_socket_port = (UINT)local_port;
2236 
2237 
2238                                     tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
2239 
2240                                     /* Add this socket to the list of bound sockets.  */
2241                                     socket_ptr -> nx_tcp_socket_bound_next =   ip_ptr -> nx_ip_tcp_port_table[index];
2242                                     socket_ptr -> nx_tcp_socket_bound_previous =  (ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous;
2243                                     ((ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous) -> nx_tcp_socket_bound_next =  socket_ptr;
2244                                     (ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous = socket_ptr;
2245 
2246 
2247                                     tx_mutex_put(&ip_ptr -> nx_ip_protection);
2248                                 }
2249                             }
2250 #endif
2251 
2252                             /* Release the protection mutex.  */
2253                             tx_mutex_put(nx_bsd_protection_ptr);
2254 
2255                             return(NX_SOC_OK);
2256                         }
2257                     }
2258                 }
2259 
2260                 if(address_conflict)
2261                 {
2262 
2263                     break; /* Break out of the for loop */
2264                 }
2265             }
2266         }
2267     }
2268 
2269 #ifdef NX_BSD_RAW_SUPPORT
2270     if (localAddress -> sa_family == AF_PACKET)
2271     {
2272         for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
2273         {
2274 
2275             /* Skip its own entry. */
2276             if((i == sockID) ||
2277                /* Skip invalid entries. */
2278                (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE)) ||
2279                /* Skip the entries with different protocol ID */
2280                (nx_bsd_socket_array[i].nx_bsd_socket_protocol != bsd_socket_ptr -> nx_bsd_socket_protocol) ||
2281                /* Skip the entries with different address family. */
2282                (nx_bsd_socket_array[i].nx_bsd_socket_family != bsd_socket_ptr -> nx_bsd_socket_family) ||
2283                /* Skip the unbound entries */
2284                (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND)))
2285             {
2286 
2287                 continue;
2288             }
2289 
2290             if (nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface_index == bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index)
2291             {
2292 
2293                 /* Bind to same interface. */
2294                 address_conflict = 1;
2295                 break;
2296             }
2297 
2298             if (nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface_index == NX_BSD_LOCAL_IF_INADDR_ANY)
2299             {
2300 
2301                 /* A socket is bound to any interface. */
2302                 address_conflict = 1;
2303                 break;
2304             }
2305         }
2306     }
2307 #endif /* NX_BSD_RAW_SUPPORT */
2308 
2309     if(address_conflict)
2310     {
2311 
2312         /* Release the protection mutex.  */
2313         tx_mutex_put(nx_bsd_protection_ptr);
2314 
2315         /* Set the socket error if extended socket options enabled. */
2316         nx_bsd_set_errno(EADDRINUSE);
2317 
2318         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
2319         return(NX_SOC_ERROR);
2320     }
2321 
2322     /* Mark this BSD socket as busy.  */
2323     bsd_socket_ptr -> nx_bsd_socket_busy = tx_thread_identify();
2324 
2325     /* Determine what type of bind is required.  */
2326     if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
2327     {
2328 
2329         /* Setup TCP socket pointer.  */
2330         tcp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
2331 
2332         /* Call NetX to bind the client socket.  */
2333         status =  nx_tcp_client_socket_bind(tcp_socket_ptr, (UINT)local_port, NX_NO_WAIT);
2334 
2335         /* Update the port. */
2336         if((status == NX_SUCCESS) && (local_port == 0))
2337             local_port = (INT)(tcp_socket_ptr -> nx_tcp_socket_port);
2338 
2339     }
2340     else if (bsd_socket_ptr -> nx_bsd_socket_udp_socket)
2341     {
2342 
2343         /* Set up a pointer to the UDP socket.  */
2344         udp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_udp_socket;
2345 
2346         /* Bind the UDP socket to the specified port in NetX.  */
2347         status =  nx_udp_socket_bind(udp_socket_ptr, (UINT)local_port, NX_BSD_TIMEOUT);
2348 
2349         /* Update the port. */
2350         if((status == NX_SUCCESS) && (local_port == 0))
2351             local_port = (INT)(udp_socket_ptr -> nx_udp_socket_port);
2352     }
2353     else
2354     {
2355 
2356         /* Raw socket.  All done.  Just need to set status = NX_SUCCESS and continue. */
2357         status = NX_SUCCESS;
2358     }
2359 
2360 
2361     /* Check if we were able to bind the port. */
2362     if (status == NX_SUCCESS)
2363     {
2364 
2365         bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)local_port;
2366         bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
2367 
2368 
2369         /* Make sure this thread is still the owner.  */
2370         if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
2371         {
2372 
2373             /* Clear the busy flag.  */
2374             bsd_socket_ptr -> nx_bsd_socket_busy =  TX_NULL;
2375         }
2376 
2377         /* Release the protection mutex.  */
2378         tx_mutex_put(nx_bsd_protection_ptr);
2379 
2380         /* Return successful status.  */
2381         return(NX_SOC_OK);
2382 
2383     }
2384 
2385     /* Release the protection mutex.  */
2386     tx_mutex_put(nx_bsd_protection_ptr);
2387 
2388     /* Set the socket error, if extended socket options enabled,  depending on the status returned by NetX. */
2389     nx_bsd_set_error_code(bsd_socket_ptr, status);
2390 
2391     /* Return an error, unsuccessful socket bind call.  */
2392     NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2393     return(NX_SOC_ERROR);
2394 
2395 }
2396 
2397 
2398 /**************************************************************************/
2399 /*                                                                        */
2400 /*  FUNCTION                                               RELEASE        */
2401 /*                                                                        */
2402 /*    listen                                              PORTABLE C      */
2403 /*                                                           6.3.0        */
2404 /*  AUTHOR                                                                */
2405 /*                                                                        */
2406 /*    Yuxin Zhou, Microsoft Corporation                                   */
2407 /*                                                                        */
2408 /*  DESCRIPTION                                                           */
2409 /*                                                                        */
2410 /*    This function sets the given socket ready to accept incoming client */
2411 /*    connections. The socket must already be associated with a local port*/
2412 /*    which means the bind() must have been called previously.            */
2413 /*    After this call, incoming TCP connections requests addressed to the */
2414 /*    local port (and IP address, if specified previously) will be        */
2415 /*    completed & queued until they are passed to the program via accept()*/
2416 /*                                                                        */
2417 /*  INPUT                                                                 */
2418 /*                                                                        */
2419 /*    sockID                                socket descriptor             */
2420 /*    backlog                               Maximum number of new         */
2421 /*                                          connections queued            */
2422 /*                                                                        */
2423 /*                                                                        */
2424 /*  OUTPUT                                                                */
2425 /*                                                                        */
2426 /*    NX_SOC_OK (0)                         If success                    */
2427 /*    NX_SOC_ERROR (-1)                     If failure.                   */
2428 /*                                                                        */
2429 /*  CALLS                                                                 */
2430 /*                                                                        */
2431 /*    socket                                Create a server socket        */
2432 /*    nx_tcp_server_socket_listen           Enable a server socket listen */
2433 /*    tx_mutex_get                          Get protection                */
2434 /*    tx_mutex_put                          Release protection            */
2435 /*                                                                        */
2436 /*                                                                        */
2437 /*  CALLED BY                                                             */
2438 /*                                                                        */
2439 /*    Application Code                                                    */
2440 /*                                                                        */
2441 /*  RELEASE HISTORY                                                       */
2442 /*                                                                        */
2443 /*    DATE              NAME                      DESCRIPTION             */
2444 /*                                                                        */
2445 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2446 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
2447 /*                                            resulting in version 6.1    */
2448 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
2449 /*                                            used new API/structs naming,*/
2450 /*                                            resulting in version 6.3.0  */
2451 /*                                                                        */
2452 /**************************************************************************/
nx_bsd_listen(INT sockID,INT backlog)2453 INT  nx_bsd_listen(INT sockID, INT backlog)
2454 {
2455 
2456 UINT                status;
2457 NX_BSD_SOCKET      *bsd_socket_ptr;
2458 NX_BSD_SOCKET      *bsd_secondary_socket;
2459 INT                 secondary_sockID;
2460 INT                 ret;
2461 
2462 
2463     /* Check whether supplied socket ID is valid.  */
2464     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
2465     {
2466 
2467         /* Set the socket error if extended socket options enabled. */
2468         nx_bsd_set_errno(EBADF);
2469 
2470         /* Return an error. */
2471         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2472         return(NX_SOC_ERROR);
2473     }
2474 
2475     /* Normalize the socket ID.  */
2476     sockID =  sockID - NX_BSD_SOCKFD_START;
2477 
2478     /* Get the protection mutex.  */
2479     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
2480 
2481     /* Check the status.  */
2482     if (status)
2483     {
2484 
2485         /* Set the socket error if extended socket options enabled. */
2486         nx_bsd_set_errno(EACCES);
2487 
2488         /* Return an error. */
2489         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
2490         return(NX_SOC_ERROR);
2491     }
2492 
2493     /* Set up a pointer to the BSD socket.  */
2494     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
2495 
2496     /* Determine if the socket is a UDP socket or raw  */
2497     if (bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
2498     {
2499 
2500         /* The underlying protocol is not TCP, therefore it does not support the listen operation. */
2501         nx_bsd_set_errno(EOPNOTSUPP);
2502 
2503         /* Release the protection mutex.  */
2504         tx_mutex_put(nx_bsd_protection_ptr);
2505 
2506         /* Return an error code.  */
2507         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2508         return(NX_SOC_ERROR);
2509     }
2510 
2511     /* Is the socket still in use?  */
2512     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
2513     {
2514 
2515         /* Set the socket error if extended socket options enabled. */
2516         nx_bsd_set_errno(EBADF);
2517 
2518         /* Release the protection mutex.  */
2519         tx_mutex_put(nx_bsd_protection_ptr);
2520 
2521         /* Return error code.  */
2522         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2523         return(NX_SOC_ERROR);
2524     }
2525 
2526     /* Check if the socket has an error */
2527     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
2528     {
2529         INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
2530 
2531         /* Now clear the error code. */
2532         bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
2533 
2534         /* Clear the error flag.  The application is expected to close the socket at this point.*/
2535         bsd_socket_ptr -> nx_bsd_socket_status_flags =
2536             bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
2537 
2538         nx_bsd_set_errno(errcode);
2539 
2540         /* Release the protection mutex.  */
2541         tx_mutex_put(nx_bsd_protection_ptr);
2542 
2543         /* Return an error.  */
2544         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2545 
2546         /* At this point the error flag is cleared.  Application should
2547            detect and handle the error codition. This socket is still bound
2548            to the port (either the application called bind(), or a bind
2549            operation was executed as part of the connect call) is able to
2550            handle another "connect" call, or be closed. */
2551         return(NX_SOC_ERROR);
2552     }
2553 
2554     /* Have we already started listening?  */
2555     if (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN)
2556     {
2557 
2558         /* Error, socket is already listening.  */
2559 
2560         /* Release the protection mutex.  */
2561         tx_mutex_put(nx_bsd_protection_ptr);
2562 
2563         /* Set the socket error if extended socket options enabled. */
2564         nx_bsd_set_errno(EINVAL);
2565 
2566         /* Return error code.  */
2567         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2568         return(NX_SOC_ERROR);
2569     }
2570 
2571     /* Check if this is a secondary server socket.  */
2572     if (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET)
2573     {
2574 
2575         /* Error, socket is a secondary server socket.  */
2576 
2577         /* Release the protection mutex.  */
2578         tx_mutex_put(nx_bsd_protection_ptr);
2579 
2580         /* Set the socket error if extended socket options enabled. */
2581         nx_bsd_set_errno(EOPNOTSUPP);
2582 
2583         /* Return error code.  */
2584         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2585         return(NX_SOC_ERROR);
2586     }
2587 
2588     /* Check if bound to a port.  */
2589     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND))
2590     {
2591 
2592        /* Release the protection mutex.  */
2593        tx_mutex_put(nx_bsd_protection_ptr);
2594 
2595        /* Set the socket error code. */
2596        nx_bsd_set_errno(EDESTADDRREQ);
2597 
2598        /* Return error code.  */
2599        NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2600        return(NX_SOC_ERROR);
2601     }
2602 
2603     /* Check if this master (listening) socket's secondary socket is not marked invalid.  If not, it means this socket will
2604        share the secondary socket with another master socket. */
2605     if((bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id != NX_BSD_MAX_SOCKETS)
2606     {
2607 
2608         /* It is set. */
2609 
2610         secondary_sockID = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id;
2611 
2612         bsd_secondary_socket = &nx_bsd_socket_array[secondary_sockID];
2613 
2614         /* Now check if the other master socket is in listen mode. */
2615         if(bsd_secondary_socket -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN)
2616         {
2617 
2618             /* It  is ready.. we are ready to listen on this socket. */
2619 
2620             bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ENABLE_LISTEN;
2621             bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET);
2622             bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_client_type =  NX_FALSE;
2623             bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_SERVER_MASTER_SOCKET;
2624 
2625             /* Release the protection mutex.  */
2626             tx_mutex_put(nx_bsd_protection_ptr);
2627 
2628             return(NX_SOC_OK);
2629         }
2630     }
2631 
2632     if(backlog < NX_BSD_TCP_LISTEN_MIN_BACKLOG)
2633     {
2634         backlog = NX_BSD_TCP_LISTEN_MIN_BACKLOG;
2635     }
2636 
2637     /* We need to set up this socket as a listen socket. */
2638     ret = nx_bsd_tcp_create_listen_socket(sockID, backlog);
2639 
2640     /* Release the mutex protection.  */
2641     tx_mutex_put(nx_bsd_protection_ptr);
2642 
2643     /* Return success.  */
2644     return(ret);
2645 }
2646 
2647 
2648 /**************************************************************************/
2649 /*                                                                        */
2650 /*  FUNCTION                                               RELEASE        */
2651 /*                                                                        */
2652 /*    accept                                              PORTABLE C      */
2653 /*                                                           6.3.0        */
2654 /*  AUTHOR                                                                */
2655 /*                                                                        */
2656 /*    Yuxin Zhou, Microsoft Corporation                                   */
2657 /*                                                                        */
2658 /*  DESCRIPTION                                                           */
2659 /*                                                                        */
2660 /*    This function blocks while waiting for connections addressed to the */
2661 /*    IP address and port to which this socket is bound. A listen() must  */
2662 /*    previously have been called on this given socket.                   */
2663 /*                                                                        */
2664 /*    When a connection arrives and the TCP handshake is successfully     */
2665 /*    completed, this function returns with a new socket with local and   */
2666 /*    remote address and port numbers filled in.                          */
2667 /*                                                                        */
2668 /*    For non blocking sockets, this function returns immediately.        */
2669 /*                                                                        */
2670 /*  INPUT                                                                 */
2671 /*                                                                        */
2672 /*     sockID                               socket descriptor             */
2673 /*     clientAddress                        Originating socket IP address */
2674 /*                                          and port.                     */
2675 /*     addressLength                        Length of sockaddr buffer (in)*/
2676 /*                                          returned address (out)        */
2677 /*                                                                        */
2678 /*  OUTPUT                                                                */
2679 /*                                                                        */
2680 /*    socket id                             Socket ID for new connection  */
2681 /*    NX_SOC_ERROR (-1)                     If failure                    */
2682 /*                                                                        */
2683 /*  CALLS                                                                 */
2684 /*                                                                        */
2685 /*    memset                                Clears memory                 */
2686 /*    socket                                Create a server socket        */
2687 /*    nx_tcp_server_socket_relisten         Relisten with a new TCP soc   */
2688 /*    nx_tcp_server_socket_accept           Accept a client connection    */
2689 /*    tx_mutex_get                          Get protection                */
2690 /*    tx_mutex_put                          Release protection            */
2691 /*    tx_thread_identify                    Gets the current thread       */
2692 /*                                                                        */
2693 /*  CALLED BY                                                             */
2694 /*                                                                        */
2695 /*    Application Code                                                    */
2696 /*                                                                        */
2697 /*  RELEASE HISTORY                                                       */
2698 /*                                                                        */
2699 /*    DATE              NAME                      DESCRIPTION             */
2700 /*                                                                        */
2701 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
2702 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
2703 /*                                            verified memcpy use cases,  */
2704 /*                                            resulting in version 6.1    */
2705 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
2706 /*                                            used new API/structs naming,*/
2707 /*                                            resulting in version 6.3.0  */
2708 /*                                                                        */
2709 /**************************************************************************/
nx_bsd_accept(INT sockID,struct nx_bsd_sockaddr * ClientAddress,INT * addressLength)2710 INT  nx_bsd_accept(INT sockID, struct nx_bsd_sockaddr *ClientAddress, INT *addressLength)
2711 {
2712 /* Define the accept function if NetX BSD accept() is not set to asynchronous (on automatic callback). */
2713 
2714 UINT                status;
2715 NX_BSD_SOCKET       *bsd_socket_ptr;
2716 NX_BSD_SOCKET       *bsd_secondary_socket;
2717 INT                 sec_sock_id;
2718 INT                 ret = 0;
2719 INT                 connected = 0;
2720 ULONG               requested_events;
2721 INT                 secondary_socket_id = 0;
2722 #ifndef NX_DISABLE_IPV4
2723 struct nx_bsd_sockaddr_in
2724                     peer4_address;
2725 #endif /* NX_DISABLE_IPV4 */
2726 #ifdef FEATURE_NX_IPV6
2727 struct nx_bsd_sockaddr_in6
2728                     peer6_address;
2729 #endif
2730 
2731 
2732     /* Check for valid socket ID.  */
2733     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
2734     {
2735 
2736         /* Set the socket error if extended socket options enabled. */
2737         nx_bsd_set_errno(EBADF);
2738 
2739         /* Return an error.*/
2740         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2741         return(NX_SOC_ERROR);
2742     }
2743 
2744     /* Normalize the socket ID.  */
2745     sockID =  sockID - NX_BSD_SOCKFD_START;
2746 
2747     /* Setup pointer to the BSD socket.  */
2748     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
2749 
2750     /* Get the protection mutex.  */
2751     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
2752 
2753     /* Check the status.  */
2754     if (status != NX_SUCCESS)
2755     {
2756 
2757         /* Set the socket error if extended socket options enabled. */
2758         nx_bsd_set_errno(EACCES);
2759 
2760         /* Return an error.*/
2761         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
2762         return(NX_SOC_ERROR);
2763     }
2764 
2765     /* Is the socket still in use?  */
2766     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
2767     {
2768 
2769         /* Release the protection mutex.  */
2770         tx_mutex_put(nx_bsd_protection_ptr);
2771 
2772         /* Set the socket error if extended socket options enabled. */
2773         nx_bsd_set_errno(EBADF);
2774 
2775         /* Return an error.  */
2776         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2777         return(NX_SOC_ERROR);
2778     }
2779 
2780     /* If the socket has an error */
2781     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
2782     {
2783 
2784         INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
2785 
2786         /* Now clear the error code. */
2787         bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
2788 
2789         /* Clear the error flag.  The application is expected to close the socket at this point.*/
2790         bsd_socket_ptr -> nx_bsd_socket_status_flags =
2791             bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
2792 
2793         nx_bsd_set_errno(errcode);
2794 
2795         /* Release the protection mutex.  */
2796         tx_mutex_put(nx_bsd_protection_ptr);
2797 
2798         /* Return an error.  */
2799         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2800 
2801         /* At this point the error flag is cleared.  Application should
2802            detect and handle the error codition. This socket is still bound
2803            to the port (either the application called bind(), or a bind
2804            operation was executed as part of the connect call) is able to
2805 
2806            handle another "connect" call, or be closed. */
2807         return(NX_SOC_ERROR);
2808     }
2809 
2810     /* Determine if the socket is a UDP socket.  */
2811     if (bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
2812     {
2813 
2814         /* Error, UDP or raw sockets do not perform listen.  */
2815 
2816         /* Release the protection mutex.  */
2817         tx_mutex_put(nx_bsd_protection_ptr);
2818 
2819         /* Set the socket error if extended socket options enabled. */
2820         nx_bsd_set_errno(EOPNOTSUPP);
2821 
2822         /* Return error code.  */
2823         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2824         return(NX_SOC_ERROR);
2825     }
2826 
2827     /* Has listening been enabled on this socket?  */
2828     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN))
2829     {
2830 
2831         /* No, this socket is not ready to accept TCP connections. */
2832 
2833         /* Release the protection mutex.  */
2834         tx_mutex_put(nx_bsd_protection_ptr);
2835 
2836         /* Set the socket error if extended socket options enabled. */
2837         nx_bsd_set_errno(EINVAL);
2838 
2839         /* Return error code.  */
2840         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2841         return(NX_SOC_ERROR);
2842     }
2843 
2844     /* Make sure the accept call operates on the master socket. */
2845     if((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) == 0)
2846     {
2847         /* This is not a master socket.
2848            BSD accept is only allowed on the master socket.
2849            Return. */
2850 
2851         /* Release the protection mutex.  */
2852         tx_mutex_put(nx_bsd_protection_ptr);
2853 
2854         /* Set the socket error if extended socket options enabled. */
2855         nx_bsd_set_errno(EBADF);
2856 
2857         /* Return error code.  */
2858         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2859         return(NX_SOC_ERROR);
2860     }
2861 
2862     /* Validate the secondary server socket.  */
2863     if ((bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id >= NX_BSD_MAX_SOCKETS)
2864     {
2865 
2866         /* This secondary socket is not available yet.  This could happen if the
2867            previous accept call fails to allocate a new secondary socket. */
2868         ret = nx_bsd_tcp_create_listen_socket(sockID, 0);
2869 
2870         if(ret < 0)
2871         {
2872 
2873             /* Failed to allocate a secondary socket, release the protection mutex.  */
2874             tx_mutex_put(nx_bsd_protection_ptr);
2875 
2876             /* Errno is already set inside nx_bsd_tcp_create_listen_socket.  Therefore
2877                there is no need to set errno here. */
2878 
2879             /* Return an error. */
2880             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2881             return(NX_SOC_ERROR);
2882         }
2883     }
2884 
2885     /* At this point, we have found and marked a secondary server socket for the connection request.  */
2886 
2887     /* Set up a pointer to the secondary server socket.  */
2888     sec_sock_id = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id;
2889     bsd_secondary_socket =  &nx_bsd_socket_array[sec_sock_id];
2890 
2891     /* Mark this BSD socket as busy.  */
2892     bsd_socket_ptr -> nx_bsd_socket_busy = tx_thread_identify();
2893 
2894     /* If the master socket is marked as non-blocking, we just need to check if the
2895        secondary socket has a connection already. */
2896     while(!connected)
2897     {
2898 
2899         secondary_socket_id = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id;
2900 
2901         if((secondary_socket_id < NX_BSD_MAX_SOCKETS) &&
2902            (nx_bsd_socket_array[secondary_socket_id].nx_bsd_socket_union_id.nx_bsd_socket_master_socket_id == sockID) &&
2903            (nx_bsd_socket_array[secondary_socket_id].nx_bsd_socket_status_flags & (NX_BSD_SOCKET_CONNECTED | NX_BSD_SOCKET_ERROR)))
2904         {
2905 
2906             connected = 1;
2907             bsd_secondary_socket = &nx_bsd_socket_array[secondary_socket_id];
2908             bsd_secondary_socket -> nx_bsd_socket_family = bsd_socket_ptr -> nx_bsd_socket_family;
2909             bsd_secondary_socket -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
2910 
2911         }
2912         else
2913         {
2914 
2915             if(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING)
2916             {
2917 
2918                 /* No connection yet. Return EWOULDBLOCK */
2919 
2920                 tx_mutex_put(nx_bsd_protection_ptr);
2921 
2922                 /* Set the socket error if extended socket options enabled. */
2923                 nx_bsd_set_errno(EWOULDBLOCK);
2924 
2925                 /* Return an error. */
2926                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2927 
2928                 if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
2929                 {
2930                     bsd_socket_ptr -> nx_bsd_socket_busy = NX_NULL;
2931                 }
2932                 return(NX_SOC_ERROR);
2933             }
2934 
2935             tx_mutex_put(nx_bsd_protection_ptr);
2936             tx_event_flags_get(&nx_bsd_events, NX_BSD_RECEIVE_EVENT, TX_OR_CLEAR, &requested_events, TX_WAIT_FOREVER);
2937             tx_mutex_get(nx_bsd_protection_ptr, TX_WAIT_FOREVER);
2938 
2939             /* Verify the socket is still valid. */
2940             if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
2941             {
2942                 /* The socket is no longer in use. */
2943 
2944                 /* Set the socket error code. */
2945                 nx_bsd_set_errno(EBADF);
2946 
2947                 /* Release the protection mutex.  */
2948                 tx_mutex_put(nx_bsd_protection_ptr);
2949 
2950                 /* Return error code.  */
2951                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2952                 return(NX_SOC_ERROR);
2953             }
2954         }
2955     }
2956 
2957     /* If we get here, we should have a valid connection, or an error occured. */
2958     if(bsd_secondary_socket -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
2959     {
2960         INT errcode = bsd_secondary_socket -> nx_bsd_socket_error_code;
2961 
2962         /* Now clear the error code. */
2963         bsd_secondary_socket -> nx_bsd_socket_error_code = 0;
2964 
2965         /* Clear the error flag.  The application is expected to close the socket at this point.*/
2966         bsd_secondary_socket -> nx_bsd_socket_status_flags =
2967             bsd_secondary_socket -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
2968 
2969         nx_bsd_set_errno(errcode);
2970 
2971         /* Return an error.  */
2972         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2973 
2974         /* Release the protection mutex.  */
2975         tx_mutex_put(nx_bsd_protection_ptr);
2976 
2977         /* At this point the error flag is cleared.  Application should
2978            detect and handle the error codition. This socket is still bound
2979            to the port (either the application called bind(), or a bind
2980            operation was executed as part of the connect call) is able to
2981            handle another "connect" call, or be closed. */
2982         return(NX_SOC_ERROR);
2983     }
2984 
2985     /* Update the BSD socket source port and sender IP address. */
2986     status = nxd_tcp_socket_peer_info_get(bsd_secondary_socket -> nx_bsd_socket_tcp_socket,
2987                                           &bsd_secondary_socket -> nx_bsd_socket_source_ip_address,
2988                                           (ULONG *)(&bsd_secondary_socket -> nx_bsd_socket_source_port));
2989 
2990     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. */
2991 
2992     bsd_secondary_socket -> nx_bsd_socket_peer_port = (USHORT)(bsd_secondary_socket -> nx_bsd_socket_source_port);
2993 
2994     /* Record the peer information. */
2995 #ifndef NX_DISABLE_IPV4
2996     if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
2997     {
2998 
2999         bsd_secondary_socket -> nx_bsd_socket_source_ip_address.nxd_ip_address.v4 =
3000                 bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v4;
3001     }
3002 #endif /* NX_DISABLE_IPV4 */
3003 #ifdef FEATURE_NX_IPV6
3004     if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
3005     {
3006 
3007         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];
3008         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];
3009         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];
3010         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];
3011     }
3012 #endif
3013 
3014     /* Attempt to obtain peer address if ClientAddress is not NULL. */
3015     if(ClientAddress && addressLength != 0)
3016     {
3017 
3018 #ifndef NX_DISABLE_IPV4
3019         /* Handle the IPv4 socket type. */
3020         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
3021         {
3022 
3023             /* Update the Client address with socket family, remote host IPv4 address and port.  */
3024             peer4_address.sin_family =      AF_INET;
3025             peer4_address.sin_addr.s_addr = ntohl(bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v4);
3026             peer4_address.sin_port =        ntohs((USHORT)bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_port);
3027 
3028             /* Copy the peer address/port info to the ClientAddress.  Truncate if
3029                addressLength is smaller than the size of struct sockaddr_in */
3030             if(*addressLength > (INT)sizeof(struct nx_bsd_sockaddr_in))
3031             {
3032 
3033                 memcpy(ClientAddress, &peer4_address, sizeof(struct nx_bsd_sockaddr_in)); /* Use case of memcpy is verified. */
3034                 *addressLength = sizeof(struct nx_bsd_sockaddr_in);
3035             }
3036             else
3037             {
3038                 memcpy(ClientAddress, &peer4_address, (UINT)(*addressLength)); /* Use case of memcpy is verified. */
3039             }
3040         }
3041         else
3042 #endif /* NX_DISABLE_IPV4 */
3043 
3044 #ifdef FEATURE_NX_IPV6
3045         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
3046         {
3047 
3048             /* Update the Client address with socket family, remote host IPv6 address and port.  */
3049             peer6_address.sin6_family = AF_INET6;
3050 
3051             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]);
3052             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]);
3053             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]);
3054             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]);
3055 
3056             peer6_address.sin6_port = ntohs((USHORT)bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_port);
3057 
3058             if((*addressLength) > (INT)sizeof(peer6_address))
3059             {
3060 
3061                 memcpy(ClientAddress, &peer6_address, sizeof(peer6_address)); /* Use case of memcpy is verified. */
3062                 *addressLength = sizeof(peer6_address);
3063             }
3064             else
3065             {
3066                 memcpy(ClientAddress, &peer6_address, (UINT)(*addressLength)); /* Use case of memcpy is verified. */
3067             }
3068         }
3069         else
3070 #endif /* !FEATURE_NX_IPV6 */
3071         {
3072 
3073             /* Release the protection mutex.  */
3074             tx_mutex_put(nx_bsd_protection_ptr);
3075 
3076             /* Set the socket error if extended socket options enabled. */
3077             nx_bsd_set_errno(EINVAL);
3078 
3079             /* Make sure this thread is still the owner.  */
3080             if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
3081             {
3082 
3083                 /* Clear the busy flag.  */
3084                 bsd_socket_ptr -> nx_bsd_socket_busy =  TX_NULL;
3085             }
3086 
3087             /* Error, IPv6 support is not enabled.  */
3088             NX_BSD_ERROR(ERROR, __LINE__);
3089             return(ERROR);
3090         }
3091     }
3092 
3093     /* Mark the sock_id field in both the master and secondary socket invalid. */
3094     (bsd_secondary_socket -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id = NX_BSD_MAX_SOCKETS;
3095 
3096     /* Clear the master socket connect flags. */
3097     bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTED);
3098     bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_REQUEST);
3099 
3100     /* Reset the master_socket_id */
3101     ret = nx_bsd_tcp_create_listen_socket(sockID, 0);
3102 
3103     if(ret < 0)
3104     {
3105         (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = NX_BSD_MAX_SOCKETS;
3106     }
3107 
3108     /* Make sure this thread is still the owner.  */
3109     if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
3110     {
3111 
3112         /* Clear the busy flag.  */
3113         bsd_socket_ptr -> nx_bsd_socket_busy =  TX_NULL;
3114     }
3115 
3116     /* Release the protection mutex.  */
3117     tx_mutex_put(nx_bsd_protection_ptr);
3118 
3119     return(secondary_socket_id + NX_BSD_SOCKFD_START);
3120 
3121 }
3122 
3123 /**************************************************************************/
3124 /*                                                                        */
3125 /*  FUNCTION                                               RELEASE        */
3126 /*                                                                        */
3127 /*    nx_bsd_send_internal                                PORTABLE C      */
3128 /*                                                           6.3.0        */
3129 /*  AUTHOR                                                                */
3130 /*                                                                        */
3131 /*    Yuxin Zhou, Microsoft Corporation                                   */
3132 /*                                                                        */
3133 /*  DESCRIPTION                                                           */
3134 /*                                                                        */
3135 /*    This is sends a message to a given destination address/port         */
3136 /*                                                                        */
3137 /*  INPUT                                                                 */
3138 /*                                                                        */
3139 /*    sockID                                BSD Socket ID                 */
3140 /*    msg                                   Pointer to the outgoing       */
3141 /*                                            message                     */
3142 /*    msgLength                             The Size of the message       */
3143 /*    flags                                 Control flags, support        */
3144 /*                                            MSG_DONTWAIT                */
3145 /*    dst_address                           The Destination Address       */
3146 /*    dst_port                              The Destination Port          */
3147 /*    local_inteterface_index               The local outgoing interface  */
3148 /*                                            to use                      */
3149 /*                                                                        */
3150 /*  OUTPUT                                                                */
3151 /*                                                                        */
3152 /*    data_sent                                                           */
3153 /*                                                                        */
3154 /*  CALLS                                                                 */
3155 /*                                                                        */
3156 /*    set_errno                             Sets the BSD errno            */
3157 /*    nx_packet_allocate                    Allocate a packet             */
3158 /*    nx_packet_data_append                 Append data to the packet     */
3159 /*    tx_mutex_get                          Get Mutex protection          */
3160 /*    tx_mutex_put                          Release Mutex protection      */
3161 /*    nx_packet_release                     Release the packet on error   */
3162 /*    nx_udp_socket_send                    UDP packet send               */
3163 /*    nx_udp_socket_interface_send          UDP packet send via a         */
3164 /*                                            specific interface          */
3165 /*    nx_tcp_socket_send                    TCP packet send               */
3166 /*    _nxd_bsd_ipv4_packet_send             Raw IPv4 packet with header   */
3167 /*                                            included                    */
3168 /*    _nxd_bsd_ipv6_packet_send             Raw IPv6 packet with header   */
3169 /*                                            included                    */
3170 /*    nxd_ip_raw_packet_interface_send      Raw packet send via a         */
3171 /*                                            specific interface          */
3172 /*  CALLED BY                                                             */
3173 /*                                                                        */
3174 /*    send                                                                */
3175 /*    sendto                                                              */
3176 /*                                                                        */
3177 /*  RELEASE HISTORY                                                       */
3178 /*                                                                        */
3179 /*    DATE              NAME                      DESCRIPTION             */
3180 /*                                                                        */
3181 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3182 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3183 /*                                            resulting in version 6.1    */
3184 /*  10-31-2023     Tiejun Zhou              Modified comment(s),          */
3185 /*                                            supported random IP id,     */
3186 /*                                            resulting in version 6.3.0  */
3187 /*                                                                        */
3188 /**************************************************************************/
nx_bsd_send_internal(INT sockID,const CHAR * msg,INT msgLength,INT flags,NXD_ADDRESS * dst_address,USHORT dst_port,UINT local_interface_index)3189 static INT nx_bsd_send_internal(INT sockID, const CHAR *msg, INT msgLength, INT flags,
3190                                 NXD_ADDRESS *dst_address, USHORT dst_port, UINT local_interface_index)
3191 {
3192 UINT                status;
3193 NX_PACKET           *packet_ptr;
3194 NX_TCP_SOCKET       *tcp_socket_ptr;
3195 NX_UDP_SOCKET       *udp_socket_ptr;
3196 NX_BSD_SOCKET       *bsd_socket_ptr;
3197 UINT                packet_type = 0;
3198 UINT                wait_option;
3199 ULONG               data_sent = (ULONG)msgLength;
3200 
3201     bsd_socket_ptr = &nx_bsd_socket_array[sockID];
3202 
3203 #ifndef NX_DISABLE_IPV4
3204     /* Determine the socket family for allocating a packet. */
3205     if (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
3206     {
3207 
3208         /* This is for an IPv4 socket.   */
3209         if (bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
3210         {
3211 
3212             /* Allocate an IPv4 UDP packet.   */
3213             packet_type = NX_IPv4_UDP_PACKET;
3214         }
3215         else if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
3216         {
3217 
3218             /* Allocate an IPv4 TCP packet.   */
3219             packet_type = NX_IPv4_TCP_PACKET;
3220         }
3221         else if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE)
3222         {
3223 
3224             packet_type = NX_PHYSICAL_HEADER;
3225         }
3226         else
3227         {
3228 
3229             /* Raw socket. */
3230             packet_type = NX_IPv4_PACKET;
3231         }
3232     }
3233 #endif /* NX_DISABLE_IPV4 */
3234     if (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
3235     {
3236 
3237         /* This is for an IPv6 socket.   */
3238         if (bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
3239         {
3240 
3241             /* Allocate an IPv4 UDP packet.   */
3242             packet_type = NX_IPv6_UDP_PACKET;
3243         }
3244         else if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
3245         {
3246             /* Allocate an IPv4 TCP packet.   */
3247             packet_type = NX_IPv6_TCP_PACKET;
3248         }
3249         else if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE)
3250         {
3251             packet_type = NX_PHYSICAL_HEADER;
3252         }
3253         else
3254         {
3255             /* Raw socket. */
3256             packet_type = NX_IPv6_PACKET;
3257         }
3258     }
3259 
3260     /* Allocate the packet for sending.  */
3261     if(packet_type == 0)
3262     {
3263         /* Set the socket error.  */
3264         nx_bsd_set_errno(EINVAL);
3265 
3266         /* Return an error status.*/
3267         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3268         return(NX_SOC_ERROR);
3269     }
3270 
3271     /* Is this a non blocking socket? */
3272     if ((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING) ||
3273         (flags & MSG_DONTWAIT))
3274     {
3275 
3276         /* Yes, set to wait to zero on the NetX call. */
3277         wait_option = 0 ;
3278     }
3279     /* Does this socket have a send timeout option set? */
3280     else if (bsd_socket_ptr -> nx_bsd_option_send_timeout)
3281     {
3282 
3283         /* Yes, this is our wait option. */
3284         wait_option = bsd_socket_ptr -> nx_bsd_option_send_timeout;
3285     }
3286     else
3287         wait_option = TX_WAIT_FOREVER;
3288 
3289     status =  nx_packet_allocate(nx_bsd_default_packet_pool, &packet_ptr, packet_type, wait_option);
3290 
3291     /* Check for errors.   */
3292     if (status != NX_SUCCESS)
3293     {
3294 
3295         /* Set the socket error.  */
3296         nx_bsd_set_errno(ENOBUFS);
3297 
3298         /* Return an error status.*/
3299         NX_BSD_ERROR(status, __LINE__);
3300         return(NX_SOC_ERROR);
3301     }
3302 
3303     /* Now copy the data into the NetX packet.  */
3304     status =  nx_packet_data_append(packet_ptr, (VOID *) msg, (ULONG)msgLength, nx_bsd_default_packet_pool, wait_option);
3305 
3306     /* Was the data copy successful?  */
3307     if (status != NX_SUCCESS)
3308     {
3309 
3310         nx_packet_release(packet_ptr);
3311 
3312         /* Set the socket error.  */
3313         nx_bsd_set_errno(ENOBUFS);
3314 
3315         /* Return an error status.*/
3316         NX_BSD_ERROR(status, __LINE__);
3317         return(NX_SOC_ERROR);
3318     }
3319 
3320 
3321     /* Get the protection mutex.  */
3322     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
3323 
3324     /* Check the status.  */
3325     if (status != NX_SUCCESS)
3326     {
3327 
3328         /* Release the packet.  */
3329         nx_packet_release(packet_ptr);
3330 
3331         /* Set the socket error if extended socket options enabled. */
3332         nx_bsd_set_errno(EACCES);
3333 
3334         /* Return an error status.*/
3335         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
3336         return(NX_SOC_ERROR);
3337     }
3338 
3339 
3340     /* Is the socket still in use?  */
3341     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
3342     {
3343 
3344         nx_packet_release(packet_ptr);
3345 
3346         /* Set the socket error if extended options enabled. */
3347         nx_bsd_set_errno(EBADF);
3348 
3349         /* Release the protection mutex.  */
3350         tx_mutex_put(nx_bsd_protection_ptr);
3351 
3352         /* Return an error status.*/
3353         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3354         return(NX_SOC_ERROR);
3355     }
3356 
3357 
3358     /* Determine if the socket is a UDP socket.  */
3359     if (bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
3360     {
3361 
3362          /* Pickup the NetX UDP socket.  */
3363          udp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_udp_socket;
3364 
3365          /* Send the UDP packet.  */
3366          if(local_interface_index == NX_BSD_LOCAL_IF_INADDR_ANY)
3367              status =  nxd_udp_socket_send(udp_socket_ptr, packet_ptr, dst_address, dst_port);
3368          else
3369              status =  nxd_udp_socket_interface_send(udp_socket_ptr, packet_ptr, dst_address, dst_port, local_interface_index);
3370     }
3371     else if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
3372     {
3373 
3374         /* We have a TCP socket and a packet ready to send.  */
3375 
3376         /* Set a pointer to the TCP BSD socket.  */
3377         tcp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
3378 
3379         if(wait_option != TX_NO_WAIT)
3380         {
3381             /* Release the protection mutex.  */
3382             tx_mutex_put(nx_bsd_protection_ptr);
3383         }
3384 
3385         /* Send the TCP packet.  */
3386         status =  nx_tcp_socket_send(tcp_socket_ptr, packet_ptr, wait_option);
3387 
3388         /* Check partial data sent. */
3389         if (status)
3390         {
3391 
3392             /* Get length of data sent. */
3393             data_sent -= packet_ptr -> nx_packet_length;
3394 
3395             if (data_sent)
3396             {
3397 
3398                 /* Partial data sent. Mark as success. */
3399                 status = NX_SUCCESS;
3400 
3401                 /* Release the packet.  */
3402                 nx_packet_release(packet_ptr);
3403             }
3404         }
3405 
3406         if(wait_option != TX_NO_WAIT)
3407         {
3408             /* Obtain the protection mutex.  */
3409             tx_mutex_get(nx_bsd_protection_ptr, TX_WAIT_FOREVER);
3410         }
3411     }
3412     else
3413     {
3414         /* Is this BSD socket configured to append the IP header? */
3415         if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE)
3416         {
3417 
3418         /* Yes it is. Make sure the packet source and destination interface are set. */
3419         ULONG *ip_addr_ptr;
3420         UINT   src_interface;
3421 
3422 #ifndef NX_DISABLE_IPV4
3423             if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
3424             {
3425 
3426                 ip_addr_ptr = (ULONG*)(packet_ptr -> nx_packet_prepend_ptr + 12);
3427 
3428                 src_interface = (UINT)nx_bsd_find_interface_by_source_addr(AF_INET, ip_addr_ptr);
3429 
3430                 if(src_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
3431                     src_interface = 0;
3432 
3433                 packet_ptr -> nx_packet_address.nx_packet_interface_ptr = &(nx_bsd_default_ip -> nx_ip_interface[src_interface]);
3434 
3435                 /* If the IP ID field is non-zero, the current nx_ip_packet_id
3436                    value is modified */
3437                 if((*(packet_ptr -> nx_packet_prepend_ptr + 4) == 0) &&
3438                    (*(packet_ptr -> nx_packet_prepend_ptr + 5) == 0))
3439                 {
3440 
3441 #ifdef NX_ENABLE_IP_ID_RANDOMIZATION
3442                     ULONG rand_id = (ULONG)NX_RAND();
3443                     *(packet_ptr -> nx_packet_prepend_ptr + 4) = (UCHAR)((rand_id & 0xFFFF) >> 8);
3444                     *(packet_ptr -> nx_packet_prepend_ptr + 5) = (UCHAR)(rand_id & 0xFF);
3445 #else
3446                     *(packet_ptr -> nx_packet_prepend_ptr + 4) = (UCHAR)(((nx_bsd_default_ip -> nx_ip_packet_id) & 0xFFFF) >> 8);
3447                     *(packet_ptr -> nx_packet_prepend_ptr + 5) = (UCHAR)((nx_bsd_default_ip -> nx_ip_packet_id) & 0xFF);
3448 #endif /* NX_ENABLE_IP_ID_RANDOMIZATION */
3449                 }
3450 
3451                 /* Clear the checksum field. */
3452                 *(packet_ptr -> nx_packet_prepend_ptr + 10) = 0;
3453                 *(packet_ptr -> nx_packet_prepend_ptr + 11) = 0;
3454 
3455                 _nxd_bsd_ipv4_packet_send(packet_ptr);
3456 
3457                 status = NX_SUCCESS;
3458             }
3459 #endif /* NX_DISABLE_IPV4 */
3460 #ifdef FEATURE_NX_IPV6
3461             if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
3462             {
3463 
3464                 ip_addr_ptr = (ULONG*)(packet_ptr -> nx_packet_prepend_ptr + 8);
3465                 src_interface = (UINT)nx_bsd_find_interface_by_source_addr(AF_INET6, ip_addr_ptr);
3466 
3467                 if(src_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
3468                 {
3469                     status = NX_NOT_SUCCESSFUL;
3470                 }
3471 
3472                 else
3473                 {
3474 
3475                     NX_IPV6_HEADER *ipv6_header;
3476                     ULONG src_addr[4], dest_addr[4];
3477 
3478                     packet_ptr -> nx_packet_ip_header = packet_ptr -> nx_packet_prepend_ptr;
3479 
3480                     packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr = &nx_bsd_default_ip -> nx_ipv6_address[src_interface];
3481 
3482                     ipv6_header = (NX_IPV6_HEADER*)packet_ptr -> nx_packet_ip_header;
3483 
3484                     /* Set up source / Destination IP */
3485                     COPY_IPV6_ADDRESS(ipv6_header -> nx_ip_header_destination_ip, dest_addr);
3486                     COPY_IPV6_ADDRESS(ipv6_header -> nx_ip_header_source_ip, src_addr);
3487                     NX_IPV6_ADDRESS_CHANGE_ENDIAN(dest_addr);
3488                     NX_IPV6_ADDRESS_CHANGE_ENDIAN(src_addr);
3489 
3490 
3491                     _nxd_bsd_ipv6_packet_send(packet_ptr, src_addr, dest_addr);
3492 
3493                     status = NX_SUCCESS;
3494                 }
3495             }
3496 #endif
3497         }
3498         else
3499         {
3500 
3501             /* Raw socket without any IP header appended yet. We can send this directly to the NetX Duo IP packet handler.  */
3502             if(local_interface_index == NX_BSD_LOCAL_IF_INADDR_ANY)
3503                 local_interface_index = 0;
3504 
3505             status = nxd_ip_raw_packet_interface_send(nx_bsd_default_ip, packet_ptr, dst_address,
3506                                                       local_interface_index, bsd_socket_ptr -> nx_bsd_socket_protocol,
3507                                                       NX_IP_TIME_TO_LIVE, NX_IP_NORMAL);
3508         }
3509     }
3510 
3511     /* Was the packet send successful?  */
3512     if (status != NX_SUCCESS)
3513     {
3514 
3515         /* No, release the packet.  */
3516         nx_packet_release(packet_ptr);
3517 
3518         /* Set the socket error.  */
3519 
3520         /* Set the socket error according to the NetX error status returned.  */
3521         switch (status)
3522         {
3523 
3524             case NX_IP_ADDRESS_ERROR:
3525                 nx_bsd_set_errno(EDESTADDRREQ);
3526                 break;
3527 
3528             case NX_NOT_ENABLED:
3529                 nx_bsd_set_errno(EPROTONOSUPPORT);
3530                 break;
3531 
3532             case NX_NOT_CONNECTED:
3533                 nx_bsd_set_errno(ENOTCONN);
3534                 break;
3535 
3536             case NX_NO_PACKET:
3537             case NX_UNDERFLOW:
3538                 nx_bsd_set_errno(ENOBUFS);
3539                 break;
3540 
3541             case NX_WINDOW_OVERFLOW:
3542             case NX_WAIT_ABORTED:
3543             case NX_TX_QUEUE_DEPTH:
3544                 if ((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING) ||
3545                     (flags & MSG_DONTWAIT))
3546                     nx_bsd_set_errno( EWOULDBLOCK);
3547                 else
3548                     nx_bsd_set_errno(ETIMEDOUT);
3549                 break;
3550 
3551             default:
3552                 /* NX_NOT_BOUND */
3553                 /* NX_PTR_ERROR */
3554                 /* NX_INVALID_PACKET */
3555                 nx_bsd_set_errno(EINVAL);
3556                 break;
3557         }
3558 
3559         /* Return an error status. */
3560         NX_BSD_ERROR(status, __LINE__);
3561 
3562         /* Release the protection mutex.  */
3563         tx_mutex_put(nx_bsd_protection_ptr);
3564 
3565         return(NX_SOC_ERROR);
3566     }
3567 
3568     /* Release the protection mutex.  */
3569     tx_mutex_put(nx_bsd_protection_ptr);
3570 
3571     return((INT)data_sent);
3572 }
3573 
3574 /**************************************************************************/
3575 /*                                                                        */
3576 /*  FUNCTION                                               RELEASE        */
3577 /*                                                                        */
3578 /*    send                                                PORTABLE C      */
3579 /*                                                           6.3.0        */
3580 /*  AUTHOR                                                                */
3581 /*                                                                        */
3582 /*    Yuxin Zhou, Microsoft Corporation                                   */
3583 /*                                                                        */
3584 /*  DESCRIPTION                                                           */
3585 /*                                                                        */
3586 /*    This function sends a packet out the given  socket.                 */
3587 /*    When the call returns, the data has been queued for transmission    */
3588 /*    over the connection. The return value indicates the number of byes  */
3589 /*    actually transmitted.                                               */
3590 /*                                                                        */
3591 /*    The flags argument is provided for consistency with the BSD send    */
3592 /*    service. It allows various protocol features, such as out-of-bound  */
3593 /*    out-of-bound data, to be accessed. However, none of these features  */
3594 /*    are implemented.                                                    */
3595 /*                                                                        */
3596 /*    If packets are being sent out a UDP socket which is not bound to a  */
3597 /*    local port, this function find an available free port to bind to the*/
3598 /*    socket. For TCP sockets, the socket must already by connected (so   */
3599 /*    also bound to port)                                                 */
3600 /*                                                                        */
3601 /*    Note: send() does not support raw sockets. Use the sendto() service */
3602 /*    to transmit raw packets.                                            */
3603 /*                                                                        */
3604 /*  INPUT                                                                 */
3605 /*                                                                        */
3606 /*    sockID                                Socket                        */
3607 /*    msg                                   Data to be transmitted        */
3608 /*    msgLength                             Number of bytes to be sent    */
3609 /*    flags                                 Control flags, support        */
3610 /*                                            MSG_DONTWAIT                */
3611 /*                                                                        */
3612 /*  OUTPUT                                                                */
3613 /*                                                                        */
3614 /*     number of bytes sent                 If successful                 */
3615 /*     NX_SOC_ERROR (-1)                    If failure                    */
3616 /*                                                                        */
3617 /*  CALLS                                                                 */
3618 /*                                                                        */
3619 /*   nx_tcp_socket_send                     Send a packet                 */
3620 /*   nx_packet_allocate                     Get a free packet             */
3621 /*   nx_packet_data_append                  Copy data into packet         */
3622 /*   nx_packet_release                      Free a packet used to send    */
3623 /*   tx_mutex_get                           Get protection                */
3624 /*   tx_mutex_put                           Release protection            */
3625 /*                                                                        */
3626 /*  CALLED BY                                                             */
3627 /*                                                                        */
3628 /*    Application Code                                                    */
3629 /*                                                                        */
3630 /*  RELEASE HISTORY                                                       */
3631 /*                                                                        */
3632 /*    DATE              NAME                      DESCRIPTION             */
3633 /*                                                                        */
3634 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3635 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3636 /*                                            resulting in version 6.1    */
3637 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
3638 /*                                            used new API/structs naming,*/
3639 /*                                            resulting in version 6.3.0  */
3640 /*                                                                        */
3641 /**************************************************************************/
nx_bsd_send(INT sockID,const CHAR * msg,INT msgLength,INT flags)3642 INT  nx_bsd_send(INT sockID, const CHAR *msg, INT msgLength, INT flags)
3643 {
3644 
3645 NX_BSD_SOCKET *bsd_socket_ptr;
3646 
3647 
3648     /* Check for invalid socket IDd.  */
3649     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
3650     {
3651 
3652         /* Set the socket error if extended options enabled. */
3653         nx_bsd_set_errno(EBADF);
3654 
3655         /* Return an error status.*/
3656         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3657         return(NX_SOC_ERROR);
3658     }
3659 
3660     /* Normalize the socket ID.  */
3661     sockID =  sockID - NX_BSD_SOCKFD_START;
3662 
3663     /* Set up a pointer to the BSD socket.  */
3664     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
3665 
3666     /* If the socket has an error */
3667     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
3668     {
3669         INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
3670 
3671         /* Now clear the error code. */
3672         bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
3673 
3674         /* Clear the error flag.  The application is expected to close the socket at this point.*/
3675         bsd_socket_ptr -> nx_bsd_socket_status_flags =
3676             bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
3677 
3678         nx_bsd_set_errno(errcode);
3679 
3680         /* Return an error.  */
3681         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3682 
3683         /* At this point the error flag is cleared.  Application should
3684            detect and handle the error codition. This socket is still bound
3685            to the port (either the application called bind(), or a bind
3686            operation was executed as part of the connect call) is able to
3687            handle another "connect" call, or be closed. */
3688         return(NX_SOC_ERROR);
3689     }
3690 
3691     /* Send() requires the socket be connected. A connected socket implies the socket is bound.*/
3692     if((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED) == 0)
3693     {
3694 
3695         /* For AF_PACKET family, the socket should be bound. */
3696 #if defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)
3697         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
3698         {
3699             struct nx_bsd_sockaddr_ll sockaddr_dest;
3700 
3701             if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND))
3702             {
3703 
3704                 /* Set the socket error code. */
3705                 nx_bsd_set_errno(EDESTADDRREQ);
3706 
3707                 /* Return error code.  */
3708                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3709                 return(NX_SOC_ERROR);
3710             }
3711 
3712             sockaddr_dest.sll_family = AF_PACKET;
3713             sockaddr_dest.sll_ifindex = (INT)bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index;
3714             return(_nx_bsd_hardware_internal_sendto(bsd_socket_ptr, (CHAR *)msg, msgLength, flags, (struct nx_bsd_sockaddr*)&sockaddr_dest, sizeof(struct nx_bsd_sockaddr_ll)));
3715         }
3716 
3717 #endif /* defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT) */
3718 
3719         /* However if the socket is raw socket and HDR_INCLUDE is set, it is OK. */
3720         if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE))
3721         {
3722             /* Set the socket error */
3723             nx_bsd_set_errno(ENOTCONN);
3724 
3725             /* Return an error status.*/
3726             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3727             return(NX_SOC_ERROR);
3728         }
3729     }
3730 
3731     return nx_bsd_send_internal(sockID, msg, msgLength, flags,
3732                                 &bsd_socket_ptr -> nx_bsd_socket_peer_ip,
3733                                 bsd_socket_ptr -> nx_bsd_socket_peer_port,
3734                                 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index);
3735 
3736 }
3737 
3738 
3739 /**************************************************************************/
3740 /*                                                                        */
3741 /*  FUNCTION                                               RELEASE        */
3742 /*                                                                        */
3743 /*    sendto                                              PORTABLE C      */
3744 /*                                                           6.3.0        */
3745 /*  AUTHOR                                                                */
3746 /*                                                                        */
3747 /*    Yuxin Zhou, Microsoft Corporation                                   */
3748 /*                                                                        */
3749 /*  DESCRIPTION                                                           */
3750 /*                                                                        */
3751 /*    This function sends a packet out the given socket.                  */
3752 /*    When the call returns, the data has been queued for transmission    */
3753 /*    over the connection. To use sendto on a TCP BSD socket, the         */
3754 /*    socket must already be in connected state.                          */
3755 /*                                                                        */
3756 /*    The flags argument is provided for consistency with the BSD send    */
3757 /*    service. It allows various protocol features, such as out-of-bound  */
3758 /*    out-of-bound data, to be accessed. However, none of these features  */
3759 /*    are implemented.                                                    */
3760 /*                                                                        */
3761 /*  INPUT                                                                 */
3762 /*                                                                        */
3763 /*    sockID                                Socket (must be connected).   */
3764 /*    msg                                   Data to transmit.             */
3765 /*    msgLength                             Number of bytes to send       */
3766 /*    flags                                 Control flags, support        */
3767 /*                                            MSG_DONTWAIT                */
3768 /*    sockaddr                              Destination address           */
3769 /*    destAddrLen                           Length of destination address */
3770 /*                                                                        */
3771 /*  OUTPUT                                                                */
3772 /*                                                                        */
3773 /*    Number of bytes sent                  If no error occurs            */
3774 /*    NX_SOC_ERROR (-1)                     In case of socket error       */
3775 /*                                                                        */
3776 /*  CALLS                                                                 */
3777 /*                                                                        */
3778 /*    bind                                 Bind NetX UDP sockets          */
3779 /*    nx_packet_allocate                   Get a free packet              */
3780 /*    nx_packet_data_append                Copy data into packet          */
3781 /*    nx_packet_release                    Free the nx_packet used        */
3782 /*    nx_tcp_socket_send                   Send packet over a TCP Socket  */
3783 /*    nx_udp_socket_send                   Send packet over a UDP Socket  */
3784 /*    tx_mutex_get                         Get protection                 */
3785 /*    tx_mutex_put                         Release protection             */
3786 /*                                                                        */
3787 /*  CALLED BY                                                             */
3788 /*                                                                        */
3789 /*    Application Code                                                    */
3790 /*                                                                        */
3791 /*  RELEASE HISTORY                                                       */
3792 /*                                                                        */
3793 /*    DATE              NAME                      DESCRIPTION             */
3794 /*                                                                        */
3795 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
3796 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
3797 /*                                            resulting in version 6.1    */
3798 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
3799 /*                                            used new API/structs naming,*/
3800 /*                                            resulting in version 6.3.0  */
3801 /*                                                                        */
3802 /**************************************************************************/
nx_bsd_sendto(INT sockID,CHAR * msg,INT msgLength,INT flags,struct nx_bsd_sockaddr * destAddr,INT destAddrLen)3803 INT  nx_bsd_sendto(INT sockID, CHAR *msg, INT msgLength, INT flags,  struct nx_bsd_sockaddr *destAddr, INT destAddrLen)
3804 {
3805 UINT                 status;
3806 NX_BSD_SOCKET       *bsd_socket_ptr;
3807 NXD_ADDRESS          peer_ip_address;
3808 USHORT               peer_port = 0;
3809 
3810     /* Check for a valid socket ID.  */
3811     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
3812     {
3813 
3814         /* Set the socket error if extended options enabled. */
3815         nx_bsd_set_errno(EBADF);
3816 
3817         /* Return an error status. */
3818         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3819         return(NX_SOC_ERROR);
3820     }
3821 
3822     /* Set up a socket pointer to the BSD socket.  */
3823     bsd_socket_ptr =  &nx_bsd_socket_array[sockID - NX_BSD_SOCKFD_START];
3824 
3825     /* If the socket has an error */
3826     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
3827     {
3828         INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
3829 
3830         /* Now clear the error code. */
3831         bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
3832 
3833         /* Clear the error flag.  The application is expected to close the socket at this point.*/
3834         bsd_socket_ptr -> nx_bsd_socket_status_flags =
3835             bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
3836 
3837         nx_bsd_set_errno(errcode);
3838 
3839         /* Return an error.  */
3840         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3841 
3842         /* At this point the error flag is cleared.  Application should
3843            detect and handle the error codition. This socket is still bound
3844            to the port (either the application called bind(), or a bind
3845            operation was executed as part of the connect call) is able to
3846            handle another "connect" call, or be closed. */
3847         return(NX_SOC_ERROR);
3848     }
3849     /* For TCP, make sure the socket is already connected. */
3850     if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
3851     {
3852         if((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED) == 0)
3853         {
3854             nx_bsd_set_errno(ENOTCONN);
3855 
3856             /* Return an error.  */
3857             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3858 
3859             return(NX_SOC_ERROR);
3860         }
3861         return nx_bsd_send_internal((sockID - NX_BSD_SOCKFD_START), msg, msgLength, flags, NX_NULL, 0,
3862                                     bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index);
3863     }
3864     else
3865     {
3866 
3867         /* This is a UDP or raw socket.  */
3868 
3869         /* Check whther or not the socket is AF_PACKET family. */
3870         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
3871         {
3872 
3873 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
3874             /* nx_bsd_pppoe_internal_sendto shall returns */
3875             status = (UINT)nx_bsd_pppoe_internal_sendto(bsd_socket_ptr, msg, msgLength, flags,  destAddr, destAddrLen);
3876 #elif defined(NX_BSD_RAW_SUPPORT)
3877             /* _nx_bsd_hardware_internal_sendto shall returns */
3878             status = (UINT)_nx_bsd_hardware_internal_sendto(bsd_socket_ptr, msg, msgLength, flags,  destAddr, destAddrLen);
3879 #else
3880             NX_PARAMETER_NOT_USED(destAddrLen);
3881             status = (UINT)NX_SOC_ERROR;
3882 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
3883             return((INT)status);
3884 
3885         }
3886 
3887         /* Perform error checkings on the remote address if the socket is
3888            not raw socket, or HDRINCL is not set for the raw socket. */
3889         if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE))
3890         {
3891 
3892             /* Check for an invalid destination. */
3893             if (destAddr == NX_NULL)
3894             {
3895 
3896                 /* Set the socket error if extended socket options enabled. */
3897                 nx_bsd_set_errno(EINVAL);
3898 
3899                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3900                 return(NX_SOC_ERROR);
3901             }
3902 
3903             /* Validate the destination address. */
3904             if(bsd_socket_ptr -> nx_bsd_socket_family != destAddr -> sa_family)
3905             {
3906                 nx_bsd_set_errno(EAFNOSUPPORT);
3907 
3908                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3909 
3910                 return(NX_SOC_ERROR);
3911             }
3912         }
3913 
3914         /* For UDP socket, make sure the socket is bound. */
3915         if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
3916         {
3917             if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND))
3918             {
3919                 status = nx_udp_socket_bind(bsd_socket_ptr -> nx_bsd_socket_udp_socket, NX_ANY_PORT, NX_NO_WAIT);
3920                 if((status != NX_SUCCESS) && (status != NX_ALREADY_BOUND))
3921                 {
3922                     nx_bsd_set_errno(EINVAL);
3923 
3924                     NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3925 
3926                     return(NX_SOC_ERROR);
3927                 }
3928 
3929                 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
3930                 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
3931                 bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)(bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_port);
3932                 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
3933             }
3934 
3935         }
3936 
3937 
3938 
3939         if(destAddr)
3940         {
3941             /* Get the destination IP and port for this UDP socket.  */
3942 #ifndef NX_DISABLE_IPV4
3943             if (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
3944             {
3945 
3946                 /* This is for an IPv4 packet. */
3947                 peer_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
3948                 peer_ip_address.nxd_ip_address.v4 = htonl(((struct nx_bsd_sockaddr_in *) destAddr) -> sin_addr.s_addr);
3949                 peer_port = htons(((struct nx_bsd_sockaddr_in *) destAddr) -> sin_port);
3950 
3951                 /* Local interface ID is set to invalid value, so the send routine needs to
3952                    find the best interface to send the packet based on destination IP address. */
3953 
3954             }
3955 #endif /* NX_DISABLE_IPV4 */
3956 #ifdef FEATURE_NX_IPV6
3957             if (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
3958             {
3959 
3960                 /* This is for an IPv6 packet. Set the NetX Duo IP address version. */
3961                 peer_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
3962 
3963                 peer_ip_address.nxd_ip_address.v6[0] = ntohl(((struct nx_bsd_sockaddr_in6*)destAddr) -> sin6_addr._S6_un._S6_u32[0]);
3964                 peer_ip_address.nxd_ip_address.v6[1] = ntohl(((struct nx_bsd_sockaddr_in6*)destAddr) -> sin6_addr._S6_un._S6_u32[1]);
3965                 peer_ip_address.nxd_ip_address.v6[2] = ntohl(((struct nx_bsd_sockaddr_in6*)destAddr) -> sin6_addr._S6_un._S6_u32[2]);
3966                 peer_ip_address.nxd_ip_address.v6[3] = ntohl(((struct nx_bsd_sockaddr_in6*)destAddr) -> sin6_addr._S6_un._S6_u32[3]);
3967 
3968                 peer_port = htons(((struct nx_bsd_sockaddr_in6 *) destAddr) -> sin6_port);
3969 
3970             }
3971 #endif
3972         }
3973 
3974         /* Call the internal send routine to finish the send process. */
3975         /* Local interface ID is set to a special marker, so the send routine needs to
3976            find the best interface to send the packet based on destination IP address. */
3977         return nx_bsd_send_internal((sockID - NX_BSD_SOCKFD_START), msg, msgLength, flags,
3978                                     &peer_ip_address, peer_port,
3979                                     bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index);
3980 
3981     }
3982 }
3983 
3984 
3985 /**************************************************************************/
3986 /*                                                                        */
3987 /*  FUNCTION                                               RELEASE        */
3988 /*                                                                        */
3989 /*    recv                                                PORTABLE C      */
3990 /*                                                           6.3.0        */
3991 /*  AUTHOR                                                                */
3992 /*                                                                        */
3993 /*    Yuxin Zhou, Microsoft Corporation                                   */
3994 /*                                                                        */
3995 /*  DESCRIPTION                                                           */
3996 /*                                                                        */
3997 /*    This function copies up to a specified number of bytes received on  */
3998 /*    the socket into specified location. The given socket must be in the */
3999 /*    connected state. Normally, the call blocks until either at least one*/
4000 /*    byte is returned or the connection closes.The return value indicates*/
4001 /*    the number of bytes actually copied into the buffer starting at the */
4002 /*    specified location.                                                 */
4003 /*                                                                        */
4004 /*    For a stream socket, the bytes are delivered in the same order as   */
4005 /*    they were transmitted, without omissions. For a datagram socket,    */
4006 /*    each recv() returns the data from at most one send(), and order is  */
4007 /*    not necessarily preserved.                                          */
4008 /*                                                                        */
4009 /*    For non blocking sockets, a receive status of NX_NO_PACKET from NetX*/
4010 /*    results in an error status returned from BSD, and the socket error  */
4011 /*    set to EWOULDBLOCK (if BSD extended socket features are enabled.    */
4012 /*                                                                        */
4013 /*    Likewise, an event flag status of TX_NO_EVENTS returned from ThreadX*/
4014 /*    on a non blocking socket sets the socket error to EWOULDBLOCK.      */
4015 /*                                                                        */
4016 /*  INPUT                                                                 */
4017 /*                                                                        */
4018 /*    sockID                                Socket (must be connected).   */
4019 /*    rcvBuffer                             Pointer to put data received. */
4020 /*    bufferLength                          Maximum bytes in buffer       */
4021 /*    flags                                 Control flags, support        */
4022 /*                                            MSG_PEEK and MSG_DONTWAIT   */
4023 /*                                                                        */
4024 /*  OUTPUT                                                                */
4025 /*                                                                        */
4026 /*    Number of bytes received              If success                    */
4027 /*    NX_SOC_ERROR (-1)                     If failure                    */
4028 /*    0                                     socket disconnected           */
4029 /*                                                                        */
4030 /*  CALLS                                                                 */
4031 /*                                                                        */
4032 /*    nx_bsd_recv_internal                  Actual receive function       */
4033 /*                                                                        */
4034 /*  CALLED BY                                                             */
4035 /*                                                                        */
4036 /*    Application Code                                                    */
4037 /*                                                                        */
4038 /*  RELEASE HISTORY                                                       */
4039 /*                                                                        */
4040 /*    DATE              NAME                      DESCRIPTION             */
4041 /*                                                                        */
4042 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4043 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
4044 /*                                            verified memcpy use cases,  */
4045 /*                                            resulting in version 6.1    */
4046 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
4047 /*                                            used new API/structs naming,*/
4048 /*                                            resulting in version 6.3.0  */
4049 /*                                                                        */
4050 /**************************************************************************/
nx_bsd_recv(INT sockID,VOID * rcvBuffer,INT bufferLength,INT flags)4051 INT  nx_bsd_recv(INT sockID, VOID *rcvBuffer, INT bufferLength, INT flags)
4052 {
4053 
4054 struct nx_bsd_iovec iov;
4055 
4056     iov.iov_base = rcvBuffer;
4057     iov.iov_len = (size_t)bufferLength;
4058 
4059     /* Call the recv_internal() function. */
4060     return nx_bsd_recv_internal(sockID, &iov, 1, flags, NX_NULL, NX_NULL);
4061 }
4062 
4063 
4064 /**************************************************************************/
4065 /*                                                                        */
4066 /*  FUNCTION                                               RELEASE        */
4067 /*                                                                        */
4068 /*    recvfrom                                            PORTABLE C      */
4069 /*                                                           6.4.0        */
4070 /*  AUTHOR                                                                */
4071 /*                                                                        */
4072 /*    Yuxin Zhou, Microsoft Corporation                                   */
4073 /*                                                                        */
4074 /*  DESCRIPTION                                                           */
4075 /*                                                                        */
4076 /*    This function copies up to a specified number of bytes, received on */
4077 /*    the socket into a specified location. To use recvfrom() on a TCP    */
4078 /*    socket requires the socket to be in the connected state.            */
4079 /*                                                                        */
4080 /*    This function is identical to recv() except for returning the sender*/
4081 /*    address and length if non null arguments are supplied.              */
4082 /*                                                                        */
4083 /*  INPUT                                                                 */
4084 /*                                                                        */
4085 /*    sockID                                Socket(must be connected)     */
4086 /*    buffer                                Pointer to hold data received */
4087 /*    bufferSize                            Maximum number of bytes       */
4088 /*    flags                                 Control flags, support        */
4089 /*                                            MSG_PEEK and MSG_DONTWAIT   */
4090 /*    fromAddr                              Address data of sender        */
4091 /*    fromAddrLen                           Length of address structure   */
4092 /*                                                                        */
4093 /*  OUTPUT                                                                */
4094 /*                                                                        */
4095 /*    number of bytes received              If no error occurs            */
4096 /*    NX_SOC_ERROR (-1)                     In case of any error          */
4097 /*                                                                        */
4098 /*  CALLS                                                                 */
4099 /*                                                                        */
4100 /*    nx_bsd_recv_internal                  Actual receive function       */
4101 /*                                                                        */
4102 /*  CALLED BY                                                             */
4103 /*                                                                        */
4104 /*    Application Code                                                    */
4105 /*                                                                        */
4106 /*  RELEASE HISTORY                                                       */
4107 /*                                                                        */
4108 /*    DATE              NAME                      DESCRIPTION             */
4109 /*                                                                        */
4110 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4111 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
4112 /*                                            verified memcpy use cases,  */
4113 /*                                            resulting in version 6.1    */
4114 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
4115 /*                                            used new API/structs naming,*/
4116 /*                                            resulting in version 6.3.0  */
4117 /*  12-31-2023     Yanwu Cai                Modified comment(s), and      */
4118 /*                                            added nx_bsd_recv_internal, */
4119 /*                                            resulting in version 6.4.0  */
4120 /*                                                                        */
4121 /**************************************************************************/
nx_bsd_recvfrom(INT sockID,CHAR * rcvBuffer,INT bufferLength,INT flags,struct nx_bsd_sockaddr * fromAddr,INT * fromAddrLen)4122 INT  nx_bsd_recvfrom(INT sockID, CHAR *rcvBuffer, INT bufferLength, INT flags, struct nx_bsd_sockaddr *fromAddr, INT *fromAddrLen)
4123 {
4124 struct nx_bsd_iovec iov;
4125 
4126     iov.iov_base = rcvBuffer;
4127     iov.iov_len = (size_t)bufferLength;
4128 
4129     /* Call the recv_internal() function. */
4130     return nx_bsd_recv_internal(sockID, &iov, 1, flags, fromAddr, fromAddrLen);
4131 }
4132 
4133 /**************************************************************************/
4134 /*                                                                        */
4135 /*  FUNCTION                                               RELEASE        */
4136 /*                                                                        */
4137 /*    recvmsg                                             PORTABLE C      */
4138 /*                                                           6.4.0        */
4139 /*  AUTHOR                                                                */
4140 /*                                                                        */
4141 /*    Yanwu Cai, Microsoft Corporation                                    */
4142 /*                                                                        */
4143 /*  DESCRIPTION                                                           */
4144 /*                                                                        */
4145 /*    This function copies up to a specified number of bytes, received on */
4146 /*    the socket into a specified location. To use recvmsg() on a TCP     */
4147 /*    socket requires the socket to be in the connected state.            */
4148 /*                                                                        */
4149 /*  INPUT                                                                 */
4150 /*                                                                        */
4151 /*    sockID                                Socket(must be connected)     */
4152 /*    msg                                   Pointer to hold msghdr struct */
4153 /*    flags                                 Control flags, support        */
4154 /*                                            MSG_PEEK and MSG_DONTWAIT   */
4155 /*                                                                        */
4156 /*  OUTPUT                                                                */
4157 /*                                                                        */
4158 /*    number of bytes received              If no error occurs            */
4159 /*    NX_SOC_ERROR (-1)                     In case of any error          */
4160 /*                                                                        */
4161 /*  CALLS                                                                 */
4162 /*                                                                        */
4163 /*    nx_bsd_recv_internal                  Actual receive function       */
4164 /*                                                                        */
4165 /*  CALLED BY                                                             */
4166 /*                                                                        */
4167 /*    Application Code                                                    */
4168 /*                                                                        */
4169 /*  RELEASE HISTORY                                                       */
4170 /*                                                                        */
4171 /*    DATE              NAME                      DESCRIPTION             */
4172 /*                                                                        */
4173 /*  12-31-2023     Yanwu Cai                Initial Version 6.4.0         */
4174 /*                                                                        */
4175 /**************************************************************************/
nx_bsd_recvmsg(INT sockID,struct nx_bsd_msghdr * msg,INT flags)4176 INT nx_bsd_recvmsg(INT sockID, struct nx_bsd_msghdr *msg, INT flags)
4177 {
4178 INT fromAddrLen = 0;
4179 
4180     if (msg -> msg_name != NX_NULL)
4181     {
4182         fromAddrLen = (INT)(msg -> msg_namelen);
4183     }
4184 
4185     return(nx_bsd_recv_internal(sockID, msg -> msg_iov, msg -> msg_iovlen, flags, (struct nx_bsd_sockaddr *)(msg -> msg_name), &fromAddrLen));
4186 }
4187 
4188 /**************************************************************************/
4189 /*                                                                        */
4190 /*  FUNCTION                                               RELEASE        */
4191 /*                                                                        */
4192 /*    recv_internal                                       PORTABLE C      */
4193 /*                                                           6.4.0        */
4194 /*  AUTHOR                                                                */
4195 /*                                                                        */
4196 /*    Yanwu Cai, Microsoft Corporation                                    */
4197 /*                                                                        */
4198 /*  DESCRIPTION                                                           */
4199 /*                                                                        */
4200 /*    This function copies up to a specified number of bytes received on  */
4201 /*    the socket into specified location. The given socket must be in the */
4202 /*    connected state. Normally, the call blocks until either at least one*/
4203 /*    byte is returned or the connection closes.The return value indicates*/
4204 /*    the number of bytes actually copied into the buffer starting at the */
4205 /*    specified location.                                                 */
4206 /*                                                                        */
4207 /*    For a stream socket, the bytes are delivered in the same order as   */
4208 /*    they were transmitted, without omissions. For a datagram socket,    */
4209 /*    each recv() returns the data from at most one send(), and order is  */
4210 /*    not necessarily preserved.                                          */
4211 /*                                                                        */
4212 /*    For non blocking sockets, a receive status of NX_NO_PACKET from NetX*/
4213 /*    results in an error status returned from BSD, and the socket error  */
4214 /*    set to EWOULDBLOCK (if BSD extended socket features are enabled.    */
4215 /*                                                                        */
4216 /*    Likewise, an event flag status of TX_NO_EVENTS returned from ThreadX*/
4217 /*    on a non blocking socket sets the socket error to EWOULDBLOCK.      */
4218 /*                                                                        */
4219 /*  INPUT                                                                 */
4220 /*                                                                        */
4221 /*    sockID                                Socket (must be connected).   */
4222 /*    iov                                   Pointer to iovec struct.      */
4223 /*    iovlen                                Number of iov elements        */
4224 /*    flags                                 Control flags, support        */
4225 /*                                            MSG_PEEK and MSG_DONTWAIT   */
4226 /*    fromAddr                              Address data of sender        */
4227 /*    fromAddrLen                           Length of address structure   */
4228 /*                                                                        */
4229 /*  OUTPUT                                                                */
4230 /*                                                                        */
4231 /*    Number of bytes received              If success                    */
4232 /*    NX_SOC_ERROR (-1)                     If failure                    */
4233 /*    0                                     socket disconnected           */
4234 /*                                                                        */
4235 /*  CALLS                                                                 */
4236 /*                                                                        */
4237 /*    nx_tcp_socket_receive                 Receive a Packet              */
4238 /*    nx_packet_allocate                    Allocate packet for receive   */
4239 /*    nx_packet_release                     Free the nx_packet after use  */
4240 /*    nx_packet_data_extract_offset         Retrieve packet data          */
4241 /*    tx_event_flags_get                    Wait for data to arrive       */
4242 /*    tx_mutex_get                          Get protection                */
4243 /*    tx_mutex_put                          Release protection            */
4244 /*                                                                        */
4245 /*  CALLED BY                                                             */
4246 /*                                                                        */
4247 /*    recv                                                                */
4248 /*    recvmsg                                                             */
4249 /*    recvfrom                                                            */
4250 /*                                                                        */
4251 /*  RELEASE HISTORY                                                       */
4252 /*                                                                        */
4253 /*    DATE              NAME                      DESCRIPTION             */
4254 /*                                                                        */
4255 /*  12-31-2023     Yanwu Cai                Initial Version 6.4.0         */
4256 /*                                                                        */
4257 /**************************************************************************/
nx_bsd_recv_internal(INT sockID,struct nx_bsd_iovec * iov,size_t iovlen,INT flags,struct nx_bsd_sockaddr * fromAddr,INT * fromAddrLen)4258 static INT nx_bsd_recv_internal(INT sockID, struct nx_bsd_iovec *iov, size_t iovlen, INT flags, struct nx_bsd_sockaddr *fromAddr, INT *fromAddrLen)
4259 {
4260 UINT                 status;
4261 NX_PACKET           *packet_ptr;
4262 NX_BSD_SOCKET       *bsd_socket_ptr;
4263 NX_TCP_SOCKET       *tcp_socket_ptr;
4264 ULONG                requested_events;
4265 ULONG                bytes_received;
4266 ULONG                bytes_copied;
4267 ULONG                buffer_used = 0;
4268 UINT                 wait_option;
4269 UINT                 remaining_wait_option;
4270 ULONG                offset;
4271 UINT                 header_size = 0;
4272 ULONG                start_time = nx_bsd_system_clock;
4273 #ifndef NX_DISABLE_IPV4
4274 struct nx_bsd_sockaddr_in
4275                      peer4_address;
4276 #endif /* NX_DISABLE_IPV4 */
4277 #ifdef FEATURE_NX_IPV6
4278 struct nx_bsd_sockaddr_in6
4279                      peer6_address;
4280 #endif
4281 
4282 
4283     /* Check for a valid socket ID.  */
4284     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
4285     {
4286 
4287         /* Set the socket error if extended options enabled. */
4288         nx_bsd_set_errno(EBADF);
4289 
4290         /* Return an error.  */
4291         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4292 
4293         return(NX_SOC_ERROR);
4294     }
4295 
4296     /* Normalize the socket ID.  */
4297     sockID =  sockID - NX_BSD_SOCKFD_START;
4298 
4299     /* Set up a pointer to the socket.  */
4300     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
4301 
4302     /* Set the receive wait time to FOREVER for blocking sockets. */
4303     wait_option = NX_WAIT_FOREVER;
4304 
4305     /* Is this a nonblocking socket?:  */
4306     if ((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING) ||
4307         (flags & MSG_DONTWAIT))
4308     {
4309 
4310         /* Yes, set to receive wait option to no wait (zero). */
4311         wait_option = 0;
4312     }
4313     /* Does this socket have a receive timeout option set? */
4314     else if (bsd_socket_ptr -> nx_bsd_option_receive_timeout)
4315     {
4316 
4317         /* Yes, this is our wait option. */
4318         wait_option = bsd_socket_ptr -> nx_bsd_option_receive_timeout;
4319     }
4320 
4321     /* Get the protection mutex.  */
4322     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
4323 
4324     /* Check the status.  */
4325     if (status)
4326     {
4327 
4328         /* Set the socket error if extended socket options enabled. */
4329         nx_bsd_set_errno(EACCES);
4330 
4331         /* Return an error. */
4332         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
4333         return(NX_SOC_ERROR);
4334     }
4335 
4336     /* If the socket has an error */
4337     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
4338     {
4339 
4340         INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
4341 
4342         /* Now clear the error code. */
4343         bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
4344 
4345         /* Clear the error flag.  The application is expected to close the socket at this point.*/
4346         bsd_socket_ptr -> nx_bsd_socket_status_flags =
4347             bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
4348 
4349         nx_bsd_set_errno(errcode);
4350 
4351         /* Release the protection mutex.  */
4352         tx_mutex_put(nx_bsd_protection_ptr);
4353 
4354         /* Return an error.  */
4355         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4356 
4357         /* At this point the error flag is cleared.  The application should
4358            detect and handle the error codition. This socket is still bound
4359            to the port (either the application called bind(), or a bind
4360            operation was executed as part of the connect call) and is able to
4361            handle another "connect" call, or be closed. */
4362         return(NX_SOC_ERROR);
4363     }
4364 
4365     /* Set pointers to the BSD NetX Duo sockets.  */
4366     tcp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
4367 
4368     /* Loop to check for a received packet.  */
4369     do
4370     {
4371 
4372         /* Is the socket still in use?  */
4373         if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
4374         {
4375 
4376             /* Set the socket error if extended options enabled. */
4377             nx_bsd_set_errno(EBADF);
4378 
4379             /* Release the protection mutex.  */
4380             tx_mutex_put(nx_bsd_protection_ptr);
4381 
4382             /* Return an error.  */
4383             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4384             return(NX_SOC_ERROR);
4385         }
4386 
4387         /* Check if the BSD socket already has received a packet.  */
4388         packet_ptr =  bsd_socket_ptr -> nx_bsd_socket_received_packet;
4389 
4390         if (packet_ptr)
4391         {
4392 
4393             /* Got one. Break out of the loop.  */
4394             break;
4395         }
4396 
4397         /* Check if there is an incoming packet on this socket.  */
4398         else
4399         {
4400 
4401             /* Determine if this is a TCP BSD socket.  */
4402             if (tcp_socket_ptr)
4403             {
4404 
4405                 /* It is, check the socket TCP receive queue with a zero wait option (no suspension).  */
4406                 status =  nx_tcp_socket_receive(tcp_socket_ptr, &packet_ptr, TX_NO_WAIT);
4407 
4408                 /* Check for no packet on the queue.  */
4409                 if (status == NX_NOT_CONNECTED)
4410                 {
4411 
4412                     /* Release the protection mutex.  */
4413                     tx_mutex_put(nx_bsd_protection_ptr);
4414 
4415                     /* Is peer shutdown orderly? */
4416                     if ((tcp_socket_ptr -> nx_tcp_socket_state == NX_TCP_CLOSE_WAIT) ||
4417                         (tcp_socket_ptr -> nx_tcp_socket_state >= NX_TCP_CLOSING))
4418                     {
4419 
4420                         /* Yes. Return 0. */
4421                         return(NX_SUCCESS);
4422                     }
4423 
4424                     /* Set the socket status (not really an error).  */
4425                     nx_bsd_set_errno(ENOTCONN);
4426 
4427                     /* Return an error.  */
4428                     NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4429                     return(NX_SOC_ERROR);
4430                 }
4431 
4432                 if (status == NX_SUCCESS)
4433                 {
4434 
4435                     /* Increase the received count. */
4436                     bsd_socket_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
4437                     bsd_socket_ptr -> nx_bsd_socket_received_packet_count++;
4438                 }
4439             }
4440 
4441             /* Have we found a new packet?  */
4442             if ((status == NX_SUCCESS) && (packet_ptr))
4443             {
4444 
4445                 /* Setup the bsd socket with the packet information.  */
4446                 bsd_socket_ptr -> nx_bsd_socket_received_packet =         packet_ptr;
4447                 bsd_socket_ptr -> nx_bsd_socket_received_packet_offset =  0;
4448 
4449                 /* Get out of the loop.  */
4450                 break;
4451             }
4452         }
4453 
4454         /* No packet is available.  */
4455 
4456         /* Release the protection mutex.  */
4457         tx_mutex_put(nx_bsd_protection_ptr);
4458 
4459         /* Calculate remaining wait option. */
4460         remaining_wait_option = (UINT)(wait_option - (nx_bsd_system_clock - start_time));
4461         if (remaining_wait_option > wait_option)
4462         {
4463 
4464             /* Wait option expired. */
4465             status = TX_NO_EVENTS;
4466         }
4467         else
4468         {
4469 
4470             /* Suspend this socket on a RECEIVE event (incoming packet) for the specified wait time.  */
4471             status =  tx_event_flags_get(&nx_bsd_events, NX_BSD_RECEIVE_EVENT, TX_OR_CLEAR, &requested_events, remaining_wait_option);
4472         }
4473 
4474         /* Check for any events. */
4475         if (status == TX_NO_EVENTS)
4476         {
4477 
4478             /* No packets received. */
4479 
4480             /* Set the socket error depending if this is a non blocking socket. */
4481             if ((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING) ||
4482                 (wait_option == NX_WAIT_FOREVER) ||
4483                 (flags & MSG_DONTWAIT))
4484                 nx_bsd_set_errno(EWOULDBLOCK);
4485             else
4486                 nx_bsd_set_errno(EAGAIN);
4487 
4488             /* Return an error.  */
4489             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4490             return(NX_SOC_ERROR);
4491         }
4492         else if (status != TX_SUCCESS)
4493         {
4494 
4495             /* Set the socket error if extended socket options enabled. */
4496             nx_bsd_set_errno(EINVAL);
4497 
4498             /* Return an error.  */
4499             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4500             return(NX_SOC_ERROR);
4501         }
4502 
4503         /* Re-obtain the protection mutex.  */
4504         status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
4505 
4506         /* Check the status.  */
4507         if (status)
4508         {
4509 
4510             /* Set the socket error if extended socket options enabled. */
4511             nx_bsd_set_errno(EACCES);
4512 
4513             /* Return an error.  */
4514             NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
4515             return(NX_SOC_ERROR);
4516         }
4517 
4518         if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
4519         {
4520             /* The socket is no longer in use. */
4521 
4522             /* Set the socket error code. */
4523             nx_bsd_set_errno(EBADF);
4524 
4525             /* Release the protection mutex.  */
4526             tx_mutex_put(nx_bsd_protection_ptr);
4527 
4528             /* Return error code.  */
4529             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4530             return(NX_SOC_ERROR);
4531         }
4532 
4533     } while (1);
4534 
4535     /* At this point, the socket has received a packet.  */
4536 
4537 
4538     /* Obtain sender information for UDP socket. */
4539     if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
4540     {
4541 
4542         /* Get the sender and port from the UDP packet.  */
4543         nxd_udp_source_extract(packet_ptr, &bsd_socket_ptr -> nx_bsd_socket_source_ip_address, (UINT *)&bsd_socket_ptr -> nx_bsd_socket_source_port);
4544     }
4545 
4546 #if defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)
4547     else if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
4548     {
4549 
4550         /* Validate the packet length.  */
4551         if (packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr < 14)
4552         {
4553 
4554             /* Set the socket error if extended socket options enabled. */
4555             nx_bsd_set_errno(EINVAL);
4556 
4557             /* Release the protection mutex.  */
4558             tx_mutex_put(nx_bsd_protection_ptr);
4559 
4560             /* Release the packet.  */
4561             nx_packet_release(packet_ptr);
4562 
4563             /* Return an error.  */
4564             NX_BSD_ERROR(status, __LINE__);
4565             return(NX_SOC_ERROR);
4566         }
4567 
4568         /* Pick up the sender's MAC address. */
4569         bsd_socket_ptr -> nx_bsd_socket_sll_addr[0] = packet_ptr -> nx_packet_prepend_ptr[6];
4570         bsd_socket_ptr -> nx_bsd_socket_sll_addr[1] = packet_ptr -> nx_packet_prepend_ptr[7];
4571         bsd_socket_ptr -> nx_bsd_socket_sll_addr[2] = packet_ptr -> nx_packet_prepend_ptr[8];
4572         bsd_socket_ptr -> nx_bsd_socket_sll_addr[3] = packet_ptr -> nx_packet_prepend_ptr[9];
4573         bsd_socket_ptr -> nx_bsd_socket_sll_addr[4] = packet_ptr -> nx_packet_prepend_ptr[10];
4574         bsd_socket_ptr -> nx_bsd_socket_sll_addr[5] = packet_ptr -> nx_packet_prepend_ptr[11];
4575 
4576         /* Pick up the sender's protocol */
4577         bsd_socket_ptr -> nx_bsd_socket_sll_protocol = (USHORT)((packet_ptr -> nx_packet_prepend_ptr[12] << 8) |
4578                                                                 (packet_ptr -> nx_packet_prepend_ptr[13]));
4579         if (bsd_socket_ptr -> nx_bsd_socket_sll_protocol == 0x8100)
4580         {
4581 
4582             /* Skip VLAN tag. */
4583             bsd_socket_ptr -> nx_bsd_socket_sll_protocol = (USHORT)((packet_ptr -> nx_packet_prepend_ptr[16] << 8) |
4584                                                                     (packet_ptr -> nx_packet_prepend_ptr[17]));
4585         }
4586 
4587         /* Find the IF Index */
4588         bsd_socket_ptr -> nx_bsd_socket_sll_ifindex = packet_ptr -> nx_packet_ip_interface -> nx_interface_index;
4589 
4590     }
4591 #endif /* defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT) */
4592 
4593 
4594 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4595     /* For raw socket, make sure the source address is extracted. */
4596     else if(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET)
4597     {
4598 
4599         /* Get the sender IP address from the raw packet.  */
4600         status = nx_bsd_raw_packet_info_extract(packet_ptr, &(bsd_socket_ptr -> nx_bsd_socket_source_ip_address), NX_NULL);
4601     }
4602 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
4603 
4604     /* Pickup the current offset.  */
4605     offset =  bsd_socket_ptr -> nx_bsd_socket_received_packet_offset;
4606 
4607 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4608     /* Perform extra processing on this packet if it processed as a raw packet. */
4609     if((bsd_socket_ptr -> nx_bsd_socket_family != AF_PACKET) &&
4610        (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET))
4611     {
4612 
4613         if(bsd_socket_ptr -> nx_bsd_socket_status_flags & (NX_BSD_SOCKET_RX_NO_HDR))
4614         {
4615             header_size = 0;
4616         }
4617         else
4618         {
4619 #ifndef NX_DISABLE_IPV4
4620             if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
4621             {
4622 
4623 
4624                 header_size = (UINT)(packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_ip_header);
4625 
4626                 /* Byte-Swap the basic IPv4 header.  The NetX Duo IP receive process does not
4627                    examine the extension header.  Therefore it does not perform byte swap
4628                    on extension headers. */
4629                 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_word_0));
4630                 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_word_1));
4631                 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_word_2));
4632                 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_source_ip));
4633                 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_destination_ip));
4634 
4635             }
4636 #endif /* NX_DISABLE_IPV4 */
4637 #ifdef FEATURE_NX_IPV6
4638             if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
4639             {
4640 
4641                 NX_IPV6_HEADER *ipv6_header_ptr;
4642                 UCHAR           next_header_type;
4643 
4644                 header_size = (UINT)(packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_ip_header);
4645 
4646                 ipv6_header_ptr = (NX_IPV6_HEADER*)packet_ptr -> nx_packet_ip_header;
4647 
4648                 /* Pick up the next header. */
4649                 next_header_type = (ipv6_header_ptr -> nx_ip_header_word_1 >> 8) & 0xFF;
4650 
4651                 NX_CHANGE_ULONG_ENDIAN(ipv6_header_ptr -> nx_ip_header_word_0);
4652                 NX_CHANGE_ULONG_ENDIAN(ipv6_header_ptr -> nx_ip_header_word_1);
4653                 NX_IPV6_ADDRESS_CHANGE_ENDIAN(ipv6_header_ptr -> nx_ip_header_destination_ip);
4654                 NX_IPV6_ADDRESS_CHANGE_ENDIAN(ipv6_header_ptr -> nx_ip_header_source_ip);
4655 
4656                 /* Go through the rest of the IPv6 extension headers. */
4657                 _nxd_bsd_swap_ipv6_extension_headers(packet_ptr, next_header_type);
4658             }
4659 #endif
4660             bytes_copied = 0;
4661             while(iovlen)
4662             {
4663                 if(iov -> iov_len > (header_size - bytes_copied))
4664                 {
4665                     memcpy(iov -> iov_base, (VOID*)((UINT)(packet_ptr -> nx_packet_ip_header) + bytes_copied), (UINT)(header_size - bytes_copied)); /* Use case of memcpy is verified. */
4666                     buffer_used = (header_size - bytes_copied);
4667                     bytes_copied += (header_size - bytes_copied);
4668 
4669                     break;
4670                 }
4671                 else
4672                 {
4673                     memcpy(iov -> iov_base, (VOID*)((UINT)(packet_ptr -> nx_packet_ip_header) + bytes_copied), iov -> iov_len); /* Use case of memcpy is verified. */
4674                     bytes_copied += iov -> iov_len;
4675                     iovlen--;
4676                     iov++;
4677                     buffer_used = 0;
4678                 }
4679             }
4680             header_size = bytes_copied;
4681 
4682         }
4683     }
4684 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
4685 
4686     bytes_copied = 0;
4687     while(iovlen)
4688     {
4689         /* Copy the packet data into the supplied buffer.  */
4690         status =  nx_packet_data_extract_offset(packet_ptr, offset + bytes_copied, (VOID*)((UINT)(iov -> iov_base) + buffer_used), (ULONG) (iov -> iov_len - buffer_used), &bytes_received);
4691 
4692         /* Check for an error.  */
4693         if (status)
4694         {
4695 
4696             /* Set the socket error if extended socket options enabled. */
4697             nx_bsd_set_errno(EINVAL);
4698 
4699             /* Release the protection mutex.  */
4700             tx_mutex_put(nx_bsd_protection_ptr);
4701 
4702             /* Release the packet.  */
4703             nx_packet_release(packet_ptr);
4704 
4705             /* Return an error.  */
4706             NX_BSD_ERROR( status, __LINE__);
4707             return(NX_SOC_ERROR);
4708         }
4709 
4710         bytes_copied += bytes_received;
4711         if (bytes_received < iov -> iov_len - buffer_used)
4712         {
4713             break;
4714         }
4715 
4716         buffer_used = 0;
4717         iovlen--;
4718         iov++;
4719     }
4720 
4721     if((flags & MSG_PEEK) == 0)
4722     {
4723 
4724         /* Calculate the new offset.  */
4725         offset =  offset + bytes_copied;
4726 
4727         /* Determine if all the packet data was consumed.  */
4728         if(packet_ptr -> nx_packet_length <= offset)
4729         {
4730 
4731             bsd_socket_ptr -> nx_bsd_socket_received_packet =  packet_ptr -> nx_packet_queue_next;
4732 
4733             /* Release the packet.  */
4734             nx_packet_release(packet_ptr);
4735 
4736             /* Clear the offset.  */
4737             bsd_socket_ptr -> nx_bsd_socket_received_packet_offset =  0;
4738         }
4739         else if((bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
4740 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
4741                         || (bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
4742 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
4743                )
4744         {
4745 
4746             /* For UDP or raw socket, We extracted as much as can fit in the caller's buffer.
4747                We will discard the remaining bytes. */
4748             bsd_socket_ptr -> nx_bsd_socket_received_packet =  packet_ptr -> nx_packet_queue_next;
4749 
4750             bytes_copied = packet_ptr -> nx_packet_length;
4751 
4752             /* No need to retain the packet.  */
4753             nx_packet_release(packet_ptr);
4754 
4755             /* Clear the offset.  */
4756             bsd_socket_ptr -> nx_bsd_socket_received_packet_offset =  0;
4757         }
4758         else
4759         {
4760 
4761             /* For TCP, the remaining data is saved for the next recv call.
4762                Just update the offset.  */
4763             bsd_socket_ptr -> nx_bsd_socket_received_packet_offset =  offset;
4764         }
4765         bsd_socket_ptr -> nx_bsd_socket_received_byte_count -= bytes_copied;
4766         bsd_socket_ptr -> nx_bsd_socket_received_packet_count--;
4767     }
4768 
4769     /* Release the protection mutex.  */
4770     tx_mutex_put(nx_bsd_protection_ptr);
4771 
4772     /* At this point we did receive a packet. */
4773     /* Supply the sender address if valid pointer is supplied. */
4774     if(fromAddr && (*fromAddrLen != 0))
4775     {
4776 
4777 #ifndef NX_DISABLE_IPV4
4778         /* Handle the IPv4 socket type. */
4779         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
4780         {
4781             /* Update the Client address with socket family, remote host IPv4 address and port.  */
4782             peer4_address.sin_family =      AF_INET;
4783             if(bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
4784             {
4785                 peer4_address.sin_addr.s_addr = htonl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v4);
4786                 peer4_address.sin_port = htons(bsd_socket_ptr -> nx_bsd_socket_peer_port);
4787             }
4788             else
4789             {
4790                 peer4_address.sin_addr.s_addr = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v4);
4791 
4792 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4793                 if(!(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET))
4794 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
4795                     peer4_address.sin_port =    ntohs((USHORT)bsd_socket_ptr -> nx_bsd_socket_source_port);
4796             }
4797             /* Copy the peer address/port info to the ClientAddress.  Truncate if
4798                addressLength is smaller than the size of struct sockaddr_in */
4799             if(*fromAddrLen > (INT)sizeof(struct nx_bsd_sockaddr_in))
4800             {
4801                 *fromAddrLen = sizeof(struct nx_bsd_sockaddr_in);
4802             }
4803             memcpy(fromAddr, &peer4_address, (UINT)(*fromAddrLen)); /* Use case of memcpy is verified. */
4804         }
4805         else
4806 #endif /* NX_DISABLE_IPV4 */
4807 
4808 #ifdef FEATURE_NX_IPV6
4809         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
4810         {
4811             /* Update the Client address with socket family, remote host IPv6 address and port.  */
4812             peer6_address.sin6_family = AF_INET6;
4813 
4814             if(bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
4815             {
4816                 peer6_address.sin6_addr._S6_un._S6_u32[0] = ntohl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[0]);
4817                 peer6_address.sin6_addr._S6_un._S6_u32[1] = ntohl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[1]);
4818                 peer6_address.sin6_addr._S6_un._S6_u32[2] = ntohl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[2]);
4819                 peer6_address.sin6_addr._S6_un._S6_u32[3] = ntohl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[3]);
4820                 peer6_address.sin6_port = ntohs(bsd_socket_ptr -> nx_bsd_socket_peer_port);
4821             }
4822             else
4823             {
4824                 peer6_address.sin6_addr._S6_un._S6_u32[0] = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[0]);
4825                 peer6_address.sin6_addr._S6_un._S6_u32[1] = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[1]);
4826                 peer6_address.sin6_addr._S6_un._S6_u32[2] = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[2]);
4827                 peer6_address.sin6_addr._S6_un._S6_u32[3] = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[3]);
4828 
4829             /* Skip the port data for raw sockets. They do not use them. */
4830 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4831                 if(!(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET))
4832 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
4833                     peer6_address.sin6_port = ntohs((USHORT)bsd_socket_ptr -> nx_bsd_socket_source_port);
4834             }
4835 
4836             if((*fromAddrLen) > (INT)sizeof(peer6_address))
4837             {
4838                 *fromAddrLen = sizeof(peer6_address);
4839             }
4840             memcpy(fromAddr, &peer6_address, (UINT)(*fromAddrLen)); /* Use case of memcpy is verified. */
4841 
4842         }
4843         else
4844 #endif /* !FEATURE_NX_IPV6 */
4845 #if defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT)
4846         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
4847         {
4848             if(*fromAddrLen >= (INT)sizeof(struct nx_bsd_sockaddr_ll))
4849             {
4850                 struct nx_bsd_sockaddr_ll *sockaddr = (struct nx_bsd_sockaddr_ll*)fromAddr;
4851                 INT i;
4852                 sockaddr -> sll_family = AF_PACKET;
4853                 sockaddr -> sll_protocol = bsd_socket_ptr -> nx_bsd_socket_sll_protocol;
4854                 sockaddr -> sll_ifindex = bsd_socket_ptr -> nx_bsd_socket_sll_ifindex;
4855                 sockaddr -> sll_hatype = 0;
4856                 sockaddr -> sll_pkttype = 0;
4857                 sockaddr -> sll_halen = 6;
4858                 for(i = 0; i < 6; i++)
4859                     sockaddr -> sll_addr[i] = bsd_socket_ptr -> nx_bsd_socket_sll_addr[i];
4860                 *fromAddrLen = sizeof(struct nx_bsd_sockaddr_ll);
4861             }
4862 
4863         }
4864         else
4865 #endif
4866         {
4867 
4868             /* Set the socket error if extended socket options enabled. */
4869             nx_bsd_set_errno(EINVAL);
4870 
4871             /* Error, IPv6 support is not enabled.  */
4872             NX_BSD_ERROR(ERROR, __LINE__);
4873             return(ERROR);
4874         }
4875     }
4876 
4877     /* Successful received a packet. Return the number of bytes copied to buffer.  */
4878     return((INT)bytes_copied + (INT)header_size);
4879 }
4880 
4881 
4882 /**************************************************************************/
4883 /*                                                                        */
4884 /*  FUNCTION                                               RELEASE        */
4885 /*                                                                        */
4886 /*    soc_close                                           PORTABLE C      */
4887 /*                                                           6.3.0        */
4888 /*  AUTHOR                                                                */
4889 /*                                                                        */
4890 /*    Yuxin Zhou, Microsoft Corporation                                   */
4891 /*                                                                        */
4892 /*  DESCRIPTION                                                           */
4893 /*                                                                        */
4894 /*    This function terminates communications on the supplied BSD socket. */
4895 /*    The socket is disallowed for further sends and receives. Socket     */
4896 /*    resources such as socket memory are returned to the system.         */
4897 /*                                                                        */
4898 /*    If a socket is enabled with the linger option, that will be used in */
4899 /*    place of the default NX_BSD TIMEOUT for blocking sockets.  Sockets  */
4900 /*    enabled for non blocking have their timeout set for zero. Note that */
4901 /*    a zero wait option results in an immediate shutdown (e.g. send RST) */
4902 /*    unless the NX_DISABLE_RESET_DISCONNECT is not enabled.              */
4903 /*                                                                        */
4904 /*    For BSD applications enabled for disconnect complete notification   */
4905 /*    for TCP sockets, the socket will remain open until NetX notifies us */
4906 /*    that the disconnect is complete.  This allows the host BSD          */
4907 /*    application to perform asynchronous disconnects without having to   */
4908 /*    wait for the disconnect to complete.                                */
4909 /*                                                                        */
4910 /*  INPUT                                                                 */
4911 /*                                                                        */
4912 /*    socketID                                                            */
4913 /*                                                                        */
4914 /*  OUTPUT                                                                */
4915 /*                                                                        */
4916 /*    NX_SOC_OK (0)                         On success                    */
4917 /*    NX_SOC_ERROR (-1)                     On failure                    */
4918 /*                                                                        */
4919 /*  CALLS                                                                 */
4920 /*                                                                        */
4921 /*    memset                                Clear memory                  */
4922 /*    nx_tcp_socket_disconnect              Disconnect a TCP Socket       */
4923 /*    nx_tcp_client_socket_unbind           Unbind the socket             */
4924 /*    nx_tcp_server_socket_unaccept         Unaccept the socket           */
4925 /*    nx_tcp_server_socket_unlisten         Unlisten on a port            */
4926 /*    nx_tcp_socket_delete                  Deletes a TCP Socket          */
4927 /*    nx_udp_socket_unbind                  Unbind a UDP Socket           */
4928 /*    nx_udp_socket_delete                  Deletes a UDP Socket          */
4929 /*    tx_block_release                      Release block for socket      */
4930 /*    tx_mutex_get                          Get protection                */
4931 /*    tx_mutex_put                          Release protection            */
4932 /*                                                                        */
4933 /*  CALLED BY                                                             */
4934 /*                                                                        */
4935 /*    Application Code                                                    */
4936 /*                                                                        */
4937 /*  RELEASE HISTORY                                                       */
4938 /*                                                                        */
4939 /*    DATE              NAME                      DESCRIPTION             */
4940 /*                                                                        */
4941 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
4942 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
4943 /*                                            resulting in version 6.1    */
4944 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
4945 /*                                            used new API/structs naming,*/
4946 /*                                            resulting in version 6.3.0  */
4947 /*                                                                        */
4948 /**************************************************************************/
nx_bsd_soc_close(INT sockID)4949 INT  nx_bsd_soc_close(INT sockID)
4950 {
4951 
4952 NX_BSD_SOCKET       *bsd_socket_ptr;
4953 NX_TCP_SOCKET       *tcp_socket_ptr;
4954 NX_UDP_SOCKET       *udp_socket_ptr;
4955 NX_PACKET           *packet_ptr;
4956 NX_PACKET           *next_packet_ptr;
4957 ULONG                timeout;
4958 INT                  i;
4959 UINT                 counter;
4960 INT                  delete_socket;
4961 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4962 INT                  protocol;
4963 UINT                 index;
4964 #endif
4965 
4966     /* Check for a valid socket ID.  */
4967     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
4968     {
4969 
4970         /* Set the socket error. */
4971         nx_bsd_set_errno(EBADF);
4972 
4973         /* Error, invalid socket ID.  */
4974         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4975         return(NX_SOC_ERROR);
4976     }
4977 
4978     /* Normalize the socket ID.  */
4979     sockID =  sockID - NX_BSD_SOCKFD_START;
4980 
4981     /* Set up a pointer to the BSD socket.  */
4982     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
4983 
4984     /* Get the protection mutex.  */
4985     tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
4986 
4987     /* Is the socket already in use?  */
4988     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
4989     {
4990 
4991         /* No; If the NetX socket associated with this BSD socket been deleted, this is ok. */
4992         if (!bsd_socket_ptr -> nx_bsd_socket_tcp_socket && !bsd_socket_ptr -> nx_bsd_socket_udp_socket)
4993         {
4994 
4995             /* Yes, no further action possible. Release the protection mutex.  */
4996             tx_mutex_put(nx_bsd_protection_ptr);
4997 
4998             return NX_SOC_OK;
4999         }
5000 
5001         /* Otherwise, it is an error if socket not in use anymore.  */
5002 
5003         /* Release the protection mutex.  */
5004         tx_mutex_put(nx_bsd_protection_ptr);
5005 
5006         /* Set the socket error if extended socket options enabled. */
5007         nx_bsd_set_errno(EACCES);
5008 
5009         /* Return error.  */
5010         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5011         return(NX_SOC_ERROR);
5012     }
5013 
5014     /* Set NetX socket pointers.  */
5015     tcp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
5016     udp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_udp_socket;
5017 
5018     /* There is. Flush the queue of all packets. */
5019     packet_ptr = bsd_socket_ptr -> nx_bsd_socket_received_packet;
5020     /* Setup packet pointer to the beginning of the queue.  */
5021     while(packet_ptr)
5022     {
5023         next_packet_ptr = packet_ptr -> nx_packet_queue_next;
5024 
5025         /* Mark it as allocated so it will be released.  */
5026         packet_ptr -> nx_packet_queue_next =  (NX_PACKET *) NX_PACKET_ALLOCATED;
5027 
5028         nx_packet_release(packet_ptr);
5029 
5030         /* Move to the next packet */
5031         packet_ptr = next_packet_ptr;
5032     }
5033 
5034     bsd_socket_ptr -> nx_bsd_socket_received_packet = NX_NULL;
5035     bsd_socket_ptr -> nx_bsd_socket_received_packet_tail = NX_NULL;
5036     bsd_socket_ptr -> nx_bsd_socket_received_byte_count = 0;
5037     bsd_socket_ptr -> nx_bsd_socket_received_packet_count = 0;
5038     bsd_socket_ptr -> nx_bsd_socket_received_packet_count_max = 0;
5039 
5040     /* Now delete the underlying TCP or UDP socket. */
5041 
5042     /* Is this a TCP socket? */
5043     if (tcp_socket_ptr)
5044     {
5045 
5046         /* If the socket has not been closed, disconnect it. This would be the case
5047            if NetX already closed the socket e.g. a RST packet received before the
5048            host application called this function. */
5049         if (tcp_socket_ptr -> nx_tcp_socket_state != NX_TCP_CLOSED)
5050         {
5051 
5052             /* Disconnect the socket. */
5053 
5054             /* If the disconnect takes more than the timeout option, NetX marks the socket as "closed"
5055                or puts it back to "listen" state. The default value is 1 to emulate an immediate
5056                socket closure without sending a RST packet.  */
5057             timeout = NX_BSD_TCP_SOCKET_DISCONNECT_TIMEOUT;
5058 
5059             /* Release the mutex while disconnecting. */
5060             tx_mutex_put(nx_bsd_protection_ptr);
5061 
5062             nx_tcp_socket_disconnect(tcp_socket_ptr, timeout);
5063 
5064             tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
5065 
5066             /* Verify that the socket is still valid. */
5067             if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
5068             {
5069                 /* The socket is no longer in use. */
5070 
5071                 /* Set the socket error code. */
5072                 nx_bsd_set_errno(EBADF);
5073 
5074                 /* Release the protection mutex.  */
5075                 tx_mutex_put(nx_bsd_protection_ptr);
5076 
5077                 /* Return error code.  */
5078                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5079                 return(NX_SOC_ERROR);
5080             }
5081         }
5082         /* Make sure the socket is unbound, not accepting connections and not bound to a listening port. */
5083         if(tcp_socket_ptr -> nx_tcp_socket_port)
5084         {
5085 
5086             if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CLIENT)
5087             {
5088                 nx_tcp_client_socket_unbind(tcp_socket_ptr);
5089             }
5090             else
5091             {
5092                 nx_tcp_server_socket_unaccept(tcp_socket_ptr);
5093             }
5094 
5095         }
5096 
5097         /* Now we can delete the NetX TCP socket.  */
5098         nx_tcp_socket_delete(tcp_socket_ptr);
5099 
5100         /* Clear the TCP socket structure.  */
5101         memset((VOID *) tcp_socket_ptr, 0, sizeof(NX_TCP_SOCKET));
5102 
5103         /* Release the NetX TCP socket.  */
5104         tx_block_release((VOID *) tcp_socket_ptr);
5105 
5106         /* If this is the master server socket, we need to unaccept the
5107            associated secondary socket. */
5108         if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET)
5109         {
5110 
5111             INT sec_soc_id = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id;
5112 
5113             if(sec_soc_id < NX_BSD_MAX_SOCKETS)
5114             {
5115 
5116                 /* Find whether or not this is the only master socket that is connected to this
5117                    secondary socket. */
5118                 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
5119                 {
5120 
5121                     if(i == sockID)
5122                         continue;
5123 
5124                     if((nx_bsd_socket_array[i].nx_bsd_socket_protocol == NX_PROTOCOL_TCP) &&
5125                        (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) &&
5126                        (nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id == sec_soc_id))
5127                     {
5128                         break;
5129                     }
5130                 }
5131 
5132                 if(i == NX_BSD_MAX_SOCKETS)
5133                 {
5134 
5135                     /* Unaccept and unlisten on the socket/port */
5136                     /* nx_tcp_server_socket_unaccept(tcp_socket_ptr); */
5137                     /* nx_tcp_server_socket_unlisten(nx_bsd_default_ip, tcp_socket_ptr -> nx_tcp_socket_port); */
5138 
5139                     /* Release the secondary socket if there are no more master sockets associated
5140                        with this secondary socket. */
5141 
5142                     tcp_socket_ptr = nx_bsd_socket_array[sec_soc_id].nx_bsd_socket_tcp_socket;
5143 
5144                     /* If the secondary socket has not been closed, disconnect it. This would be the case
5145                        if NetX already closed the master socket. */
5146                     if (tcp_socket_ptr -> nx_tcp_socket_state != NX_TCP_CLOSED)
5147                     {
5148 
5149                         /* Disconnect the socket. */
5150 
5151                         /* If the disconnect takes more than the timeout option, NetX marks the socket as "closed"
5152                            or puts it back to "listen" state. The default value is 1 to emulate an immediate
5153                            socket closure without sending a RST packet.  */
5154                         timeout = NX_BSD_TCP_SOCKET_DISCONNECT_TIMEOUT;
5155 
5156                         /* Release the mutex while disconnecting. */
5157                         tx_mutex_put(nx_bsd_protection_ptr);
5158 
5159                         nx_tcp_socket_disconnect(tcp_socket_ptr, timeout);
5160 
5161                         tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
5162 
5163                         /* Verify that the socket is still valid. */
5164                         if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
5165                         {
5166                             /* The socket is no longer in use. */
5167 
5168                             /* Set the socket error code. */
5169                             nx_bsd_set_errno(EBADF);
5170 
5171                             /* Release the protection mutex.  */
5172                             tx_mutex_put(nx_bsd_protection_ptr);
5173 
5174                             /* Return error code.  */
5175                             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5176                             return(NX_SOC_ERROR);
5177                         }
5178                     }
5179 
5180                     /* Unaccept on the secondary socket. */
5181                     nx_tcp_server_socket_unaccept(tcp_socket_ptr);
5182                     nx_tcp_server_socket_unlisten(nx_bsd_default_ip, tcp_socket_ptr -> nx_tcp_socket_port);
5183                     nx_tcp_socket_delete(tcp_socket_ptr);
5184 
5185                     memset((VOID*)tcp_socket_ptr, 0, sizeof(NX_TCP_SOCKET));
5186                     tx_block_release((VOID*)tcp_socket_ptr);
5187                     memset((VOID*)&(nx_bsd_socket_array[sec_soc_id]), 0, sizeof(NX_BSD_SOCKET));
5188                 }
5189             }
5190         }
5191 
5192         /* Finally Clear the BSD socket structure.  */
5193         memset((VOID *) bsd_socket_ptr, 0, sizeof(NX_BSD_SOCKET));
5194 
5195         tx_mutex_put(nx_bsd_protection_ptr);
5196 
5197         /* Return */
5198         return(NX_SOC_OK);
5199 
5200     }
5201     else if (udp_socket_ptr)
5202     {
5203 
5204         /* A UDP socket needs to be closed.  */
5205 
5206         /* Check whether this is the last BSD socket attached to the NX_UDP_SOCKET */
5207         counter = (UINT)udp_socket_ptr -> nx_udp_socket_reserved_ptr;
5208 
5209         delete_socket = NX_TRUE;
5210         /* Decrease the counter value. */
5211         if(counter & 0xFFFF0000)
5212         {
5213 
5214             counter = ((counter & 0xFFFF0000) - 0x00010000 + (counter & 0x0000FFFF)) & 0xFFFFFFFF;
5215 
5216             udp_socket_ptr -> nx_udp_socket_reserved_ptr = (VOID*)counter;
5217 
5218             if(counter & 0xFFFF0000)
5219             {
5220 
5221                 /* Do not delete this socket. */
5222                 delete_socket = NX_FALSE;
5223 
5224                 /* If the underlying NX_UDP_SOCKET points to this UDP socket, we need to
5225                    reassign a BSD socket to the NX UDP socket. */
5226                 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
5227                 {
5228 
5229                     if((nx_bsd_socket_array[i].nx_bsd_socket_udp_socket == udp_socket_ptr) &&
5230                        (i != sockID))
5231                     {
5232 
5233                         counter = (counter & 0xFFFF0000) + (UINT)i;
5234                         udp_socket_ptr -> nx_udp_socket_reserved_ptr = (VOID*)counter;
5235                         break;
5236                     }
5237                 }
5238 
5239                 if(i == NX_BSD_MAX_SOCKETS)
5240                 {
5241                     delete_socket = NX_TRUE;
5242                 }
5243             }
5244         }
5245 
5246         if(delete_socket == NX_TRUE)
5247         {
5248 
5249             if(udp_socket_ptr -> nx_udp_socket_bound_next)
5250             {
5251                 nx_udp_socket_unbind(udp_socket_ptr);
5252             }
5253 
5254             /* Socket successfully unbound. Now delete the UDP socket.  */
5255             nx_udp_socket_delete(udp_socket_ptr);
5256 
5257             /* Clear the UDP socket block.  */
5258             memset((VOID *) udp_socket_ptr, 0, sizeof(NX_UDP_SOCKET));
5259 
5260             /* Release the NetX UDP socket memory.  */
5261             tx_block_release((VOID *) udp_socket_ptr);
5262         }
5263         else
5264         {
5265             /* Remove this bsd udp socket from the list. */
5266             (bsd_socket_ptr -> nx_bsd_socket_next) -> nx_bsd_socket_previous = bsd_socket_ptr -> nx_bsd_socket_previous;
5267             (bsd_socket_ptr -> nx_bsd_socket_previous) -> nx_bsd_socket_next = bsd_socket_ptr -> nx_bsd_socket_next;
5268         }
5269 
5270         /* Clear the BSD socket block.  */
5271         memset((VOID *) bsd_socket_ptr, 0, sizeof(NX_BSD_SOCKET));
5272 
5273         /* Release the protection mutex.  */
5274         tx_mutex_put(nx_bsd_protection_ptr);
5275 
5276         return(NX_SOC_OK);
5277     }
5278 
5279 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
5280     else if (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET)
5281     {
5282 
5283         /* There is no native NetX Duo raw socket to delete or
5284            port to unbind. So just release the BSD socket memory.  */
5285 
5286         /* Remove this socket from the list. */
5287         protocol = bsd_socket_ptr -> nx_bsd_socket_protocol;
5288 
5289         /* Calculate the hash index in the raw socket protocol table. */
5290         index = (UINT) ((protocol + (protocol >> 8)) & NX_BSD_SOCKET_RAW_PROTOCOL_TABLE_MASK);
5291 
5292         /* Determine if this is the only socket on this list. */
5293         if(bsd_socket_ptr -> nx_bsd_socket_next == bsd_socket_ptr)
5294         {
5295             /* Yes, this is the only socket on the list. */
5296 
5297             /* Clear the list head pointer. */
5298             nx_bsd_socket_raw_protocol_table[index] = NX_NULL;
5299         }
5300         else
5301         {
5302             /* Remove this bsd udp socket from the list. */
5303              (bsd_socket_ptr -> nx_bsd_socket_next) -> nx_bsd_socket_previous = bsd_socket_ptr -> nx_bsd_socket_previous;
5304              (bsd_socket_ptr -> nx_bsd_socket_previous) -> nx_bsd_socket_next = bsd_socket_ptr -> nx_bsd_socket_next;
5305 
5306              /* Determine if the head of the list points to the socket being removed.
5307                 If so, we need to move the head pointer. */
5308              if(nx_bsd_socket_raw_protocol_table[index] == bsd_socket_ptr)
5309              {
5310                  /* Yes, we need to move the list head pointer. */
5311                  nx_bsd_socket_raw_protocol_table[index] = bsd_socket_ptr -> nx_bsd_socket_next;
5312              }
5313         }
5314 
5315         /* Clear the BSD socket block.  */
5316         memset((VOID *) bsd_socket_ptr, 0, sizeof(NX_BSD_SOCKET));
5317 
5318         /* Release the protection mutex.  */
5319         tx_mutex_put(nx_bsd_protection_ptr);
5320 
5321         return(NX_SOC_OK);
5322 
5323     }
5324 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
5325 #if defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT)
5326     else if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
5327     {
5328         /* There is no native NetX Duo raw socket to delete or
5329            port to unbind. So just release the BSD socket memory.  */
5330 
5331         /* Clear the BSD socket block.  */
5332         memset((VOID *) bsd_socket_ptr, 0, sizeof(NX_BSD_SOCKET));
5333 
5334         /* Release the protection mutex.  */
5335         tx_mutex_put(nx_bsd_protection_ptr);
5336 
5337         return(NX_SOC_OK);
5338     }
5339 
5340 #endif /* defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT) */
5341 
5342 
5343 
5344 
5345     /* Unknown socket type or invalid socket. */
5346 
5347     /* Release the protection mutex.  */
5348     tx_mutex_put(nx_bsd_protection_ptr);
5349 
5350     /* Set the socket error if extended socket options enabled. */
5351     nx_bsd_set_errno(EINVAL);
5352 
5353     /* Return error.  */
5354     NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5355     return(NX_SOC_ERROR);
5356 
5357 
5358 
5359 }
5360 
5361 /**************************************************************************/
5362 /*                                                                        */
5363 /*  FUNCTION                                               RELEASE        */
5364 /*                                                                        */
5365 /*    fcntl                                               PORTABLE C      */
5366 /*                                                           6.3.0        */
5367 /*  AUTHOR                                                                */
5368 /*                                                                        */
5369 /*    Yuxin Zhou, Microsoft Corporation                                   */
5370 /*                                                                        */
5371 /*  DESCRIPTION                                                           */
5372 /*                                                                        */
5373 /*    This function performs the requested operation on the file (e.g.    */
5374 /*    socket) descriptor set.  This implementation supports only the set  */
5375 /*    or get flag, and only sets (or clears) the non blocking option.     */
5376 /*                                                                        */
5377 /*  INPUT                                                                 */
5378 /*                                                                        */
5379 /*    sockID                                socket descriptor             */
5380 /*    flag_type                             File description request      */
5381 /*    f_options                             Option(s) to set on the       */
5382 /*                                              specified file (socket)   */
5383 /*                                                                        */
5384 /*  OUTPUT                                                                */
5385 /*                                                                        */
5386 /*    NX_SOC_ERROR                          Errors with request           */
5387 /*    (file descriptor flags)               File descriptor flags         */
5388 /*                                                                        */
5389 /*  CALLS                                                                 */
5390 /*                                                                        */
5391 /*    tx_mutex_get                          Get protection                */
5392 /*    tx_mutex_put                          Release protection            */
5393 /*                                                                        */
5394 /*  CALLED BY                                                             */
5395 /*                                                                        */
5396 /*    Application Code                                                    */
5397 /*                                                                        */
5398 /*  RELEASE HISTORY                                                       */
5399 /*                                                                        */
5400 /*    DATE              NAME                      DESCRIPTION             */
5401 /*                                                                        */
5402 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5403 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5404 /*                                            resulting in version 6.1    */
5405 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
5406 /*                                            used new API/structs naming,*/
5407 /*                                            resulting in version 6.3.0  */
5408 /*                                                                        */
5409 /**************************************************************************/
nx_bsd_fcntl(INT sockID,UINT flag_type,UINT f_options)5410 INT nx_bsd_fcntl(INT sockID, UINT flag_type, UINT f_options)
5411 {
5412 
5413 NX_BSD_SOCKET   *bsd_socket_ptr;
5414 
5415     /* Check for invalid socket ID. */
5416     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
5417     {
5418 
5419         /* Set the socket error if extended options enabled. */
5420         nx_bsd_set_errno(EBADF);
5421 
5422         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5423 
5424         /* Return error status. */
5425         return NX_SOC_ERROR;
5426     }
5427 
5428     /* Normalize the socket ID to our array. */
5429     sockID =  sockID - NX_BSD_SOCKFD_START;
5430 
5431     /* Build pointer to BSD socket structure.  */
5432     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
5433 
5434     if(flag_type == F_SETFL)
5435     {
5436         /* Set the FD flag. */
5437         bsd_socket_ptr -> nx_bsd_file_descriptor_flags = (INT)f_options;
5438 
5439 
5440         /* Are there flags to clear? */
5441         if ((f_options & O_NONBLOCK) == 0)
5442         {
5443             /* Disable the socket for non blocking. */
5444             bsd_socket_ptr -> nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING);
5445         }
5446         else
5447         {
5448             /* Enable the socket for non blocking. */
5449             bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING;
5450         }
5451 
5452         /* All done. Return 0 */
5453         return(0);
5454     }
5455     else if(flag_type == F_GETFL)
5456     {
5457         return(bsd_socket_ptr -> nx_bsd_file_descriptor_flags);
5458     }
5459     /* Flag_type is not the one we support */
5460 
5461     /* Set the socket error if extended socket options enabled. */
5462     nx_bsd_set_errno(EINVAL);
5463 
5464     NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5465 
5466     /* Return error status. */
5467     return NX_SOC_ERROR;
5468 
5469 
5470 
5471 }
5472 
5473 
5474 /**************************************************************************/
5475 /*                                                                        */
5476 /*  FUNCTION                                               RELEASE        */
5477 /*                                                                        */
5478 /*    ioctl                                               PORTABLE C      */
5479 /*                                                           6.4.0        */
5480 /*  AUTHOR                                                                */
5481 /*                                                                        */
5482 /*    Yuxin Zhou, Microsoft Corporation                                   */
5483 /*                                                                        */
5484 /*  DESCRIPTION                                                           */
5485 /*                                                                        */
5486 /*    This function carries out a socket IO service specified by the      */
5487 /*    command.                                                            */
5488 /*                                                                        */
5489 /*  INPUT                                                                 */
5490 /*                                                                        */
5491 /*    sockID                                Socket (must be connected).   */
5492 /*    command                               IO command for ioctl function */
5493 /*    result                                data returned (value)         */
5494 /*                                                                        */
5495 /*  OUTPUT                                                                */
5496 /*                                                                        */
5497 /*    Number of bytes received              If success                    */
5498 /*    NX_SOC_ERROR (-1)                     Error during socket opration  */
5499 /*    NX_SOC_OK (0)                         Successful completion         */
5500 /*                                                                        */
5501 /*  CALLS                                                                 */
5502 /*                                                                        */
5503 /*    nx_tcp_socket_bytes_available         Retreive number of bytes on   */
5504 /*                                               the specified TCP socket */
5505 /*    nx_udp_socket_bytes_available         Retreive number of bytes on   */
5506 /*                                               the specified UDP socket */
5507 /*    tx_mutex_get                          Get protection                */
5508 /*    tx_mutex_put                          Release protection            */
5509 /*                                                                        */
5510 /*  CALLED BY                                                             */
5511 /*                                                                        */
5512 /*    Application Code                                                    */
5513 /*                                                                        */
5514 /*  RELEASE HISTORY                                                       */
5515 /*                                                                        */
5516 /*    DATE              NAME                      DESCRIPTION             */
5517 /*                                                                        */
5518 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5519 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5520 /*                                            resulting in version 6.1    */
5521 /*  03-08-2023     Wenhui Xie               Modified comment(s), corrected*/
5522 /*                                            the result of FIONREAD,     */
5523 /*                                            resulting in version 6.2.1  */
5524 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
5525 /*                                            used new API/structs naming,*/
5526 /*                                            resulting in version 6.3.0  */
5527 /*  12-31-2023     Yanwu Cai                Modified comment(s), and      */
5528 /*                                            added SIOCGIFINDEX and      */
5529 /*                                            SIOCGIFHWADDR commands,     */
5530 /*                                            resulting in version 6.4.0  */
5531 /*                                                                        */
5532 /**************************************************************************/
nx_bsd_ioctl(INT sockID,INT command,INT * result)5533 INT  nx_bsd_ioctl(INT sockID,  INT command, INT *result)
5534 {
5535 
5536 NX_BSD_SOCKET       *bsd_socket_ptr;
5537 NX_TCP_SOCKET       *tcp_socket_ptr;
5538 NX_UDP_SOCKET       *udp_socket_ptr;
5539 UINT                 status;
5540 #ifdef NX_BSD_RAW_SUPPORT
5541 UINT                 i;
5542 struct nx_bsd_ifreq *ifreq;
5543 NX_INTERFACE        *nx_interface;
5544 #endif
5545 
5546     /* Check that the supplied socket ID is valid.  */
5547     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
5548     {
5549 
5550         /* Error, invalid socket ID.  */
5551         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5552         return(NX_SOC_ERROR);
5553     }
5554 
5555     /* Normalize the socket ID.  */
5556     sockID =  sockID - NX_BSD_SOCKFD_START;
5557 
5558     /* Get the protection mutex.  */
5559     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
5560 
5561     /* Check the status.  */
5562     if (status)
5563     {
5564 
5565         /* Error getting the protection mutex.  */
5566         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
5567         return(NX_SOC_ERROR);
5568     }
5569 
5570     /* Set a pointer to the BSD socket.  */
5571     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
5572 
5573     /* Pick up the associated NetX socket pointers.  */
5574     tcp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
5575     udp_socket_ptr =  bsd_socket_ptr -> nx_bsd_socket_udp_socket;
5576 
5577     /* Handle the command. */
5578     switch (command)
5579     {
5580 
5581         case FIONREAD:
5582         {
5583 
5584             /* Check NULL pointer. */
5585             if(result == NX_NULL)
5586             {
5587                 tx_mutex_put(nx_bsd_protection_ptr);
5588 
5589                 nx_bsd_set_errno(EFAULT);
5590 
5591                 /* Error, invalid address. */
5592                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5593 
5594                 return(NX_SOC_ERROR);
5595             }
5596 
5597             /* Determine which socket pointer to use.  */
5598             if (tcp_socket_ptr)
5599             {
5600 
5601                 /* Extract the number of bytes on the TCP receive queue. */
5602                 status = nx_tcp_socket_bytes_available(tcp_socket_ptr, (ULONG *)result);
5603 
5604                 if (status != NX_SUCCESS)
5605                 {
5606 
5607                     tx_mutex_put(nx_bsd_protection_ptr);
5608 
5609                     /* Error in the native NetX call.  */
5610                     NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
5611                     return(NX_SOC_ERROR);
5612                 }
5613                 else
5614                 {
5615                     *result += (INT)(bsd_socket_ptr -> nx_bsd_socket_received_byte_count);
5616             }
5617             }
5618             else if (udp_socket_ptr)
5619             {
5620 
5621                 /* Extract the number of bytes on the UDP receive queue. */
5622                 *result = (INT)(bsd_socket_ptr ->  nx_bsd_socket_received_byte_count);
5623             }
5624 
5625             break;
5626         }
5627 
5628         case FIONBIO:
5629         {
5630 
5631             /* Check NULL pointer. */
5632             if(result == NX_NULL)
5633             {
5634                 tx_mutex_put(nx_bsd_protection_ptr);
5635 
5636                 nx_bsd_set_errno(EFAULT);
5637 
5638                 /* Error, invalid address. */
5639                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5640 
5641                 return(NX_SOC_ERROR);
5642             }
5643 
5644             if(*result == NX_FALSE)
5645             {
5646 
5647                 /* Disable the socket for non blocking. */
5648                 bsd_socket_ptr -> nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING);
5649 
5650                 /* Update the file descriptor with the non blocking bit. */
5651                 bsd_socket_ptr -> nx_bsd_file_descriptor_flags  &= ~O_NONBLOCK;
5652             }
5653             else
5654             {
5655 
5656                 /* Enable the socket for non blocking. */
5657                 bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING;
5658 
5659                 /* Update the file descriptor with the non blocking bit. */
5660                 bsd_socket_ptr -> nx_bsd_file_descriptor_flags  |= O_NONBLOCK;
5661             }
5662 
5663             break;
5664         }
5665 
5666 #ifdef NX_BSD_RAW_SUPPORT
5667         case SIOCGIFINDEX:
5668         {
5669             ifreq = (struct nx_bsd_ifreq*)result;
5670 
5671             for (i = 0; i < NX_MAX_IP_INTERFACES; i++)
5672             {
5673                 if (strncmp(ifreq->ifr_name, nx_bsd_default_ip->nx_ip_interface[i].nx_interface_name, NX_BSD_IFNAMSIZE) == 0)
5674                 {
5675                     break;
5676                 }
5677             }
5678 
5679             if (i == NX_MAX_IP_INTERFACES)
5680             {
5681                 tx_mutex_put(nx_bsd_protection_ptr);
5682 
5683                 /* Did not find a matching interface. */
5684                 nx_bsd_set_errno(EINVAL);
5685 
5686                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5687                 return NX_SOC_ERROR;
5688             }
5689 
5690             ifreq -> ifr_ifindex = (INT)i;
5691 
5692             break;
5693         }
5694 
5695         case SIOCGIFHWADDR:
5696         {
5697             ifreq = (struct nx_bsd_ifreq*)result;
5698 
5699             if (ifreq -> ifr_ifindex < 0 || ifreq -> ifr_ifindex >= NX_MAX_IP_INTERFACES)
5700             {
5701                 tx_mutex_put(nx_bsd_protection_ptr);
5702                 nx_bsd_set_errno(EINVAL);
5703                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5704                 return NX_SOC_ERROR;
5705             }
5706 
5707             nx_interface = &nx_bsd_default_ip -> nx_ip_interface[ifreq -> ifr_ifindex];
5708             if (!(nx_interface -> nx_interface_valid))
5709             {
5710                 tx_mutex_put(nx_bsd_protection_ptr);
5711                 nx_bsd_set_errno(EINVAL);
5712                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5713                 return NX_SOC_ERROR;
5714             }
5715 
5716             ifreq -> ifr_hwaddr.sa_data[0] = (UCHAR)(nx_interface -> nx_interface_physical_address_msw >> 8);
5717             ifreq -> ifr_hwaddr.sa_data[1] = (UCHAR)(nx_interface -> nx_interface_physical_address_msw & 0xFF);
5718             ifreq -> ifr_hwaddr.sa_data[2] = (UCHAR)(nx_interface -> nx_interface_physical_address_lsw >> 24);
5719             ifreq -> ifr_hwaddr.sa_data[3] = (UCHAR)(nx_interface -> nx_interface_physical_address_lsw >> 16);
5720             ifreq -> ifr_hwaddr.sa_data[4] = (UCHAR)(nx_interface -> nx_interface_physical_address_lsw >> 8);
5721             ifreq -> ifr_hwaddr.sa_data[5] = (UCHAR)(nx_interface -> nx_interface_physical_address_lsw & 0xFF);
5722 
5723             break;
5724         }
5725 #endif
5726 
5727         default:
5728 
5729             /* Unhandled command; ignore  */
5730             break;
5731     }
5732 
5733     tx_mutex_put(nx_bsd_protection_ptr);
5734 
5735     return NX_SOC_OK;
5736 }
5737 
5738 /**************************************************************************/
5739 /*                                                                        */
5740 /*  FUNCTION                                               RELEASE        */
5741 /*                                                                        */
5742 /*    inet_ntoa                                           PORTABLE C      */
5743 /*                                                           6.3.0        */
5744 /*  AUTHOR                                                                */
5745 /*                                                                        */
5746 /*    Yuxin Zhou, Microsoft Corporation                                   */
5747 /*                                                                        */
5748 /*  DESCRIPTION                                                           */
5749 /*                                                                        */
5750 /*    This function converts an IP address to a string and returns a      */
5751 /*    pointer to the string.  The caller is recommended to copy the       */
5752 /*    contents of the buffer to local memory since this function and      */
5753 /*    internal buffer can be reused.                                      */
5754 /*                                                                        */
5755 /*  INPUT                                                                 */
5756 /*                                                                        */
5757 /*    address_to_convert                    Struct holding IP address.    */
5758 /*                                                                        */
5759 /*  OUTPUT                                                                */
5760 /*                                                                        */
5761 /*    char *                                Pointer to converted string   */
5762 /*    0x0                                   Error during conversion       */
5763 /*                                                                        */
5764 /*  CALLS                                                                 */
5765 /*                                                                        */
5766 /*    tx_mutex_get                          Get mutex protection          */
5767 /*    bsd_number_convert                    Convert integer to ascii      */
5768 /*                                                                        */
5769 /*  CALLED BY                                                             */
5770 /*                                                                        */
5771 /*    Application Code                                                    */
5772 /*                                                                        */
5773 /*  RELEASE HISTORY                                                       */
5774 /*                                                                        */
5775 /*    DATE              NAME                      DESCRIPTION             */
5776 /*                                                                        */
5777 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5778 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5779 /*                                            resulting in version 6.1    */
5780 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
5781 /*                                            used new API/structs naming,*/
5782 /*                                            resulting in version 6.3.0  */
5783 /*                                                                        */
5784 /**************************************************************************/
nx_bsd_inet_ntoa(struct nx_bsd_in_addr address_to_convert)5785 CHAR *nx_bsd_inet_ntoa(struct nx_bsd_in_addr address_to_convert)
5786 {
5787 UINT status;
5788 
5789     /* Because we are using global buffer space to write out the string, get the protection mutex.  */
5790     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
5791 
5792     if (status != NX_SUCCESS)
5793     {
5794         return NX_NULL;
5795     }
5796 
5797     inet_ntoa_internal(&address_to_convert, nx_bsd_url_buffer, NX_BSD_URL_BUFSIZE);
5798 
5799     tx_mutex_put(nx_bsd_protection_ptr);
5800 
5801     /* Return the start of the string buffer. */
5802     return nx_bsd_url_buffer;
5803 
5804 }
5805 
5806 /**************************************************************************/
5807 /*                                                                        */
5808 /*  FUNCTION                                               RELEASE        */
5809 /*                                                                        */
5810 /*    bsd_number_convert                                  PORTABLE C      */
5811 /*                                                           6.1          */
5812 /*  AUTHOR                                                                */
5813 /*                                                                        */
5814 /*    Yuxin Zhou, Microsoft Corporation                                   */
5815 /*                                                                        */
5816 /*  DESCRIPTION                                                           */
5817 /*                                                                        */
5818 /*    This function converts an integer to a string.                      */
5819 /*                                                                        */
5820 /*  INPUT                                                                 */
5821 /*                                                                        */
5822 /*    number                                Number to convert             */
5823 /*    string                                Pointer to string buffer      */
5824 /*    buffer_len                            Size of the string buffer     */
5825 /*    base                                  the base of the number,       */
5826 /*                                          2,8,10,16                     */
5827 /*                                                                        */
5828 /*  OUTPUT                                                                */
5829 /*                                                                        */
5830 /*    size                                  Size of string buffer         */
5831 /*                                                                        */
5832 /*  CALLS                                                                 */
5833 /*                                                                        */
5834 /*    None                                                                */
5835 /*                                                                        */
5836 /*  CALLED BY                                                             */
5837 /*                                                                        */
5838 /*    Application Code                                                    */
5839 /*                                                                        */
5840 /*  RELEASE HISTORY                                                       */
5841 /*                                                                        */
5842 /*    DATE              NAME                      DESCRIPTION             */
5843 /*                                                                        */
5844 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5845 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5846 /*                                            resulting in version 6.1    */
5847 /*                                                                        */
5848 /**************************************************************************/
bsd_number_convert(UINT number,CHAR * string,ULONG buffer_len,UINT base)5849 UINT  bsd_number_convert(UINT number, CHAR *string, ULONG buffer_len, UINT base)
5850 {
5851 
5852 UINT    j;
5853 UINT    digit;
5854 UINT    size;
5855 
5856 
5857     /* Initialize counters.  */
5858     size =  0;
5859 
5860     /* Loop to convert the number to ASCII.  */
5861     while (size < buffer_len)
5862     {
5863 
5864         /* Shift the current digits over one.  */
5865         for (j = size; j != 0; j--)
5866         {
5867 
5868             /* Move each digit over one place.  */
5869             string[j] =  string[j-1];
5870         }
5871 
5872         /* Compute the next decimal digit.  */
5873         digit =  number % base;
5874 
5875         /* Update the input number.  */
5876         number =  number / base;
5877 
5878         /* Store the new digit in ASCII form.  */
5879         if(digit < 10)
5880             string[0] =  (CHAR) (digit + 0x30);
5881         else
5882             string[0] =  (CHAR) (digit + 0x57);
5883 
5884         /* Increment the size.  */
5885         size++;
5886 
5887         /* Determine if the number is now zero.  */
5888         if (number == 0)
5889             break;
5890     }
5891 
5892     /* Make the string NULL terminated.  */
5893     string[size] =  (CHAR) NX_NULL;
5894 
5895     /* Determine if there is an overflow error.  */
5896     if (number)
5897     {
5898 
5899         /* Error, return bad values to user.  */
5900         size =  0;
5901         string[0] = '0';
5902     }
5903 
5904     /* Return size to caller.  */
5905     return(size);
5906 }
5907 
5908 /**************************************************************************/
5909 /*                                                                        */
5910 /*  FUNCTION                                               RELEASE        */
5911 /*                                                                        */
5912 /*    inet_aton                                           PORTABLE C      */
5913 /*                                                           6.3.0        */
5914 /*  AUTHOR                                                                */
5915 /*                                                                        */
5916 /*    Yuxin Zhou, Microsoft Corporation                                   */
5917 /*                                                                        */
5918 /*  DESCRIPTION                                                           */
5919 /*                                                                        */
5920 /*    This function converts hexadecimal characters into an ASCII IP      */
5921 /*    address representation.                                             */
5922 /*                                                                        */
5923 /*  INPUT                                                                 */
5924 /*                                                                        */
5925 /*    address_buffer_ptr                    String holding the IP address */
5926 /*    addr                                  Struct to store the IP address*/
5927 /*                                                                        */
5928 /*  OUTPUT                                                                */
5929 /*                                                                        */
5930 /*    NX_SUCCESS                            Successful conversion         */
5931 /*    NX_SOC_ERROR                          Error during conversion       */
5932 /*                                                                        */
5933 /*  CALLS                                                                 */
5934 /*                                                                        */
5935 /*    nx_bsd_isdigit                        Indicate char is a number     */
5936 /*    isspace                               Indicate char is a space      */
5937 /*    islower                               Indicate char is lowercase    */
5938 /*    htonl                                 Convert to network byte order */
5939 /*                                                                        */
5940 /*  CALLED BY                                                             */
5941 /*                                                                        */
5942 /*    Application Code                                                    */
5943 /*                                                                        */
5944 /*  RELEASE HISTORY                                                       */
5945 /*                                                                        */
5946 /*    DATE              NAME                      DESCRIPTION             */
5947 /*                                                                        */
5948 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
5949 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
5950 /*                                            resulting in version 6.1    */
5951 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
5952 /*                                            used new API/structs naming,*/
5953 /*                                            resulting in version 6.3.0  */
5954 /*                                                                        */
5955 /**************************************************************************/
nx_bsd_inet_aton(const CHAR * address_buffer_ptr,struct nx_bsd_in_addr * addr)5956 INT nx_bsd_inet_aton(const CHAR *address_buffer_ptr, struct nx_bsd_in_addr *addr)
5957 {
5958 ULONG value;
5959 INT   base = 10, ip_address_index;
5960 UCHAR tempchar;
5961 const UCHAR *buffer_ptr;
5962 UINT  ip_address_number[4];  /* Four discreet numbers in IP address representation. */
5963 UINT *ip_number_ptr;         /* IP address as equivalent ULONG value. */
5964 UINT  dot_flag;
5965 
5966     /* Set local variables. */
5967     buffer_ptr = (const UCHAR *) address_buffer_ptr;
5968     ip_number_ptr = ip_address_number;
5969 
5970     tempchar = *buffer_ptr;
5971 
5972     /* Check for an invalid first character. */
5973     if (nx_bsd_isdigit(tempchar)== NX_FALSE)
5974     {
5975         return (0);
5976     }
5977 
5978     dot_flag = 1;
5979 
5980     /* Parse the rest of the characters from the input number. */
5981     do
5982     {
5983 
5984         /* Initialize the (next) extracted IP address number to zero. */
5985         value = 0;
5986 
5987         if(dot_flag== 1)
5988         {
5989             /* Initialize the numeric base to decimal unless we determine hex or octal. */
5990             base = 10;
5991 
5992             /* Determine which number base the input number buffer is. */
5993             if (*buffer_ptr == '0')
5994             {
5995                 /* Get the next character. */
5996                 buffer_ptr++;
5997 
5998                 /* A leading 0 followed by an 'x' indicates this is hexidecimal. */
5999                 if ((*buffer_ptr== 'x') || (*buffer_ptr == 'X'))
6000                 {
6001                     base = 16;
6002 
6003                     /* Move ahead one character past the leading '0x' */
6004                     buffer_ptr++;
6005                 }
6006                 else
6007                 {
6008                     /* This is octal. */
6009                     base = 8;
6010                     buffer_ptr--;
6011                 }
6012             }
6013         }
6014 
6015         tempchar = *buffer_ptr;
6016 
6017         /* Parse characters making up the next word. */
6018         while (*buffer_ptr != '\0')
6019         {
6020             /* Check if the next character is a decimal or octal digit. */
6021             if (nx_bsd_isdigit(tempchar))
6022             {
6023 
6024                 dot_flag = 0;
6025 
6026                 /* Convert the tempchar character to a number.  Multiply the existing
6027                    number by the base (8 or 10) and this digit to the sum. */
6028                 value = (value * (ULONG)base) + (ULONG)(tempchar - '0');
6029 
6030                 /* Advance the IP address pointer to the next character. */
6031                 buffer_ptr++;
6032 
6033                 /* Get the next character. */
6034                 tempchar = *buffer_ptr;
6035             }
6036             /* Else check if we are expecting a hexidecimal number. */
6037             else if (nx_bsd_isxdigit(tempchar))
6038             {
6039                 /* We are; Verify the base is 16. */
6040                 if(base == 16)
6041                 {
6042 
6043                     /* It is.  handle upper or lower case hex digit. */
6044                     CHAR c = (CHAR)(nx_bsd_islower(tempchar) ? 'a' : 'A');
6045 
6046                     dot_flag = 0;
6047 
6048                     /* Convert the hex character to a hex digit, multiply the existing word by shifting the bits,
6049                        and add this hex digit to the sum. */
6050                     value = (value << 4) + (ULONG)(tempchar + 10 - c);
6051 
6052                     buffer_ptr++;
6053 
6054                     /* Get the next character. */
6055                     tempchar = *buffer_ptr;
6056                 }
6057                 else
6058                 {
6059                     /* Not a valid hex character. */
6060                     return (0);
6061                 }
6062             }
6063             else
6064             {
6065                 /* We have reached a number separator or possibly end of the string.  */
6066                 break;
6067             }
6068         }
6069 
6070         /* At the end of the current word. Is this a separator character? */
6071         if (*buffer_ptr == '.')
6072         {
6073 
6074             dot_flag = 1;
6075 
6076             /* Yes, check for an invalid number (cannot exceed 255 or 0xFF. */
6077             if (value > 0xff)
6078             {
6079                 return (0);
6080             }
6081 
6082             /* Check that the pointer to the last extracted number does not exceed the array holding the IP address numbers. */
6083             if (ip_number_ptr >= (ip_address_number + 3))
6084             {
6085                 return (0);
6086             }
6087 
6088             /* Copy the computed value into the IP address number buffer. */
6089             *ip_number_ptr = value;
6090 
6091             /* Move the pointer to where we will store the next number extracted. */
6092             ip_number_ptr++;
6093 
6094             /* Move to the next character in the IP address string. */
6095             buffer_ptr++;
6096         }
6097         /* Check for non digit or seperator character indicating (maybe) end of the buffer. */
6098         else
6099             break;
6100 
6101     } while (1);
6102 
6103     /* If this is not a null terminating character, check for invalid trailing characters. */
6104     if (*buffer_ptr)
6105     {
6106 
6107         if((*buffer_ptr != '\0') && (!nx_bsd_isspace(*buffer_ptr)))
6108         {
6109 
6110             return (0);
6111         }
6112     }
6113 
6114     /* IP addresses are grouped as A, B, C, or D types.  Determine which
6115        type address we have by comparing the IP address value against...*/
6116 
6117     /* Determine this by substracting the pointer to beginning of the whole
6118        IP address number ip_number_ptr[4] against the pointer to the last extracted word, ip_address_number. */
6119     ip_address_index = ip_number_ptr - ip_address_number + 1;
6120 
6121     /* Check for an invalid array index (assume 'the array' is indexed 1-4). */
6122     if ((ip_address_index == 0) || (ip_address_index > 4))
6123     {
6124         return (0);
6125     }
6126 
6127     /* Sum each of the individual IP address numbers depending how many there were extracted. */
6128 
6129     /* Most common input... */
6130     if (ip_address_index == 4)
6131     {
6132         INT i;
6133 
6134         /* Three separators parsed, so the format is a.b.c.d where c is 8 bits */
6135 
6136         /* Check for a computed sum greater than can be contained in 8 bits. */
6137        if (value > 0xff)
6138            return (0);
6139 
6140        /* 'Add' the last extracted number by prepending the three other bytes onto the total value. */
6141        for (i = 0; i<=2; i++)
6142        {
6143            value |= ip_address_number[i] << (24 - (i*8));
6144        }
6145     }
6146     /* Most common input... */
6147     else if (ip_address_index == 1)
6148     {
6149 
6150         /* We are done, this address contained one 32 bit word (no separators).  */
6151     }
6152     /* Less common input... */
6153     else if (ip_address_index ==  2)
6154     {
6155         /* One separator, so the format is a.b where b is 24 bits */
6156 
6157         /* Check for a computed sum greater than can be contained in 24 bits. */
6158         if (value > 0xffffff)
6159             return (0);
6160 
6161         /* 'Add' the last extracted number by prepending the most significant byte onto the total value. */
6162         value |= (ip_address_number[0] << 24);
6163      }
6164      else if (ip_address_index ==  3)
6165      {
6166         /* Two separators parsed, so the format is a.b.c where c is 16 bits */
6167          INT i;
6168 
6169          /* Check for a computed sum greater than can be contained in 16 bits. */
6170         if (value > 0xffff)
6171             return (0);
6172 
6173         /* 'Add' the last extracted number by prepending the two most significant bytes onto the total value. */
6174         for (i = 0; i<=1; i++)
6175         {
6176             value |= ip_address_number[i] << (24 - (i*8));
6177         }
6178      }
6179 
6180     /* Check if a return pointer for the address data is supplied. */
6181     if (addr)
6182     {
6183 
6184         /* Convert the IP address data to network byte order and return the data. */
6185         addr->s_addr = htonl(value);
6186     }
6187 
6188     return (1);
6189 }
6190 
6191 
6192 /**************************************************************************/
6193 /*                                                                        */
6194 /*  FUNCTION                                               RELEASE        */
6195 /*                                                                        */
6196 /*    inet_addr                                           PORTABLE C      */
6197 /*                                                           6.3.0        */
6198 /*  AUTHOR                                                                */
6199 /*                                                                        */
6200 /*    Yuxin Zhou, Microsoft Corporation                                   */
6201 /*                                                                        */
6202 /*  DESCRIPTION                                                           */
6203 /*                                                                        */
6204 /*    This function converts an IP address string to a number. If it      */
6205 /*    detects an error in the conversion it returns a zero address.       */
6206 /*                                                                        */
6207 /*  INPUT                                                                 */
6208 /*                                                                        */
6209 /*    buffer                                IP address text buffer        */
6210 /*    address                               Converted address number      */
6211 /*                                                                        */
6212 /*  OUTPUT                                                                */
6213 /*                                                                        */
6214 /*    NX_SUCCESS                            Successful conversion         */
6215 /*    NX_SOC_ERROR                          Error during conversion       */
6216 /*                                                                        */
6217 /*  CALLS                                                                 */
6218 /*                                                                        */
6219 /*    inet_aton                             Indicate char is a space      */
6220 /*                                                                        */
6221 /*  CALLED BY                                                             */
6222 /*                                                                        */
6223 /*    Application Code                                                    */
6224 /*                                                                        */
6225 /*  RELEASE HISTORY                                                       */
6226 /*                                                                        */
6227 /*    DATE              NAME                      DESCRIPTION             */
6228 /*                                                                        */
6229 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6230 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6231 /*                                            resulting in version 6.1    */
6232 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
6233 /*                                            used new API/structs naming,*/
6234 /*                                            resulting in version 6.3.0  */
6235 /*                                                                        */
6236 /**************************************************************************/
nx_bsd_inet_addr(const CHAR * buffer)6237 nx_bsd_in_addr_t nx_bsd_inet_addr(const CHAR *buffer)
6238 {
6239 
6240 struct  nx_bsd_in_addr ip_address;
6241 UINT    status;
6242 
6243     status = (UINT)nx_bsd_inet_aton(buffer, &ip_address);
6244 
6245     if (status == 0)
6246     {
6247         return (0xFFFFFFFF);
6248     }
6249 
6250     return(ip_address.s_addr);
6251 }
6252 
6253 
6254 /**************************************************************************/
6255 /*                                                                        */
6256 /*  FUNCTION                                               RELEASE        */
6257 /*                                                                        */
6258 /*    getsockopt                                          PORTABLE C      */
6259 /*                                                           6.3.0        */
6260 /*  AUTHOR                                                                */
6261 /*                                                                        */
6262 /*    Yuxin Zhou, Microsoft Corporation                                   */
6263 /*                                                                        */
6264 /*  DESCRIPTION                                                           */
6265 /*                                                                        */
6266 /*    This function returns the status of the specified socket option in  */
6267 /*    the current BSD socket session.                                     */
6268 /*                                                                        */
6269 /*  INPUT                                                                 */
6270 /*                                                                        */
6271 /*    sockID                                socket descriptor             */
6272 /*    option_level                          Category of option (SOCKET)   */
6273 /*    option_name                           Socket option ID              */
6274 /*    option_value                          Pointer to option value       */
6275 /*    option_value                          Pointer to size of value      */
6276 /*                                                                        */
6277 /*  OUTPUT                                                                */
6278 /*                                                                        */
6279 /*    tx_mutex_get                          Get protection                */
6280 /*    tx_mutex_put                          Release protection            */
6281 /*                                                                        */
6282 /*  CALLS                                                                 */
6283 /*                                                                        */
6284 /*    NX_SOC_OK                             Request processed successfully*/
6285 /*    NX_SOC_ERROR                          Errors with request           */
6286 /*    (option data)                         Pointer to requested data     */
6287 /*                                                                        */
6288 /*  CALLED BY                                                             */
6289 /*                                                                        */
6290 /*    Application Code                                                    */
6291 /*                                                                        */
6292 /*  RELEASE HISTORY                                                       */
6293 /*                                                                        */
6294 /*    DATE              NAME                      DESCRIPTION             */
6295 /*                                                                        */
6296 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6297 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6298 /*                                            resulting in version 6.1    */
6299 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
6300 /*                                            used new API/structs naming,*/
6301 /*                                            resulting in version 6.3.0  */
6302 /*                                                                        */
6303 /**************************************************************************/
nx_bsd_getsockopt(INT sockID,INT option_level,INT option_name,VOID * option_value,INT * option_length)6304 INT  nx_bsd_getsockopt(INT sockID, INT option_level, INT option_name, VOID *option_value, INT *option_length)
6305 {
6306 
6307 TX_INTERRUPT_SAVE_AREA
6308 
6309 INT                                     status;
6310 NX_BSD_SOCKET                           *bsd_socket_ptr;
6311 struct          nx_bsd_sock_errno       *so_errno;
6312 struct          nx_bsd_sock_keepalive   *so_keepalive;
6313 struct          nx_bsd_sock_reuseaddr   *so_reuseaddr;
6314 struct          nx_bsd_timeval          *so_rcvtimeval;
6315 struct          nx_bsd_sock_winsize     *soc_window_size;
6316 ULONG                                   ticks;
6317 
6318 
6319     /* Check for valid socket ID/descriptor. */
6320     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
6321     {
6322 
6323         /* Set the socket error if extended options enabled. */
6324         nx_bsd_set_errno(EBADF);
6325 
6326         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6327         return(NX_SOC_ERROR);
6328     }
6329 
6330     /* Check for invalid input. */
6331     if((option_value == NX_NULL) || (option_length == NX_NULL))
6332     {
6333 
6334         /* Set the socket error if extended socket options enabled. */
6335         nx_bsd_set_errno(EINVAL);
6336 
6337         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6338         return NX_SOC_ERROR;
6339     }
6340 
6341     if (option_level == IPPROTO_IP)
6342     {
6343 
6344         if((option_name <= SO_MAX) ||  (option_name > IP_OPTION_MAX))
6345         {
6346 
6347             /* Error, one or more invalid arguments.  */
6348 
6349             /* Set the socket error if extended socket options enabled. */
6350             nx_bsd_set_errno(ENOPROTOOPT);
6351 
6352             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6353             return NX_SOC_ERROR;
6354         }
6355     }
6356     else if(option_level == SOL_SOCKET)
6357     {
6358 
6359         if((option_name > SO_MAX) || (option_name < SO_MIN))
6360         {
6361 
6362             /* Error, one or more invalid arguments.  */
6363 
6364             /* Set the socket error if extended socket options enabled. */
6365             nx_bsd_set_errno(ENOPROTOOPT);
6366 
6367             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6368             return NX_SOC_ERROR;
6369         }
6370     }
6371     else
6372     {
6373 
6374         /* Error, one or more invalid arguments.  */
6375 
6376         /* Set the socket error if extended socket options enabled. */
6377         nx_bsd_set_errno(EINVAL);
6378 
6379         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6380         return NX_SOC_ERROR;
6381     }
6382 
6383     /* Normalize the socket ID.  */
6384     sockID =  sockID - NX_BSD_SOCKFD_START;
6385 
6386     /* Get the protection mutex.  */
6387     status =  (INT)tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
6388 
6389     /* Check the status.  */
6390     if (status)
6391     {
6392 
6393         /* Set the socket error if extended socket options enabled. */
6394         nx_bsd_set_errno(EACCES);
6395 
6396         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
6397         return(NX_SOC_ERROR);
6398     }
6399 
6400     /* Setup pointer to socket.  */
6401     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
6402 
6403     status = NX_SOC_OK;
6404     switch (option_name)
6405     {
6406 
6407         case SO_ERROR:
6408         {
6409 
6410            /* If a valid option pointer was supplied, verify it points to a valid data size. */
6411            if (*option_length < (INT)sizeof(so_errno -> error))
6412            {
6413 
6414                tx_mutex_put(nx_bsd_protection_ptr);
6415 
6416                /* Set the socket error if extended socket options enabled. */
6417                nx_bsd_set_errno(EINVAL);
6418 
6419                NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6420                return(NX_SOC_ERROR);
6421            }
6422 
6423            so_errno = (struct nx_bsd_sock_errno *)option_value;
6424 
6425            TX_DISABLE
6426            if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
6427            {
6428                so_errno -> error = bsd_socket_ptr -> nx_bsd_socket_error_code;
6429 
6430                /* Now clear the error code. */
6431                bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
6432 
6433                /* Clear the error flag.  The application is expected to close the socket at this point.*/
6434                bsd_socket_ptr -> nx_bsd_socket_status_flags = bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
6435            }
6436            else
6437                so_errno -> error = 0;
6438            TX_RESTORE
6439 
6440            /* Set the actual size of the data returned. */
6441            *option_length = sizeof(struct nx_bsd_sock_errno);
6442 
6443         }
6444 
6445         break;
6446 
6447         case SO_KEEPALIVE:
6448 
6449             /* Determine if NetX Duo supports keepalive. */
6450 
6451             /* Check to make sure the size arguement is sufficient if supplied. */
6452             if (*option_length < (INT)sizeof(so_keepalive -> keepalive_enabled))
6453             {
6454 
6455                 tx_mutex_put(nx_bsd_protection_ptr);
6456 
6457                 /* Set the socket error if extended socket options enabled. */
6458                 nx_bsd_set_errno(EINVAL);
6459 
6460                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6461                 return(NX_SOC_ERROR);
6462             }
6463 
6464             so_keepalive = (struct nx_bsd_sock_keepalive *)option_value;
6465 #ifndef NX_ENABLE_TCP_KEEPALIVE
6466             so_keepalive -> keepalive_enabled = NX_FALSE;
6467 #else
6468             so_keepalive -> keepalive_enabled = (INT)(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled);
6469 #endif /* NX_ENABLE_TCP_KEEPALIVE */
6470             *option_length = sizeof(struct nx_bsd_sock_keepalive);
6471 
6472         break;
6473 
6474         case SO_RCVTIMEO:
6475 
6476             /* Check if the receive time out is set. */
6477             if (bsd_socket_ptr -> nx_bsd_option_receive_timeout == 0)
6478             {
6479                 tx_mutex_put(nx_bsd_protection_ptr);
6480 
6481                 /* Set the socket error if extended socket options enabled. */
6482                 nx_bsd_set_errno(EINVAL);
6483 
6484                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6485                 return(NX_SOC_ERROR);
6486 
6487             }
6488 
6489             so_rcvtimeval = (struct nx_bsd_timeval *)option_value;
6490 
6491             ticks = bsd_socket_ptr -> nx_bsd_option_receive_timeout;
6492 
6493 
6494             so_rcvtimeval -> tv_usec = (nx_bsd_suseconds_t)(ticks * NX_MICROSECOND_PER_CPU_TICK) % 1000000;
6495             so_rcvtimeval -> tv_sec = (nx_bsd_time_t)((ticks * NX_MICROSECOND_PER_CPU_TICK) / 1000000);
6496             *option_length = sizeof(so_rcvtimeval);
6497 
6498         break;
6499 
6500         case SO_RCVBUF:
6501 
6502             soc_window_size = (struct nx_bsd_sock_winsize *)option_value;
6503             soc_window_size -> winsize = (INT)(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_default);
6504             *option_length = sizeof(soc_window_size);
6505 
6506         break;
6507 
6508         case SO_REUSEADDR:
6509 
6510             /* Check to make sure the size arguement is sufficient if supplied. */
6511             if (*option_length < (INT)sizeof(so_reuseaddr -> reuseaddr_enabled))
6512             {
6513 
6514                 tx_mutex_put(nx_bsd_protection_ptr);
6515 
6516                 /* Set the socket error if extended socket options enabled. */
6517                 nx_bsd_set_errno(EINVAL);
6518 
6519                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6520                 return(NX_SOC_ERROR);
6521             }
6522 
6523             so_reuseaddr= (struct nx_bsd_sock_reuseaddr *)option_value;
6524             so_reuseaddr -> reuseaddr_enabled = bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR;
6525             *option_length = sizeof(struct nx_bsd_sock_reuseaddr);
6526 
6527         break;
6528 
6529         case IP_MULTICAST_TTL:
6530 
6531             /* Validate the option length. */
6532             if(*option_length != sizeof(UCHAR))
6533             {
6534 
6535                 tx_mutex_put(nx_bsd_protection_ptr);
6536 
6537                 /* Set the socket error if extended socket options enabled. */
6538                 nx_bsd_set_errno(EINVAL);
6539 
6540                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6541                 return NX_SOC_ERROR;
6542             }
6543 
6544             /* Verify that the socket is still valid. */
6545             if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
6546             {
6547 
6548                 tx_mutex_put(nx_bsd_protection_ptr);
6549 
6550                 /* Set the socket error if extended socket options enabled. */
6551                 nx_bsd_set_errno(EBADF);
6552 
6553                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6554                 return NX_SOC_ERROR;
6555             }
6556 
6557             /* Make sure socket is UDP type. */
6558             if(bsd_socket_ptr -> nx_bsd_socket_udp_socket == NX_NULL)
6559             {
6560 
6561                 tx_mutex_put(nx_bsd_protection_ptr);
6562 
6563                 /* Set the socket error if extended socket options enabled. */
6564                 nx_bsd_set_errno(ENOPROTOOPT);
6565 
6566                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6567                 return NX_SOC_ERROR;
6568             }
6569 
6570             /* Set the TTL value. */
6571             *(UCHAR*)option_value = (UCHAR)(bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_time_to_live);
6572             break;
6573 
6574         default:
6575 
6576             tx_mutex_put(nx_bsd_protection_ptr);
6577 
6578             /* Set the socket error if extended socket options enabled. */
6579             nx_bsd_set_errno(ENOPROTOOPT);
6580 
6581             /* Unsupported or unknown option. */
6582             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6583             return(NX_SOC_ERROR);
6584     }
6585 
6586     /* Release the protection mutex.  */
6587     tx_mutex_put(nx_bsd_protection_ptr);
6588 
6589     return status;
6590 }
6591 
6592 /**************************************************************************/
6593 /*                                                                        */
6594 /*  FUNCTION                                               RELEASE        */
6595 /*                                                                        */
6596 /*    setsockopt                                          PORTABLE C      */
6597 /*                                                           6.4.0        */
6598 /*  AUTHOR                                                                */
6599 /*                                                                        */
6600 /*    Yuxin Zhou, Microsoft Corporation                                   */
6601 /*                                                                        */
6602 /*  DESCRIPTION                                                           */
6603 /*                                                                        */
6604 /*    This function enables the specified socket option in the current BSD*/
6605 /*    socket session to the specified setting.                            */
6606 /*                                                                        */
6607 /*  INPUT                                                                 */
6608 /*                                                                        */
6609 /*    sockID                                socket descriptor             */
6610 /*    option_level                          Category of option (SOCKET)   */
6611 /*    option_name                           Socket option ID              */
6612 /*    option_value                          Pointer to option value       */
6613 /*    option_length                         Size of option value data     */
6614 /*                                                                        */
6615 /*  OUTPUT                                                                */
6616 /*                                                                        */
6617 /*    NX_SOC_OK                             Request processed successfully*/
6618 /*    NX_SOC_ERROR                          Errors with request           */
6619 /*                                                                        */
6620 /*  CALLS                                                                 */
6621 /*                                                                        */
6622 /*    tx_mutex_get                          Get protection                */
6623 /*    tx_mutex_put                          Release protection            */
6624 /*                                                                        */
6625 /*  CALLED BY                                                             */
6626 /*                                                                        */
6627 /*    Application Code                                                    */
6628 /*                                                                        */
6629 /*  RELEASE HISTORY                                                       */
6630 /*                                                                        */
6631 /*    DATE              NAME                      DESCRIPTION             */
6632 /*                                                                        */
6633 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
6634 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
6635 /*                                            resulting in version 6.1    */
6636 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
6637 /*                                            used new API/structs naming,*/
6638 /*                                            resulting in version 6.3.0  */
6639 /*  12-31-2023     Yanwu Cai                Modified comment(s), and      */
6640 /*                                            added PACKET_ADD_MEMBERSHIP */
6641 /*                                            and PACKET_DROP_MEMBERSHIP, */
6642 /*                                            resulting in version 6.4.0  */
6643 /*                                                                        */
6644 /**************************************************************************/
nx_bsd_setsockopt(INT sockID,INT option_level,INT option_name,const VOID * option_value,INT option_length)6645 INT  nx_bsd_setsockopt(INT sockID, INT option_level, INT option_name, const VOID *option_value, INT option_length)
6646 {
6647 UINT                    reuse_enabled;
6648 NX_BSD_SOCKET           *bsd_socket_ptr;
6649 ULONG                   window_size;
6650 ULONG                   timer_ticks;
6651 struct nx_bsd_timeval   *time_val;
6652 #if defined(NX_ENABLE_IP_RAW_PACKET_FILTER) || !defined(NX_DISABLE_IPV4)
6653 INT             i;
6654 #endif /* defined(NX_ENABLE_IP_RAW_PACKET_FILTER) || !defined(NX_DISABLE_IPV4) */
6655 #ifndef NX_DISABLE_IPV4
6656 struct nx_bsd_ip_mreq
6657                *mreq;
6658 UINT            mcast_interface;
6659 UINT            status;
6660 #endif /* NX_DISABLE_IPV4 */
6661 #if defined(NX_BSD_RAW_SUPPORT) && defined(NX_ENABLE_VLAN)
6662 struct nx_bsd_packet_mreq
6663                *pkt_mreq;
6664 ULONG           physical_addr_msw;
6665 ULONG           physical_addr_lsw;
6666 #endif
6667 
6668 
6669     /* Check for valid socket ID. */
6670     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
6671     {
6672 
6673         /* Error, invalid socket ID.  */
6674 
6675         /* Set the socket error if extended options enabled. */
6676         nx_bsd_set_errno(EBADF);
6677 
6678         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6679         return(NX_SOC_ERROR);
6680     }
6681 
6682     /* Check for invalid paremters. */
6683     if((option_value == NX_NULL) || (option_length == 0))
6684     {
6685 
6686         /* Error, one or more invalid arguments.  */
6687 
6688         /* Set the socket error if extended socket options enabled. */
6689         nx_bsd_set_errno(EINVAL);
6690 
6691         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6692         return NX_SOC_ERROR;
6693     }
6694 
6695     if (option_level == IPPROTO_IP)
6696     {
6697 
6698         if((option_name <= SO_MAX) ||  (option_name > IP_OPTION_MAX))
6699         {
6700 
6701             /* Error, one or more invalid arguments.  */
6702 
6703             /* Set the socket error if extended socket options enabled. */
6704             nx_bsd_set_errno(ENOPROTOOPT);
6705 
6706             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6707             return NX_SOC_ERROR;
6708         }
6709     }
6710     else if(option_level == SOL_SOCKET)
6711     {
6712 
6713         if((option_name > SO_MAX) ||
6714            (option_name < SO_MIN))
6715         {
6716             /* Error, one or more invalid arguments.  */
6717 
6718             /* Set the socket error if extended socket options enabled. */
6719             nx_bsd_set_errno(ENOPROTOOPT);
6720 
6721             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6722             return NX_SOC_ERROR;
6723         }
6724     }
6725     else if(option_level == SOL_PACKET)
6726     {
6727         if ((option_name > PACKET_OPTION_MAX) ||
6728             (option_name < PACKET_ADD_MEMBERSHIP))
6729         {
6730             /* Error, one or more invalid arguments.  */
6731 
6732             /* Set the socket error if extended socket options enabled. */
6733             nx_bsd_set_errno(ENOPROTOOPT);
6734 
6735             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6736             return NX_SOC_ERROR;
6737         }
6738     }
6739     else if (option_level == IPPROTO_TCP)
6740     {
6741 
6742         if ((option_name > TCP_NOOPT) ||
6743             (option_name < TCP_NODELAY))
6744         {
6745             /* Error, one or more invalid arguments.  */
6746 
6747             /* Set the socket error if extended socket options enabled. */
6748             nx_bsd_set_errno(ENOPROTOOPT);
6749 
6750             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6751             return NX_SOC_ERROR;
6752         }
6753     }
6754     else
6755     {
6756         /* Error, one or more invalid arguments.  */
6757 
6758         /* Set the socket error if extended socket options enabled. */
6759         nx_bsd_set_errno(EINVAL);
6760 
6761         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6762         return NX_SOC_ERROR;
6763     }
6764     /* Normalize the socket ID.  */
6765     sockID =  sockID - NX_BSD_SOCKFD_START;
6766 
6767     /* Set up pointer to the BSD socket.  */
6768     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
6769 
6770     /* Set the socket option status. */
6771     switch (option_name)
6772     {
6773 
6774         case SO_BROADCAST:
6775 
6776             /* This is the default behavior of NetX. All sockets have this capability. */
6777         break;
6778 
6779         case SO_KEEPALIVE:
6780 
6781             /* Only available to TCP BSD sockets. */
6782             if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
6783             {
6784 
6785                 /* Verify TCP keep alive is built into the NetX library or return an error. */
6786 #ifndef NX_ENABLE_TCP_KEEPALIVE
6787 
6788                 /* Set the socket error if extended socket options enabled. */
6789                 nx_bsd_set_errno(ENOPROTOOPT);
6790 
6791                 /* Return an error status. */
6792                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6793                 return NX_SOC_ERROR;
6794 #else
6795                 /* Determine if NetX Duo supports keepalive. */
6796 
6797                 /* Update the BSD socket with this attribute. */
6798                 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled =
6799                                         (UINT)(((struct nx_bsd_sock_keepalive *)option_value) -> keepalive_enabled);
6800 
6801                 if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled == NX_TRUE)
6802                 {
6803 
6804                     /* Set the keep alive timeout for this socket with the NetX configurable keep alive timeout. */
6805                     bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_timeout =  NX_TCP_KEEPALIVE_INITIAL;
6806                 }
6807                 else
6808                 {
6809 
6810                     /* Clear the socket keep alive timeout. */
6811                     bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_timeout =  0;
6812                 }
6813 #endif /* NX_ENABLE_TCP_KEEPALIVE */
6814             }
6815             else
6816             {
6817                 /* Not a TCP socket. */
6818 
6819                 /* Set the socket error if extended socket options enabled. */
6820                 nx_bsd_set_errno(ENOPROTOOPT);
6821 
6822                 /* Return an error status. */
6823                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6824                 return NX_SOC_ERROR;
6825             }
6826 
6827         break;
6828 
6829         case SO_LINGER:
6830 
6831             /* The Linger socket option is not supported in NetX Duo BSD. */
6832 
6833             return NX_NOT_ENABLED;
6834 
6835         case SO_SNDTIMEO:
6836 
6837             time_val =  (struct nx_bsd_timeval *)option_value;
6838 
6839             /* Calculate ticks for the ThreadX Timer.  */
6840             timer_ticks = (ULONG)(time_val -> tv_usec)/NX_MICROSECOND_PER_CPU_TICK  + (ULONG)(time_val -> tv_sec) * NX_IP_PERIODIC_RATE;
6841 
6842             bsd_socket_ptr -> nx_bsd_option_send_timeout = timer_ticks;
6843 
6844         break;
6845 
6846         case SO_RCVTIMEO:
6847 
6848             time_val =  (struct nx_bsd_timeval *)option_value;
6849 
6850             /* Calculate ticks for the ThreadX Timer.  */
6851             timer_ticks = (ULONG)(time_val -> tv_usec)/NX_MICROSECOND_PER_CPU_TICK  + (ULONG)(time_val -> tv_sec) * NX_IP_PERIODIC_RATE;
6852 
6853             bsd_socket_ptr -> nx_bsd_option_receive_timeout = timer_ticks;
6854 
6855         break;
6856 
6857         case SO_RCVBUF:
6858 
6859             /* Only available to TCP sockets. */
6860             if (!bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
6861             {
6862 
6863                 /* Set the socket error if extended socket options enabled. */
6864                 nx_bsd_set_errno(ENOPROTOOPT);
6865 
6866                 /* Return an error status. */
6867                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6868                 return NX_SOC_ERROR;
6869             }
6870 
6871 
6872             window_size = (ULONG)(((struct nx_bsd_sock_winsize *)option_value) -> winsize);
6873 
6874 #ifdef NX_ENABLE_TCP_WINDOW_SCALING
6875 
6876 
6877             /* If Window scaling feature is enabled, record this user-specified window size. */
6878             bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_maximum = window_size;
6879 #else
6880             /* Otherwise the windows size limit is applied. */
6881             if(window_size > 65535)
6882                 window_size = 65535;
6883 
6884 #endif /* NX_ENABLE_TCP_WINDOW_SCALING */
6885 
6886             /* Setup the sliding window information.  */
6887             bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_default =   window_size;
6888             bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_current =   window_size;
6889 
6890         break;
6891 
6892         case SO_REUSEADDR:
6893 
6894             reuse_enabled = (UINT)(((struct nx_bsd_sock_reuseaddr *)option_value) -> reuseaddr_enabled);
6895 
6896             if(reuse_enabled)
6897                 bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR;
6898             else
6899                 bsd_socket_ptr -> nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR);
6900 
6901         break;
6902 
6903 
6904         case TCP_NODELAY:
6905 
6906             /* This is the default behavior of NetX. All sockets have this attribute. */
6907 
6908         break;
6909 
6910         case IP_MULTICAST_TTL:
6911 
6912             /* Validate the option length. */
6913             if(option_length != sizeof(UCHAR) && option_length != sizeof(INT))
6914             {
6915 
6916                 /* Set the socket error if extended socket options enabled. */
6917                 nx_bsd_set_errno(EINVAL);
6918 
6919                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6920                 return NX_SOC_ERROR;
6921             }
6922 
6923             /* Verify that the socket is still valid. */
6924             if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
6925             {
6926 
6927                 /* Set the socket error if extended socket options enabled. */
6928                 nx_bsd_set_errno(EBADF);
6929 
6930                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6931                 return NX_SOC_ERROR;
6932             }
6933 
6934             /* Make sure socket is UDP type. */
6935             if(bsd_socket_ptr -> nx_bsd_socket_udp_socket == NX_NULL)
6936             {
6937                 /* Set the socket error if extended socket options enabled. */
6938                 nx_bsd_set_errno(ENOPROTOOPT);
6939 
6940                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6941                 return NX_SOC_ERROR;
6942             }
6943 
6944             /* Set the TTL value. */
6945             if (option_length == sizeof(UCHAR))
6946             {
6947                 bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_time_to_live = *(UCHAR*)option_value;
6948             }
6949             else
6950             {
6951                 bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_time_to_live = (UCHAR)(*(INT*)option_value);
6952             }
6953         break;
6954 
6955         case IP_MULTICAST_LOOP:
6956 
6957             /* This is not supported yet. */
6958 
6959         break;
6960 
6961         case IP_MULTICAST_IF:
6962 
6963             /* This is not supported yet. */
6964 
6965         break;
6966 #if defined(NX_BSD_RAW_SUPPORT) && defined(NX_ENABLE_VLAN)
6967 
6968         case PACKET_ADD_MEMBERSHIP:
6969         case PACKET_DROP_MEMBERSHIP:
6970 
6971             /* Validate the option length */
6972             if (option_length != sizeof(struct nx_bsd_packet_mreq))
6973             {
6974 
6975                 /* Set the socket error if extended socket options enabled. */
6976                 nx_bsd_set_errno(EINVAL);
6977 
6978                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6979                 return NX_SOC_ERROR;
6980             }
6981 
6982             pkt_mreq = (struct nx_bsd_packet_mreq*)option_value;
6983 
6984             if (pkt_mreq -> mr_alen != ETH_ALEN || pkt_mreq -> mr_type != PACKET_MR_MULTICAST)
6985             {
6986 
6987                 /* Set the socket error if extended socket options enabled. */
6988                 nx_bsd_set_errno(EINVAL);
6989 
6990                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6991                 return NX_SOC_ERROR;
6992             }
6993 
6994             /* Verify that the socket is still valid. */
6995             if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
6996             {
6997                 /* Set the socket error if extended socket options enabled. */
6998                 nx_bsd_set_errno(EBADF);
6999 
7000                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7001                 return NX_SOC_ERROR;
7002             }
7003 
7004             physical_addr_msw = (pkt_mreq -> mr_address[0] << 8) | pkt_mreq->mr_address[1];
7005             physical_addr_lsw = (pkt_mreq -> mr_address[2] << 24) | (pkt_mreq->mr_address[3] << 16) |
7006                                 (pkt_mreq -> mr_address[4] << 8) | pkt_mreq -> mr_address[5];
7007 
7008             if (option_name == PACKET_ADD_MEMBERSHIP)
7009             {
7010                 status = nx_link_multicast_join(nx_bsd_default_ip, pkt_mreq -> mr_ifindex,
7011                                                 physical_addr_msw, physical_addr_lsw);
7012             }
7013             else
7014             {
7015                 status = nx_link_multicast_leave(nx_bsd_default_ip, pkt_mreq -> mr_ifindex,
7016                                                  physical_addr_msw, physical_addr_lsw);
7017             }
7018 
7019             if (status != NX_SUCCESS)
7020             {
7021 
7022                 nx_bsd_set_errno(EINVAL);
7023 
7024                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7025                 return NX_SOC_ERROR;
7026             }
7027 
7028             break;
7029 #endif
7030 
7031         case IP_RAW_RX_NO_HEADER:
7032 
7033 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
7034             i = *(INT*)option_value;
7035 
7036             if((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET) &&
7037                ((bsd_socket_ptr -> nx_bsd_socket_family == AF_INET) || (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)))
7038             {
7039 
7040                 if(i)
7041                 {
7042 
7043                     bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_RX_NO_HDR;
7044                 }
7045                 else
7046                 {
7047 
7048                     bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_RX_NO_HDR);
7049                 }
7050             }
7051             else
7052 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
7053             {
7054 
7055                 nx_bsd_set_errno(EINVAL);
7056 
7057                 /* Return an error status. */
7058                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7059 
7060                 return NX_SOC_ERROR;
7061             }
7062 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
7063             break;
7064 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
7065 
7066         case IP_RAW_IPV6_HDRINCL:
7067 
7068 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
7069             i = *(INT*)option_value;
7070 
7071             /* Is this an IPv6 socket? */
7072             if((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET) &&
7073                (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6))
7074             {
7075 
7076                 /* Should the No Header feature be enabled (NX_TRUE)? */
7077                 if(i)
7078                 {
7079 
7080                     /* Yes, set the flag for no header. */
7081                     bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_TX_HDR_INCLUDE;
7082                 }
7083                 else
7084                 {
7085 
7086                     /* No, clear the flag for no header. */
7087                     bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_TX_HDR_INCLUDE);
7088                 }
7089             }
7090             else
7091 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
7092             {
7093 
7094                 nx_bsd_set_errno(EINVAL);
7095 
7096                 /* Return an error status. */
7097                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7098 
7099                 return NX_SOC_ERROR;
7100             }
7101 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
7102             break;
7103 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
7104 
7105 
7106 #ifndef NX_DISABLE_IPV4
7107         case IP_ADD_MEMBERSHIP:
7108         case IP_DROP_MEMBERSHIP:
7109 
7110             /* Validate the option length */
7111             if(option_length != sizeof(struct nx_bsd_ip_mreq))
7112             {
7113 
7114                 /* Set the socket error if extended socket options enabled. */
7115                 nx_bsd_set_errno(EINVAL);
7116 
7117                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7118                 return NX_SOC_ERROR;
7119             }
7120 
7121             mreq = (struct nx_bsd_ip_mreq*)option_value;
7122 
7123             /* Make sure the multicast group address is valid. */
7124             if((mreq -> imr_multiaddr.s_addr & ntohl(NX_IP_CLASS_D_TYPE)) != ntohl(NX_IP_CLASS_D_TYPE))
7125             {
7126                 /* Set the socket error if extended socket options enabled. */
7127                 nx_bsd_set_errno(EINVAL);
7128 
7129                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7130                 return NX_SOC_ERROR;
7131             }
7132 
7133             /* Verify that the socket is still valid. */
7134             if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
7135             {
7136                 /* Set the socket error if extended socket options enabled. */
7137                 nx_bsd_set_errno(EBADF);
7138 
7139                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7140                 return NX_SOC_ERROR;
7141             }
7142 
7143             /* Make sure socket is UDP type. */
7144             if(bsd_socket_ptr -> nx_bsd_socket_udp_socket == NX_NULL)
7145             {
7146                 /* Set the socket error if extended socket options enabled. */
7147                 nx_bsd_set_errno(ENOPROTOOPT);
7148 
7149                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7150                 return NX_SOC_ERROR;
7151             }
7152 
7153             /* Validate that the interface is one of the local IPv4 interfaces. */
7154             /* We allow imr_interface being zero to indicate the primary interface. */
7155             mcast_interface = NX_MAX_IP_INTERFACES;
7156 
7157             if(mreq -> imr_interface.s_addr == INADDR_ANY)
7158             {
7159                 mcast_interface = 0;
7160             }
7161             else
7162             {
7163 
7164                 /* Set the socket error if extended socket options enabled. */
7165                 UINT addr;
7166 
7167                 /* Convert the local interface value to host byte order. */
7168                 addr = ntohl(mreq -> imr_interface.s_addr);
7169 
7170                 /* Search through the interface table for a matching one. */
7171                 for(i = 0; i < NX_MAX_IP_INTERFACES; i++)
7172                 {
7173 
7174                     if(addr == nx_bsd_default_ip -> nx_ip_interface[i].nx_interface_ip_address)
7175                     {
7176 
7177                         mcast_interface = (UINT)i;
7178                         break;
7179                     }
7180                 }
7181             }
7182 
7183             if(mcast_interface == NX_MAX_IP_INTERFACES)
7184             {
7185 
7186                 /* Did not find a matching interface. */
7187                 nx_bsd_set_errno(EINVAL);
7188 
7189                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7190                 return NX_SOC_ERROR;
7191             }
7192 
7193             if(option_name == IP_ADD_MEMBERSHIP)
7194             {
7195 
7196                 /* Make sure the IGMP feature is enabled. */
7197                 if(nx_bsd_default_ip -> nx_ip_igmp_packet_receive == NX_NULL)
7198                 {
7199                     nx_igmp_enable(nx_bsd_default_ip);
7200                 }
7201 
7202                 /* Join the group. */
7203                 status = nx_igmp_multicast_interface_join(nx_bsd_default_ip, ntohl(mreq -> imr_multiaddr.s_addr), mcast_interface);
7204             }
7205             else
7206             {
7207 
7208                 /* Leave group */
7209                 status = nx_igmp_multicast_leave(nx_bsd_default_ip, ntohl(mreq -> imr_multiaddr.s_addr));
7210             }
7211 
7212             if(status != NX_SUCCESS)
7213             {
7214 
7215                 nx_bsd_set_errno(EINVAL);
7216 
7217                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7218                 return NX_SOC_ERROR;
7219             }
7220 
7221             break;
7222 #endif /* NX_DISABLE_IPV4 */
7223 
7224         case IP_HDRINCL:
7225 
7226 #if defined(NX_ENABLE_IP_RAW_PACKET_FILTER) && !defined(NX_DISABLE_IPV4)
7227             i = *(INT*)option_value;
7228             /* First verify that raw socket processing is enabled on the IP instance and that this is
7229                an IPv4 thread. */
7230             if((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET) &&
7231                (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET))
7232             {
7233 
7234                 /* Is the option being enabled (NX_TRUE)? */
7235                 if(i)
7236                 {
7237 
7238                     /* Yes, set the flag bit indicating BSD will append the IP header. */
7239                     bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_TX_HDR_INCLUDE;
7240                 }
7241                 else
7242                 {
7243 
7244                     /* No, clear the flag bit indicating IP task will append the IP header. */
7245                     bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_TX_HDR_INCLUDE);
7246                 }
7247             }
7248             else
7249 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
7250             {
7251 
7252                 nx_bsd_set_errno(EINVAL);
7253 
7254                 /* Return an error status. */
7255                 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7256 
7257                 return NX_SOC_ERROR;
7258             }
7259 
7260 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
7261             break;
7262 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
7263 
7264         default:
7265 
7266             /* Set the socket error if extended socket options enabled. */
7267             nx_bsd_set_errno(EINVAL);
7268 
7269             /* Return an error status. */
7270             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7271             return NX_SOC_ERROR;
7272     }
7273 
7274     /* Socket option successfully updated. */
7275     return NX_SUCCESS;
7276 }
7277 
7278 
7279 /**************************************************************************/
7280 /*                                                                        */
7281 /*  FUNCTION                                               RELEASE        */
7282 /*                                                                        */
7283 /*    getsockname                                         PORTABLE C      */
7284 /*                                                           6.3.0        */
7285 /*  AUTHOR                                                                */
7286 /*                                                                        */
7287 /*    Yuxin Zhou, Microsoft Corporation                                   */
7288 /*                                                                        */
7289 /*  DESCRIPTION                                                           */
7290 /*                                                                        */
7291 /*    This function returns the socket's primary interface address and    */
7292 /*    port. For NetX Duo environments, it returns the address at address  */
7293 /*    index 1 into the IP address table; this is where the primary        */
7294 /*    interface global IP address is normally located.                    */
7295 /*                                                                        */
7296 /*  INPUT                                                                 */
7297 /*                                                                        */
7298 /*    sockID                                socket descriptor             */
7299 /*    localAddress                          sockaddr struct to return     */
7300 /*                                          the local address             */
7301 /*    addressLength                         Number of bytes in sockAddr   */
7302 /*                                                                        */
7303 /*  OUTPUT                                                                */
7304 /*                                                                        */
7305 /*    NX_SOC_OK (0)                         On success                    */
7306 /*    NX_SOC_ERROR (-1)                     On failure                    */
7307 /*                                                                        */
7308 /*  CALLS                                                                 */
7309 /*                                                                        */
7310 /*    tx_mutex_get                          Get protection                */
7311 /*    tx_mutex_put                          Release protection            */
7312 /*                                                                        */
7313 /*  CALLED BY                                                             */
7314 /*                                                                        */
7315 /*    Application Code                                                    */
7316 /*                                                                        */
7317 /*  RELEASE HISTORY                                                       */
7318 /*                                                                        */
7319 /*    DATE              NAME                      DESCRIPTION             */
7320 /*                                                                        */
7321 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7322 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
7323 /*                                            verified memcpy use cases,  */
7324 /*                                            resulting in version 6.1    */
7325 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
7326 /*                                            used new API/structs naming,*/
7327 /*                                            resulting in version 6.3.0  */
7328 /*                                                                        */
7329 /**************************************************************************/
nx_bsd_getsockname(INT sockID,struct nx_bsd_sockaddr * localAddress,INT * addressLength)7330 INT  nx_bsd_getsockname(INT sockID, struct nx_bsd_sockaddr *localAddress, INT *addressLength)
7331 {
7332 
7333 #ifndef NX_DISABLE_IPV4
7334 struct nx_bsd_sockaddr_in  soc_struct;
7335 #endif /* NX_DISABLE_IPV4 */
7336 #ifdef FEATURE_NX_IPV6
7337 struct nx_bsd_sockaddr_in6 soc6_struct;
7338 #endif
7339 UINT                status;
7340 NX_BSD_SOCKET       *bsd_socket_ptr;
7341 
7342 
7343     /* Check whether supplied socket ID is valid.  */
7344     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
7345     {
7346 
7347         /* Set the socket error if extended options enabled. */
7348         nx_bsd_set_errno(EBADF);
7349 
7350         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7351         return(NX_SOC_ERROR);
7352     }
7353 
7354     if((localAddress == NX_NULL) || (addressLength == NX_NULL) || (*addressLength == 0))
7355     {
7356 
7357         /* Set the socket error if extended socket options enabled. */
7358         nx_bsd_set_errno(EINVAL);
7359 
7360         /* Return error.  */
7361         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7362         return(NX_SOC_ERROR);
7363     }
7364 
7365     /* Normalize the socket ID.  */
7366     sockID =  sockID - NX_BSD_SOCKFD_START;
7367 
7368     /* Setup pointer to socket.  */
7369     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
7370 
7371     /* Get the protection mutex.  */
7372     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
7373 
7374     /* Check the status.  */
7375     if (status)
7376     {
7377 
7378         /* Set the socket error if extended socket options enabled. */
7379         nx_bsd_set_errno(EACCES);
7380 
7381         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
7382         return(NX_SOC_ERROR);
7383     }
7384 
7385     /* Is the socket still in use?  */
7386     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
7387     {
7388 
7389         /* Set the socket error if extended options enabled. */
7390         nx_bsd_set_errno(EBADF);
7391         /* Release the protection mutex.  */
7392         tx_mutex_put(nx_bsd_protection_ptr);
7393 
7394         /* Return error.  */
7395         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7396         return(NX_SOC_ERROR);
7397     }
7398 
7399     if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND))
7400     {
7401         /* This socket is not bound yet.  Just return.
7402            According to the spec, if the socket is not bound, the value stored in
7403            localAddress is unspecified. */
7404         /* Release the protection mutex.  */
7405         tx_mutex_put(nx_bsd_protection_ptr);
7406 
7407         /* Success!  */
7408         return(NX_SOC_OK);
7409     }
7410 
7411 #ifndef NX_DISABLE_IPV4
7412     if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
7413     {
7414         if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
7415         {
7416             soc_struct.sin_addr.s_addr = INADDR_ANY;
7417         }
7418         else if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == 0)
7419         {
7420 
7421             nx_bsd_set_errno(EINVAL);
7422 
7423             /* Release the protection mutex.  */
7424             tx_mutex_put(nx_bsd_protection_ptr);
7425 
7426             /* Return error.  */
7427             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7428             return(NX_SOC_ERROR);
7429         }
7430         else
7431         {
7432             NX_INTERFACE* local_if = (NX_INTERFACE*)(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface);
7433             soc_struct.sin_addr.s_addr = htonl(local_if -> nx_interface_ip_address);
7434         }
7435         soc_struct.sin_port = htons((USHORT)bsd_socket_ptr -> nx_bsd_socket_local_port);
7436 
7437         soc_struct.sin_family = AF_INET;
7438 
7439         if((*addressLength) > (INT)sizeof(struct nx_bsd_sockaddr_in))
7440         {
7441             *addressLength = sizeof(struct nx_bsd_sockaddr_in);
7442         }
7443         memcpy(localAddress, &soc_struct, (UINT)(*addressLength)); /* Use case of memcpy is verified. */
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 
7451 
7452         if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
7453         {
7454             soc6_struct.sin6_addr._S6_un._S6_u32[0] = 0;
7455             soc6_struct.sin6_addr._S6_un._S6_u32[1] = 0;
7456             soc6_struct.sin6_addr._S6_un._S6_u32[2] = 0;
7457             soc6_struct.sin6_addr._S6_un._S6_u32[3] = 0;
7458         }
7459         else if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == 0)
7460         {
7461 
7462             nx_bsd_set_errno(EINVAL);
7463 
7464             /* Release the protection mutex.  */
7465             tx_mutex_put(nx_bsd_protection_ptr);
7466 
7467             /* Return error.  */
7468             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7469             return(NX_SOC_ERROR);
7470         }
7471         else
7472         {
7473             NXD_IPV6_ADDRESS* local_v6if = (NXD_IPV6_ADDRESS*)(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface);
7474 
7475             soc6_struct.sin6_addr._S6_un._S6_u32[0] = htonl(local_v6if -> nxd_ipv6_address[0]);
7476             soc6_struct.sin6_addr._S6_un._S6_u32[1] = htonl(local_v6if -> nxd_ipv6_address[1]);
7477             soc6_struct.sin6_addr._S6_un._S6_u32[2] = htonl(local_v6if -> nxd_ipv6_address[2]);
7478             soc6_struct.sin6_addr._S6_un._S6_u32[3] = htonl(local_v6if -> nxd_ipv6_address[3]);
7479         }
7480 
7481         soc6_struct.sin6_port =  htons((USHORT)bsd_socket_ptr -> nx_bsd_socket_local_port);
7482 
7483         soc6_struct.sin6_family = AF_INET6;
7484 
7485         if((*addressLength) > (INT)sizeof(struct nx_bsd_sockaddr_in6))
7486         {
7487             *addressLength = sizeof(struct nx_bsd_sockaddr_in6);
7488         }
7489         memcpy(localAddress, &soc6_struct, (UINT)(*addressLength)); /* Use case of memcpy is verified. */
7490 
7491     }
7492     else
7493 #endif /* FEATURE_NX_IPV6 */
7494     {
7495 
7496         /* Release the protection mutex.  */
7497         tx_mutex_put(nx_bsd_protection_ptr);
7498 
7499         nx_bsd_set_errno(EPROTONOSUPPORT);
7500 
7501         /* Return error.  */
7502         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7503         return(NX_SOC_ERROR);
7504     }
7505 
7506 
7507 
7508     /* Release the protection mutex.  */
7509     tx_mutex_put(nx_bsd_protection_ptr);
7510 
7511     /* Success!  */
7512     return(NX_SOC_OK);
7513 }
7514 
7515 
7516 /**************************************************************************/
7517 /*                                                                        */
7518 /*  FUNCTION                                               RELEASE        */
7519 /*                                                                        */
7520 /*    getpeername                                         PORTABLE C      */
7521 /*                                                           6.3.0        */
7522 /*  AUTHOR                                                                */
7523 /*                                                                        */
7524 /*    Yuxin Zhou, Microsoft Corporation                                   */
7525 /*                                                                        */
7526 /*  DESCRIPTION                                                           */
7527 /*                                                                        */
7528 /*    This function returns the socket's remote address and port.         */
7529 /*                                                                        */
7530 /*  INPUT                                                                 */
7531 /*                                                                        */
7532 /*    sockID                                socket descriptor             */
7533 /*    localAddress                          sockaddr struct to return     */
7534 /*                                          the remote address            */
7535 /*    addressLength                         Number of bytes in sockAddr   */
7536 /*                                                                        */
7537 /*  OUTPUT                                                                */
7538 /*                                                                        */
7539 /*    NX_SOC_OK (0)                         On success                    */
7540 /*    NX_SOC_ERROR (-1)                     On failure                    */
7541 /*                                                                        */
7542 /*  CALLS                                                                 */
7543 /*                                                                        */
7544 /*    tx_mutex_get                          Get protection                */
7545 /*    tx_mutex_put                          Release protection            */
7546 /*                                                                        */
7547 /*  CALLED BY                                                             */
7548 /*                                                                        */
7549 /*    Application Code                                                    */
7550 /*                                                                        */
7551 /*  RELEASE HISTORY                                                       */
7552 /*                                                                        */
7553 /*    DATE              NAME                      DESCRIPTION             */
7554 /*                                                                        */
7555 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7556 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7557 /*                                            resulting in version 6.1    */
7558 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
7559 /*                                            used new API/structs naming,*/
7560 /*                                            resulting in version 6.3.0  */
7561 /*                                                                        */
7562 /**************************************************************************/
nx_bsd_getpeername(INT sockID,struct nx_bsd_sockaddr * remoteAddress,INT * addressLength)7563 INT  nx_bsd_getpeername(INT sockID, struct nx_bsd_sockaddr *remoteAddress, INT *addressLength)
7564 {
7565 
7566 UINT                status;
7567 NX_BSD_SOCKET       *bsd_socket_ptr;
7568 #ifndef NX_DISABLE_IPV4
7569 struct nx_bsd_sockaddr_in  *soc_struct_ptr = NX_NULL;
7570 #endif /* NX_DISABLE_IPV4 */
7571 #ifdef FEATURE_NX_IPV6
7572 struct nx_bsd_sockaddr_in6 *soc6_struct_ptr = NX_NULL;
7573 #endif
7574 
7575 
7576     /* Check whether supplied socket ID is valid.  */
7577     if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
7578     {
7579 
7580         /* Set the socket error if extended socket options enabled. */
7581         nx_bsd_set_errno(EINVAL);
7582 
7583         /* Error, invalid socket ID.  */
7584         NX_BSD_ERROR(ERROR, __LINE__);
7585         return(ERROR);
7586     }
7587 
7588     /* Normalize the socket ID.  */
7589     sockID =  sockID - NX_BSD_SOCKFD_START;
7590 
7591     /* Check the remote address and length pointers.  */
7592     if((remoteAddress == NX_NULL) ||(addressLength == NX_NULL))
7593     {
7594 
7595         /* Set the socket error if extended socket options enabled. */
7596         nx_bsd_set_errno(EINVAL);
7597 
7598         /* Return error.  */
7599         NX_BSD_ERROR(ERROR, __LINE__);
7600         return(ERROR);
7601     }
7602 
7603 
7604     /* Get the protection mutex.  */
7605     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
7606 
7607     /* Check the status.  */
7608     if (status)
7609     {
7610 
7611         /* Set the socket error if extended socket options enabled. */
7612         nx_bsd_set_errno(EACCES);
7613 
7614         /* Error getting the protection mutex.  */
7615         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
7616         return(ERROR);
7617     }
7618 
7619     /* Setup pointer to socket.  */
7620     bsd_socket_ptr =  &nx_bsd_socket_array[sockID];
7621 
7622 #ifndef NX_DISABLE_IPV4
7623     if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
7624     {
7625 
7626         /* This is an IPv4 only socket. */
7627 
7628         /* Now validate the size of remoteAddress structure. */
7629         if(*addressLength < (INT)sizeof(struct nx_bsd_sockaddr_in))
7630         {
7631 
7632             /* User supplied buffer is too small .*/
7633 
7634             /* Release the protection mutex.  */
7635             tx_mutex_put(nx_bsd_protection_ptr);
7636 
7637             /* Set the socket error, if socket enabled with extended BSD features. */
7638             nx_bsd_set_errno(ESOCKTNOSUPPORT);
7639 
7640             /* Return error.  */
7641             NX_BSD_ERROR(ERROR, __LINE__);
7642             return(ERROR);
7643         }
7644 
7645         soc_struct_ptr = (struct nx_bsd_sockaddr_in*)remoteAddress;
7646         *addressLength = sizeof(struct nx_bsd_sockaddr_in);
7647     }
7648     else
7649 #endif /* NX_DISABLE_IPV4 */
7650 #ifdef FEATURE_NX_IPV6
7651     if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
7652     {
7653 
7654         /* IPv6 socket */
7655 
7656         /* Now validate the size of remoteAddress structure. */
7657         if(*addressLength < (INT)sizeof(struct nx_bsd_sockaddr_in6))
7658         {
7659 
7660             /* User supplied buffer is too small .*/
7661 
7662             /* Release the protection mutex.  */
7663             tx_mutex_put(nx_bsd_protection_ptr);
7664 
7665             /* Set the socket error, if socket enabled with extended BSD features. */
7666             nx_bsd_set_errno(ESOCKTNOSUPPORT);
7667 
7668             /* Return error.  */
7669             NX_BSD_ERROR(ERROR, __LINE__);
7670             return(ERROR);
7671         }
7672 
7673         soc6_struct_ptr = (struct nx_bsd_sockaddr_in6*)remoteAddress;
7674         *addressLength = sizeof(struct nx_bsd_sockaddr_in6);
7675     }
7676     else
7677 #endif /* FEATURE_NX_IPV6 */
7678     {
7679 
7680         /* Not a valid address family. */
7681         /* Release the protection mutex.  */
7682         tx_mutex_put(nx_bsd_protection_ptr);
7683 
7684         /* Set the socket error, if socket enabled with extended BSD features. */
7685         nx_bsd_set_errno(ESOCKTNOSUPPORT);
7686 
7687         /* Return error.  */
7688         NX_BSD_ERROR(ERROR, __LINE__);
7689         return(ERROR);
7690     }
7691 
7692     /* Is the socket still in use?  */
7693     if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
7694     {
7695 
7696         /* Error, socket not in use anymore.  */
7697 
7698         /* Release the protection mutex.  */
7699         tx_mutex_put(nx_bsd_protection_ptr);
7700 
7701         /* Set the socket error if extended options enabled. */
7702         nx_bsd_set_errno(EBADF);
7703 
7704         /* Return error.  */
7705         NX_BSD_ERROR(ERROR, __LINE__);
7706         return(ERROR);
7707     }
7708 
7709     /* Check whether TCP or UDP */
7710     if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
7711     {
7712 
7713 #ifndef NX_DISABLE_IPV4
7714         /* TCP Socket.  Determine socket family type. */
7715         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
7716         {
7717 
7718             soc_struct_ptr -> sin_family      =  AF_INET;
7719             soc_struct_ptr -> sin_port        =  htons((USHORT)bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_port);
7720             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);
7721         }
7722         else
7723 #endif /* NX_DISABLE_IPV4 */
7724 #ifdef FEATURE_NX_IPV6
7725         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
7726         {
7727 
7728             soc6_struct_ptr -> sin6_family    =  AF_INET6;
7729             soc6_struct_ptr -> sin6_port      =  htons((USHORT)bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_port);
7730             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]);
7731             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]);
7732             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]);
7733             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]);
7734         }
7735         else
7736 #endif  /* FEATURE_NX_IPV6 */
7737         {
7738 
7739             /* Release the protection mutex.  */
7740             tx_mutex_put(nx_bsd_protection_ptr);
7741 
7742             /* Set the socket error if extended options enabled. */
7743             nx_bsd_set_errno(EBADF);
7744 
7745             /* Return error.  */
7746             NX_BSD_ERROR(ERROR, __LINE__);
7747             return(ERROR);
7748 
7749         }
7750     }
7751     else if (bsd_socket_ptr -> nx_bsd_socket_udp_socket)
7752     {
7753 
7754 #ifndef NX_DISABLE_IPV4
7755         /* UDP Socket.  Get Peer Name doesn't apply to UDP sockets.  Only fill in AF family information.*/
7756         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
7757         {
7758             soc_struct_ptr -> sin_family      =  AF_INET;
7759             soc_struct_ptr -> sin_port        =  0;
7760             soc_struct_ptr -> sin_addr.s_addr =  0;
7761         }
7762         else
7763 #endif /* NX_DISABLE_IPV4 */
7764 #ifdef FEATURE_NX_IPV6
7765         if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
7766         {
7767             soc6_struct_ptr -> sin6_family    =  AF_INET6;
7768             soc6_struct_ptr -> sin6_port      =  0;
7769         }
7770         else
7771 #endif /* FEATURE_NX_IPV6 */
7772         {
7773 
7774             /* Release the protection mutex.  */
7775             tx_mutex_put(nx_bsd_protection_ptr);
7776 
7777             /* Set the socket error, if socket enabled with extended BSD features. */
7778             nx_bsd_set_errno(ESOCKTNOSUPPORT);
7779 
7780             /* Return error.  */
7781             NX_BSD_ERROR(ERROR, __LINE__);
7782             return(ERROR);
7783 
7784         }
7785     }
7786     else
7787     {
7788 
7789         /* Release the protection mutex.  */
7790         tx_mutex_put(nx_bsd_protection_ptr);
7791 
7792         /* Set the socket error, if socket enabled with extended BSD features. */
7793         nx_bsd_set_errno(ESOCKTNOSUPPORT);
7794 
7795         /* Return error.  */
7796         NX_BSD_ERROR(ERROR, __LINE__);
7797         return(ERROR);
7798     }
7799 
7800 
7801     /* Release the protection mutex.  */
7802     tx_mutex_put(nx_bsd_protection_ptr);
7803 
7804     /* Success!  */
7805     return(NX_SOC_OK);
7806 }
7807 
7808 /**************************************************************************/
7809 /*                                                                        */
7810 /*  FUNCTION                                               RELEASE        */
7811 /*                                                                        */
7812 /*    select                                              PORTABLE C      */
7813 /*                                                           6.3.0        */
7814 /*  AUTHOR                                                                */
7815 /*                                                                        */
7816 /*    Yuxin Zhou, Microsoft Corporation                                   */
7817 /*                                                                        */
7818 /*  DESCRIPTION                                                           */
7819 /*                                                                        */
7820 /*    This function allows for sockets to be checked for incoming packets.*/
7821 /*    nfds should be one greater than value of the largest valued socket  */
7822 /*    descriptor in any of the lists. If you don't wish to calculate this,*/
7823 /*    use FD_SETSIZE instead.For small numbers of sockets,select() will be*/
7824 /*    less efficient if FD_SETSIZE is passed.If the bit corresponding to  */
7825 /*    a socket in an fd_set is set,that socket will be checked for the    */
7826 /*    condition the fd_set corresponds to.If the condition they are       */
7827 /*    checked for is true, they will still be set to true when select()   */
7828 /*    returns (otherwise they will be set to false).                      */
7829 /*    Note that the sets are modified by select():thus they must be reset */
7830 /*    between each call to the function.                                  */
7831 /*                                                                        */
7832 /*    fd_sets can be manipulated using the following macros or functions: */
7833 /*                                                                        */
7834 /*    FD_SET(fd, fdset)  Sets socket fd in fdset to true.                 */
7835 /*    FD_CLR(fd, fdset)  Sets socket fd in fdset to false.                */
7836 /*    FD_ISSET(fd, fdset)Returns true if socket fd is set to true in fdset*/
7837 /*    FD_ZERO(fdset)  Sets all the sockets in fdset to false.             */
7838 /*                                                                        */
7839 /*    If the input timeout is NULL, select() blocks until one of the      */
7840 /*    sockets receives a packet. If the timeout is non-NULL, select waits */
7841 /*    for the specified time and returns regardless if any socket has     */
7842 /*    received a packet.  Otherwise as soon as a socket receives a packet */
7843 /*    this function will return immediately.                              */
7844 /*                                                                        */
7845 /*    To use select() in non-blocking mode call it with a non-null timeout*/
7846 /*    input but set tv_sec and tv_usec to zero, in Unix fashion.          */
7847 /*                                                                        */
7848 /*    select() returns the number of sockets for which the specified      */
7849 /*    conditions are true. If it encounters an error, it will return -1.  */
7850 /*                                                                        */
7851 /*    NOTE:  ****** When select returns NX_SOC_ERROR it won't update      */
7852 /*           the readfds descriptor.                                      */
7853 /*                                                                        */
7854 /*  INPUT                                                                 */
7855 /*                                                                        */
7856 /*    nfds                                 Maximum socket descriptor #    */
7857 /*    fd_set *readFDs                      List of read ready sockets     */
7858 /*    fd_set *writeFDs                     List of write ready sockets    */
7859 /*    fd_set *exceptFDs                    List of exceptions             */
7860 /*    struct timeval *timeOut                                             */
7861 /*                                                                        */
7862 /*  OUTPUT                                                                */
7863 /*                                                                        */
7864 /*    NX_SUCCESS                            No descriptors read           */
7865 /*                                             (successful completion)    */
7866 /*    status                                Number of descriptors read    */
7867 /*                                             (< 0 if error occurred)    */
7868 /*                                                                        */
7869 /*  CALLS                                                                 */
7870 /*                                                                        */
7871 /*    FD_ZERO                               Clear a socket ready list     */
7872 /*    FD_ISSET                              Check a socket is ready       */
7873 /*    FD_SET                                Set a socket to check         */
7874 /*    nx_tcp_socket_receive                 Receive TCP packet            */
7875 /*    nx_udp_source_extract                 Extract source IP and port    */
7876 /*    tx_event_flags_get                    Get events                    */
7877 /*    tx_mutex_get                          Get protection                */
7878 /*    tx_mutex_put                          Release protection            */
7879 /*    tx_thread_identify                    Get current thread pointer    */
7880 /*    tx_thread_preemption_change           Disable/restore preemption    */
7881 /*                                                                        */
7882 /*  CALLED BY                                                             */
7883 /*                                                                        */
7884 /*    Application Code                                                    */
7885 /*                                                                        */
7886 /*  RELEASE HISTORY                                                       */
7887 /*                                                                        */
7888 /*    DATE              NAME                      DESCRIPTION             */
7889 /*                                                                        */
7890 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
7891 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
7892 /*                                            resulting in version 6.1    */
7893 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
7894 /*                                            used new API/structs naming,*/
7895 /*                                            resulting in version 6.3.0  */
7896 /*                                                                        */
7897 /**************************************************************************/
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)7898 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)
7899 {
7900 
7901 INT                     i;
7902 UINT                    status;
7903 NX_BSD_SOCKET_SUSPEND   suspend_request;
7904 NX_PACKET               *packet_ptr;
7905 nx_bsd_fd_set           readfds_found;
7906 nx_bsd_fd_set           writefds_found;
7907 nx_bsd_fd_set           exceptfds_found;
7908 INT                     readfds_left;
7909 INT                     writefds_left;
7910 INT                     exceptfds_left;
7911 ULONG                   ticks;
7912 UINT                    original_threshold;
7913 TX_THREAD               *current_thread_ptr;
7914 INT                     ret;
7915 
7916 
7917     /* Check for valid input parameters.  */
7918     if ((readfds == NX_NULL) && (writefds == NX_NULL) && (exceptfds == NX_NULL) && (timeout == NX_NULL))
7919     {
7920 
7921         /* Set the socket error if extended socket options enabled. */
7922         nx_bsd_set_errno(EINVAL);
7923 
7924         /* Return an error.  */
7925         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7926         return(NX_SOC_ERROR);
7927     }
7928 
7929     /* Check the maximum number of file descriptors.  */
7930     if((nfds < (NX_BSD_SOCKFD_START + 1)) || (nfds >= (NX_BSD_MAX_SOCKETS + NX_BSD_SOCKFD_START + 1)))
7931     {
7932 
7933         /* Set the socket error */
7934         nx_bsd_set_errno(EBADF);
7935 
7936         /* Return an error.  */
7937         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7938         return(NX_SOC_ERROR);
7939     }
7940 
7941     /* Clear the read and the write selector set.  */
7942     NX_BSD_FD_ZERO(&readfds_found);
7943     NX_BSD_FD_ZERO(&writefds_found);
7944     NX_BSD_FD_ZERO(&exceptfds_found);
7945 
7946     if(readfds)
7947         readfds_left = readfds -> fd_count;
7948     else
7949         readfds_left = 0;
7950 
7951     if(writefds)
7952     {
7953 
7954         writefds_left = writefds -> fd_count;
7955     }
7956     else
7957     {
7958 
7959         writefds_left = 0;
7960     }
7961 
7962     if(exceptfds)
7963     {
7964 
7965         exceptfds_left = exceptfds -> fd_count;
7966     }
7967     else
7968     {
7969 
7970         exceptfds_left = 0;
7971     }
7972 
7973     /* Compute the timeout for the suspension if a timeout value was supplied.  */
7974     if (timeout != NX_NULL)
7975     {
7976 
7977         /* Calculate ticks for the ThreadX Timer.  */
7978         ticks = (ULONG)(timeout -> tv_usec)/NX_MICROSECOND_PER_CPU_TICK + (ULONG)(timeout -> tv_sec) * NX_IP_PERIODIC_RATE;
7979     }
7980     else
7981     {
7982 
7983         /* If no timeout input, set the wait to 'forever.'  */
7984         ticks =  TX_WAIT_FOREVER;
7985     }
7986 
7987     /* Get the protection mutex.  */
7988     status =  tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
7989 
7990     /* Check the status.  */
7991     if (status != NX_SUCCESS)
7992     {
7993 
7994         /* Set the socket error if extended socket options enabled. */
7995         nx_bsd_set_errno(EACCES);
7996 
7997         /* Set the socket error. */
7998         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
7999         return(NX_SOC_ERROR);
8000     }
8001 
8002     /* Loop through the BSD sockets to see if the read ready request can be satisfied.  */
8003     for (i = 0; i < (nfds - NX_BSD_SOCKFD_START); i++)
8004     {
8005 
8006         if((readfds == NX_NULL) || (readfds_left == 0))
8007             break;
8008 
8009         /* Is this socket selected for read?  */
8010         if (NX_BSD_FD_ISSET((i + NX_BSD_SOCKFD_START), readfds))
8011         {
8012 
8013             /* Yes, decrement the number of read selectors left to search for.  */
8014             readfds_left--;
8015 
8016             /* Is this BSD socket in use?  */
8017             if (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
8018             {
8019 
8020                 /* There is; add this socket to the read ready list.  */
8021                 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
8022             }
8023 
8024             /* Check to see if there is a disconnection request pending.  */
8025             else if (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_DISCONNECTION_REQUEST)
8026             {
8027 
8028                 /* There is; add this socket to the read ready list.  */
8029                 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
8030             }
8031 
8032             /* Check to see if there is a receive packet pending.  */
8033             else if (nx_bsd_socket_array[i].nx_bsd_socket_received_packet)
8034             {
8035 
8036                 /* Therer is; add this socket to the read ready list.  */
8037                 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
8038             }
8039             /* Is this a TCP socket? */
8040             else if (nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket)
8041             {
8042                 /* Check if this is a master socket and if its associated secondary socket
8043                     is connected. If it is, the master socket should be considered readable. */
8044                 if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET)
8045                 {
8046 
8047                     if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN)
8048                     {
8049 
8050                         /* If the secondary socket does not exist, try to allocate one. */
8051                         if(nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id >= NX_BSD_MAX_SOCKETS)
8052                         {
8053 
8054                             /* This secondary socket is not avaialble yet.  This could happen if the
8055                                previous accept call fails to allocate a new secondary socket. */
8056                             ret = nx_bsd_tcp_create_listen_socket(i, 0);
8057 
8058                             if(ret < 0)
8059                             {
8060 
8061                                 /* Mark the FD set so the application could be notified. */
8062                                 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
8063                             }
8064                         }
8065 
8066                         if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
8067                         {
8068                             NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
8069                         }
8070                     }
8071                 }
8072                 else if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
8073                 {
8074 
8075                     /* Yes; attempt to perform a non-blocking read.  */
8076                     status =  nx_tcp_socket_receive(nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket, &packet_ptr, TX_NO_WAIT);
8077 
8078                     /* Check for success.  */
8079                     if (status == NX_SUCCESS)
8080                     {
8081 
8082                         /* Save the received packet in the TCP BSD socket packet pointer.  */
8083                         nx_bsd_socket_array[i].nx_bsd_socket_received_packet =  packet_ptr;
8084 
8085                         /* Reset the packet offset.  */
8086                         nx_bsd_socket_array[i].nx_bsd_socket_received_packet_offset =  0;
8087 
8088                         /* Increase the received count. */
8089                         nx_bsd_socket_array[i].nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
8090                         nx_bsd_socket_array[i].nx_bsd_socket_received_packet_count++;
8091 
8092                         /* Add this socket to the read ready list.  */
8093                         NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
8094                     }
8095                 }
8096             }
8097 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
8098             /* Is this a raw socket? */
8099             else if (nx_bsd_socket_array[i].nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET)
8100             {
8101 
8102                 /* Check the raw receive queue (by definition has a zero wait option (no suspension)).  */
8103                 status = nx_bsd_raw_packet_receive(&nx_bsd_socket_array[i], &packet_ptr);
8104 
8105                 /* Determine if we have a packet.  */
8106                 if ((status == NX_SUCCESS) && (packet_ptr))
8107                 {
8108 
8109                     /* Get the sender IP address from the raw packet.  */
8110                     status = nx_bsd_raw_packet_info_extract(packet_ptr, &(nx_bsd_socket_array[i].nx_bsd_socket_source_ip_address), NX_NULL);
8111 
8112                     /* Save the received packet in the BSD socket packet pointer.  */
8113                     nx_bsd_socket_array[i].nx_bsd_socket_received_packet =  packet_ptr;
8114 
8115                     /* Reset the packet offset.  */
8116                     nx_bsd_socket_array[i].nx_bsd_socket_received_packet_offset =  0;
8117 
8118                     /* Add this socket to the read ready list.  */
8119                     NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
8120                 }
8121             }
8122 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
8123 
8124         }
8125     }
8126     /* Loop through the BSD sockets to see if the write ready request can be satisfied.  */
8127     for(i = 0; i < (nfds - NX_BSD_SOCKFD_START); i++)
8128     {
8129 
8130         if((writefds == NX_NULL) || (writefds_left == 0))
8131             break;
8132 
8133         /* Is this socket selected for write?  */
8134         if (NX_BSD_FD_ISSET(i + NX_BSD_SOCKFD_START, writefds))
8135         {
8136 
8137             /* Yes, decrement the number of read selectors left to search for.  */
8138             writefds_left--;
8139 
8140             /* Is this BSD socket in use?  */
8141             if (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
8142             {
8143 
8144                 /* Yes, add this socket to the write ready list.  */
8145                 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &writefds_found);
8146             }
8147 
8148             /* Check to see if there is a connection request pending.  */
8149             else if (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_REQUEST)
8150             {
8151 
8152                 /* Yes, add this socket to the write ready list.  */
8153                 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &writefds_found);
8154             }
8155 
8156             /* Check to see if there is an error.*/
8157             else if (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
8158             {
8159 
8160                 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &writefds_found);
8161             }
8162         }
8163     }
8164 
8165     /* Loop through the BSD sockets to see if the exception request can be satisfied.  */
8166     for(i = 0; i < (nfds - NX_BSD_SOCKFD_START); i++)
8167     {
8168 
8169         if((exceptfds == NX_NULL) || (exceptfds_left == 0))
8170             break;
8171 
8172         /* Is this socket selected for exceptions?  */
8173         if (NX_BSD_FD_ISSET(i + NX_BSD_SOCKFD_START, exceptfds))
8174         {
8175 
8176             /* Yes, decrement the number of read selectors left to search for.  */
8177             exceptfds_left--;
8178 
8179             /* Is this BSD socket in use?  */
8180             if (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
8181             {
8182 
8183                 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &exceptfds_found);
8184             }
8185 
8186             /* Check to see if there is an error.*/
8187             else if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
8188             {
8189 
8190                 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &exceptfds_found);
8191             }
8192         }
8193     }
8194 
8195     /* Now determine if we have found anything that satisfies the select request.  */
8196     if (readfds_found.fd_count || writefds_found.fd_count || exceptfds_found.fd_count)
8197     {
8198 
8199         /* Yes, return what we have and we're done.   */
8200 
8201         /* Copy over the requested read ready fds.  */
8202         if(readfds)
8203             *readfds =  readfds_found;
8204 
8205         if(writefds)
8206             *writefds = writefds_found;
8207 
8208         if(exceptfds)
8209             *exceptfds = exceptfds_found;
8210 
8211         /* Release the protection mutex.  */
8212         tx_mutex_put(nx_bsd_protection_ptr);
8213 
8214         /* Return the number of fds found.  */
8215         return(readfds_found.fd_count + writefds_found.fd_count + exceptfds_found.fd_count);
8216     }
8217 
8218     /* Otherwise, nothing is ready to be read at this point.  */
8219 
8220     /* Pickup the current thread.  */
8221     current_thread_ptr =  tx_thread_identify();
8222 
8223     /* Save the fd requests in the local suspension structure. This will be used by the receive notify routines to
8224        wakeup threads on the select.  */
8225     suspend_request.nx_bsd_socket_suspend_actual_flags =  0;
8226 
8227     if(readfds)
8228         suspend_request.nx_bsd_socket_suspend_read_fd_set =  *readfds;
8229     else
8230         NX_BSD_FD_ZERO(&suspend_request.nx_bsd_socket_suspend_read_fd_set);
8231 
8232     if(writefds)
8233         suspend_request.nx_bsd_socket_suspend_write_fd_set = *writefds;
8234     else
8235         NX_BSD_FD_ZERO(&suspend_request.nx_bsd_socket_suspend_write_fd_set);
8236 
8237     if(exceptfds)
8238         suspend_request.nx_bsd_socket_suspend_exception_fd_set = *exceptfds;
8239     else
8240         NX_BSD_FD_ZERO(&suspend_request.nx_bsd_socket_suspend_exception_fd_set);
8241 
8242     /* Temporarily disable preemption.  */
8243     tx_thread_preemption_change(current_thread_ptr, 0, &original_threshold);
8244 
8245     /* Release the protection mutex.  */
8246     tx_mutex_put(nx_bsd_protection_ptr);
8247 
8248     status =  tx_event_flags_get(&nx_bsd_events, NX_BSD_SELECT_EVENT, TX_OR_CLEAR, (ULONG *) &suspend_request, ticks);
8249 
8250     /* Restore original preemption threshold.  */
8251     tx_thread_preemption_change(current_thread_ptr, original_threshold, &original_threshold);
8252 
8253     /* Check for an error.  */
8254     if (status != NX_SUCCESS)
8255     {
8256 
8257         /* If we got here, we received no packets. */
8258 
8259         /* TX_NO_EVENT implies an immediate return from the flag get call.
8260            This happens if the wait option is set to zero. */
8261         if (status == TX_NO_EVENTS)
8262         {
8263 
8264             /* Determine if the effected sockets are non blocking (zero ticks for the wait option). */
8265             if (ticks == 0)
8266                 nx_bsd_set_errno(EWOULDBLOCK);
8267             else
8268                 nx_bsd_set_errno(ETIMEDOUT);
8269 
8270             /* Do not handle as an error; just a timeout so return 0.  */
8271             return(0);
8272         }
8273         else
8274         {
8275 
8276             /* Actual error.  */
8277             /* Set the socket error if extended socket options enabled. */
8278             nx_bsd_set_errno(EINVAL);
8279 
8280             /* Error getting the protection mutex.  */
8281             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
8282             return(NX_SOC_ERROR);
8283         }
8284     }
8285     else
8286     {
8287 
8288         /* Otherwise, a receive event has been found. Simply copy the receive events.  */
8289         if(readfds)
8290             *readfds =  suspend_request.nx_bsd_socket_suspend_read_fd_set;
8291         if(writefds)
8292             *writefds = suspend_request.nx_bsd_socket_suspend_write_fd_set;
8293         if(exceptfds)
8294             *exceptfds = suspend_request.nx_bsd_socket_suspend_exception_fd_set;
8295 
8296         /* Return the number of fds.  */
8297         return(suspend_request.nx_bsd_socket_suspend_read_fd_set.fd_count +
8298                suspend_request.nx_bsd_socket_suspend_write_fd_set.fd_count +
8299                suspend_request.nx_bsd_socket_suspend_exception_fd_set.fd_count);
8300     }
8301 
8302 
8303 }
8304 
8305 
8306 
8307 /**************************************************************************/
8308 /*                                                                        */
8309 /*  FUNCTION                                               RELEASE        */
8310 /*                                                                        */
8311 /*    nx_bsd_tcp_receive_notify                           PORTABLE C      */
8312 /*                                                           6.1          */
8313 /*  AUTHOR                                                                */
8314 /*                                                                        */
8315 /*    Yuxin Zhou, Microsoft Corporation                                   */
8316 /*                                                                        */
8317 /*  DESCRIPTION                                                           */
8318 /*                                                                        */
8319 /*    This is the NetX callback function for TCP Socket receive operation */
8320 /*    This function resumes all the threads suspended on the socket.      */
8321 /*                                                                        */
8322 /*  INPUT                                                                 */
8323 /*                                                                        */
8324 /*    *socket_ptr                           Pointer to the socket which   */
8325 /*                                            received the data packet    */
8326 /*                                                                        */
8327 /*  OUTPUT                                                                */
8328 /*                                                                        */
8329 /*    None                                                                */
8330 /*                                                                        */
8331 /*  CALLS                                                                 */
8332 /*                                                                        */
8333 /*    FD_ZERO                               Clear a socket ready list     */
8334 /*    FD_ISSET                              Check a socket is ready       */
8335 /*    FD_SET                                Set a socket to check         */
8336 /*    tx_event_flags_get                    Get events                    */
8337 /*    tx_mutex_get                          Get protection                */
8338 /*    tx_mutex_put                          Release protection            */
8339 /*    tx_thread_identify                    Get current thread pointer    */
8340 /*                                                                        */
8341 /*  CALLED BY                                                             */
8342 /*                                                                        */
8343 /*    NetX                                                                */
8344 /*                                                                        */
8345 /*  RELEASE HISTORY                                                       */
8346 /*                                                                        */
8347 /*    DATE              NAME                      DESCRIPTION             */
8348 /*                                                                        */
8349 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8350 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8351 /*                                            resulting in version 6.1    */
8352 /*                                                                        */
8353 /**************************************************************************/
nx_bsd_tcp_receive_notify(NX_TCP_SOCKET * socket_ptr)8354 static VOID  nx_bsd_tcp_receive_notify(NX_TCP_SOCKET *socket_ptr)
8355 {
8356 UINT                    bsd_socket_index;
8357 
8358     /* Figure out what BSD socket this is.  */
8359     bsd_socket_index =  (UINT) socket_ptr -> nx_tcp_socket_reserved_ptr;
8360 
8361     /* Determine if this is a good index into the BSD socket array.  */
8362     if (bsd_socket_index >= NX_BSD_MAX_SOCKETS)
8363     {
8364 
8365         /* Bad socket index... simply return!  */
8366         return;
8367     }
8368 
8369     /* Now check if the socket may have been released (e.g. socket closed) while
8370        waiting for the mutex. */
8371     if( socket_ptr -> nx_tcp_socket_id == 0 )
8372     {
8373 
8374         return;
8375     }
8376 
8377     /* Check the suspended socket list for one ready to receive or send packets. */
8378     nx_bsd_select_wakeup(bsd_socket_index, FDSET_READ);
8379 
8380 
8381     return;
8382 }
8383 
8384 
8385 /**************************************************************************/
8386 /*                                                                        */
8387 /*  FUNCTION                                               RELEASE        */
8388 /*                                                                        */
8389 /*    nx_bsd_tcp_establish_notify                         PORTABLE C      */
8390 /*                                                           6.1          */
8391 /*  AUTHOR                                                                */
8392 /*                                                                        */
8393 /*    Yuxin Zhou, Microsoft Corporation                                   */
8394 /*                                                                        */
8395 /*  DESCRIPTION                                                           */
8396 /*                                                                        */
8397 /*    This is the NetX callback function for TCP Server Socket listen.    */
8398 /*    This function resumes all the threads suspended on the socket.      */
8399 /*                                                                        */
8400 /*  INPUT                                                                 */
8401 /*                                                                        */
8402 /*    *socket_ptr                           Pointer to the socket which   */
8403 /*                                          Received the data packet      */
8404 /*                                                                        */
8405 /*  OUTPUT                                                                */
8406 /*                                                                        */
8407 /*    None                                                                */
8408 /*                                                                        */
8409 /*  CALLS                                                                 */
8410 /*                                                                        */
8411 /*    FD_ZERO                               Clear a socket ready list     */
8412 /*    FD_ISSET                              Check a socket is ready       */
8413 /*    FD_SET                                Set a socket to check         */
8414 /*    tx_event_flags_get                    Get events                    */
8415 /*    tx_mutex_get                          Get protection                */
8416 /*    tx_mutex_put                          Release protection            */
8417 /*    tx_thread_identify                    Get current thread pointer    */
8418 /*                                                                        */
8419 /*  CALLED BY                                                             */
8420 /*                                                                        */
8421 /*    NetX                                                                */
8422 /*                                                                        */
8423 /*  RELEASE HISTORY                                                       */
8424 /*                                                                        */
8425 /*    DATE              NAME                      DESCRIPTION             */
8426 /*                                                                        */
8427 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8428 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8429 /*                                            resulting in version 6.1    */
8430 /*                                                                        */
8431 /**************************************************************************/
8432 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
nx_bsd_tcp_establish_notify(NX_TCP_SOCKET * socket_ptr)8433 static VOID  nx_bsd_tcp_establish_notify(NX_TCP_SOCKET *socket_ptr)
8434 {
8435 UINT                    bsd_socket_index;
8436 UINT                    master_socket_index;
8437 
8438     /* Figure out what BSD socket this is.  */
8439     bsd_socket_index =  (UINT) socket_ptr -> nx_tcp_socket_reserved_ptr;
8440 
8441     /* Determine if this is a good index into the BSD socket array.  */
8442     if (bsd_socket_index >= NX_BSD_MAX_SOCKETS)
8443     {
8444 
8445         /* Bad socket index... simply return!  */
8446         return;
8447     }
8448 
8449     /* Initialize the master socket index to an invalid value so we can check if it was actually used
8450        later.  */
8451     master_socket_index =  NX_BSD_MAX_SOCKETS;
8452 
8453     /* Mark the socket as connected, and also clear the EINPROGRESS flag */
8454     nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
8455 
8456     nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags |=  NX_BSD_SOCKET_CONNECTION_REQUEST;
8457 
8458     /* Reset the listen-enabled flag. */
8459     nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_LISTEN);
8460 
8461     /* Mark the socket is bound. */
8462     nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
8463 
8464 #ifndef NX_DISABLE_IPV4
8465     /* Find out the local address this socket is connected on. */
8466     if(nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_family == AF_INET)
8467     {
8468         /* IPv4 case */
8469         nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_local_bind_interface = (ULONG)socket_ptr -> nx_tcp_socket_connect_interface;
8470     }
8471 #endif /* NX_DISABLE_IPV4 */
8472 #ifdef FEATURE_NX_IPV6
8473     if(nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_family == AF_INET6)
8474     {
8475         /* IPv6 */
8476         nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_local_bind_interface = (ULONG)socket_ptr -> nx_tcp_socket_ipv6_addr;
8477     }
8478 #endif
8479     /* Determine if the BSD socket is server socket. */
8480 
8481 
8482     /* Is this a secondary socket? */
8483     if (nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET)
8484     {
8485 
8486         /* Yes, get the master socket.  */
8487         master_socket_index =  (UINT)(nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_union_id.nx_bsd_socket_master_socket_id);
8488 
8489         /* Mark the server socket as also connected. */
8490         nx_bsd_socket_array[master_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
8491 
8492         nx_bsd_socket_array[master_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_REQUEST;
8493 
8494         /* Check on connect requests for all server sockets for this master socket. */
8495         nx_bsd_select_wakeup(master_socket_index, FDSET_READ);
8496     }
8497     else
8498     {
8499         /* This is a client socket. */
8500         nx_bsd_select_wakeup(bsd_socket_index, FDSET_WRITE);
8501     }
8502 }
8503 #endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */
8504 
8505 /**************************************************************************/
8506 /*                                                                        */
8507 /*  FUNCTION                                               RELEASE        */
8508 /*                                                                        */
8509 /*    nx_bsd_tcp_socket_disconnect_notify                 PORTABLE C      */
8510 /*                                                           6.1          */
8511 /*  AUTHOR                                                                */
8512 /*                                                                        */
8513 /*    Yuxin Zhou, Microsoft Corporation                                   */
8514 /*                                                                        */
8515 /*  DESCRIPTION                                                           */
8516 /*                                                                        */
8517 /*    This is the NetX callback function for TCP Socket disconnect.       */
8518 /*    This function resumes all the BSD threads suspended on the socket.  */
8519 /*                                                                        */
8520 /*  INPUT                                                                 */
8521 /*                                                                        */
8522 /*    *socket_ptr                           Pointer to the socket which   */
8523 /*                                            received the data packet    */
8524 /*                                                                        */
8525 /*  OUTPUT                                                                */
8526 /*                                                                        */
8527 /*    None                                                                */
8528 /*                                                                        */
8529 /*  CALLS                                                                 */
8530 /*                                                                        */
8531 /*    FD_ZERO                               Clear a socket ready list     */
8532 /*    FD_ISSET                              Check a socket is ready       */
8533 /*    FD_SET                                Set a socket to check         */
8534 /*    tx_event_flags_get                    Get events                    */
8535 /*    tx_mutex_get                          Get protection                */
8536 /*    tx_mutex_put                          Release protection            */
8537 /*    tx_thread_identify                    Get current thread pointer    */
8538 /*                                                                        */
8539 /*  CALLED BY                                                             */
8540 /*                                                                        */
8541 /*    NetX                                                                */
8542 /*                                                                        */
8543 /*  RELEASE HISTORY                                                       */
8544 /*                                                                        */
8545 /*    DATE              NAME                      DESCRIPTION             */
8546 /*                                                                        */
8547 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8548 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8549 /*                                            resulting in version 6.1    */
8550 /*                                                                        */
8551 /**************************************************************************/
nx_bsd_tcp_socket_disconnect_notify(NX_TCP_SOCKET * socket_ptr)8552 static VOID  nx_bsd_tcp_socket_disconnect_notify(NX_TCP_SOCKET *socket_ptr)
8553 {
8554 
8555 UINT                    bsd_socket_index;
8556 UINT                    master_socket_index;
8557 NX_BSD_SOCKET          *bsd_socket_ptr;
8558 UINT                    status;
8559 
8560 
8561     /* Figure out what BSD socket this is.  */
8562     bsd_socket_index =  (UINT) socket_ptr -> nx_tcp_socket_reserved_ptr;
8563 
8564     /* Determine if this is a good index into the BSD socket array.  */
8565     if (bsd_socket_index >= NX_BSD_MAX_SOCKETS)
8566     {
8567         /* No good! */
8568         return;
8569     }
8570 
8571     bsd_socket_ptr = &nx_bsd_socket_array[bsd_socket_index];
8572 
8573     /* If the socket already received a disconnect request, no need to do anything here. */
8574     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_DISCONNECTION_REQUEST)
8575     {
8576         return;
8577     }
8578 
8579     /* Mark this socket as having a disconnect request pending.  */
8580     bsd_socket_ptr -> nx_bsd_socket_status_flags |=  NX_BSD_SOCKET_DISCONNECTION_REQUEST;
8581 
8582     /* Is the socket trying to make a connection? */
8583     if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_INPROGRESS)
8584     {
8585 
8586         /* Yes, clear the INPROGRESS flag. */
8587         bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
8588 
8589         /* If this is secondary server socket, there is no need to wake up the select call.  */
8590         if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET)
8591         {
8592 
8593 
8594             /* Instead the socket needs to be cleaned up and to perform a relisten. */
8595             if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED))
8596             {
8597 
8598                 /* Turn off the disconnection_request flag. */
8599                 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_DISCONNECTION_REQUEST);
8600 
8601                 nx_tcp_server_socket_unaccept(bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
8602 
8603                 /* Check if a listen request is queued up for this socket. */
8604                 nx_bsd_tcp_pending_connection(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port,
8605                                               bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
8606 
8607                 status = nx_tcp_server_socket_relisten(nx_bsd_default_ip,
8608                                                        bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port,
8609                                                        bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
8610 
8611                 /* Force the socket into SYN_RECEIVED state */
8612                 nx_tcp_server_socket_accept(bsd_socket_ptr -> nx_bsd_socket_tcp_socket, NX_NO_WAIT);
8613 
8614                 if(status == NX_CONNECTION_PENDING)
8615                 {
8616 
8617                     bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
8618                 }
8619                 else if(status != NX_SUCCESS)
8620                 {
8621 
8622                     /* Failed the relisten on the secondary socket.  Set the error code on the
8623                        master socket, and wake it up. */
8624 
8625                     master_socket_index = (UINT)(bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id;
8626 
8627                     nx_bsd_socket_array[master_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
8628                     nx_bsd_set_error_code(&nx_bsd_socket_array[master_socket_index], status);
8629 
8630                     nx_bsd_select_wakeup(master_socket_index, (FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION));
8631                 }
8632             }
8633 
8634         }
8635         else
8636         {
8637 
8638             /* Set error code. */
8639             bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
8640             bsd_socket_ptr -> nx_bsd_socket_error_code = ECONNREFUSED;
8641 
8642             /* Wake up the select on both read and write FDsets. */
8643             nx_bsd_select_wakeup(bsd_socket_index, (FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION));
8644         }
8645     }
8646     else if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
8647     {
8648 
8649         /* Wake up the select on both read and write FDsets. */
8650         nx_bsd_select_wakeup(bsd_socket_index, (FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION));
8651     }
8652     else
8653     {
8654 
8655         /* In this case, connection reaches maximum retries or is refused by peer. */
8656         bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
8657         bsd_socket_ptr -> nx_bsd_socket_error_code = ENOTCONN;
8658     }
8659 
8660 }
8661 
8662 
8663 
8664 /**************************************************************************/
8665 /*                                                                        */
8666 /*  FUNCTION                                               RELEASE        */
8667 /*                                                                        */
8668 /*    nx_bsd_udp_receive_notify                           PORTABLE C      */
8669 /*                                                           6.1          */
8670 /*  AUTHOR                                                                */
8671 /*                                                                        */
8672 /*    Yuxin Zhou, Microsoft Corporation                                   */
8673 /*                                                                        */
8674 /*  DESCRIPTION                                                           */
8675 /*                                                                        */
8676 /*    This is the NetX callback function for UDP Socket receive           */
8677 /*    operation.                                                          */
8678 /*                                                                        */
8679 /*  INPUT                                                                 */
8680 /*                                                                        */
8681 /*    *socket_ptr                           Pointer to the socket which   */
8682 /*                                          Received the data packet      */
8683 /*                                                                        */
8684 /*  OUTPUT                                                                */
8685 /*                                                                        */
8686 /*    None                                                                */
8687 /*                                                                        */
8688 /*  CALLS                                                                 */
8689 /*                                                                        */
8690 /*    FD_ZERO                               Clear a socket ready list     */
8691 /*    FD_ISSET                              Check a socket is ready       */
8692 /*    FD_SET                                Set a socket to check         */
8693 /*    tx_event_flags_get                    Get events                    */
8694 /*    tx_mutex_get                          Get protection                */
8695 /*    tx_mutex_put                          Release protection            */
8696 /*    tx_thread_identify                    Get current thread pointer    */
8697 /*    nx_udp_socket_receive                 Receive UDP packet            */
8698 /*                                                                        */
8699 /*  CALLED BY                                                             */
8700 /*                                                                        */
8701 /*    NetX                                                                */
8702 /*                                                                        */
8703 /*  RELEASE HISTORY                                                       */
8704 /*                                                                        */
8705 /*    DATE              NAME                      DESCRIPTION             */
8706 /*                                                                        */
8707 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8708 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8709 /*                                            resulting in version 6.1    */
8710 /*                                                                        */
8711 /**************************************************************************/
nx_bsd_udp_receive_notify(NX_UDP_SOCKET * socket_ptr)8712 static VOID  nx_bsd_udp_receive_notify(NX_UDP_SOCKET *socket_ptr)
8713 {
8714 
8715 UINT                    bsd_socket_index;
8716 NX_PACKET               *packet_ptr;
8717 NX_UDP_SOCKET           *udp_socket_ptr;
8718 
8719 
8720     /* Figure out what BSD socket this is.  */
8721     bsd_socket_index =  ((UINT) socket_ptr -> nx_udp_socket_reserved_ptr) & 0x0000FFFF;
8722 
8723     /* Determine if this is a good index into the BSD socket array.  */
8724     if (bsd_socket_index >= NX_BSD_MAX_SOCKETS)
8725     {
8726         return;
8727     }
8728 
8729     udp_socket_ptr = nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_udp_socket;
8730 
8731     if (nx_udp_socket_receive(udp_socket_ptr, &packet_ptr, NX_NO_WAIT))
8732     {
8733         return;
8734     }
8735 
8736     nx_bsd_udp_packet_received((INT)bsd_socket_index, packet_ptr);
8737 
8738 }
8739 
8740 
8741 /**************************************************************************/
8742 /*                                                                        */
8743 /*  FUNCTION                                               RELEASE        */
8744 /*                                                                        */
8745 /*    FD_SET                                              PORTABLE C      */
8746 /*                                                           6.3.0        */
8747 /*  AUTHOR                                                                */
8748 /*                                                                        */
8749 /*    Yuxin Zhou, Microsoft Corporation                                   */
8750 /*                                                                        */
8751 /*  DESCRIPTION                                                           */
8752 /*                                                                        */
8753 /*   This function adds a fd to the set.                                  */
8754 /*                                                                        */
8755 /*  INPUT                                                                 */
8756 /*                                                                        */
8757 /*    fd                                    fd to add.                    */
8758 /*    fd_set *fdset                         fd set.                       */
8759 /*                                                                        */
8760 /*  OUTPUT                                                                */
8761 /*                                                                        */
8762 /*    None                                                                */
8763 /*                                                                        */
8764 /*  CALLS                                                                 */
8765 /*                                                                        */
8766 /*    None                                                                */
8767 /*                                                                        */
8768 /*  CALLED BY                                                             */
8769 /*                                                                        */
8770 /*    Application Code                                                    */
8771 /*                                                                        */
8772 /*  RELEASE HISTORY                                                       */
8773 /*                                                                        */
8774 /*    DATE              NAME                      DESCRIPTION             */
8775 /*                                                                        */
8776 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8777 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8778 /*                                            resulting in version 6.1    */
8779 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
8780 /*                                            used new API/structs naming,*/
8781 /*                                            resulting in version 6.3.0  */
8782 /*                                                                        */
8783 /**************************************************************************/
NX_BSD_FD_SET(INT fd,nx_bsd_fd_set * fdset)8784 VOID  NX_BSD_FD_SET(INT fd, nx_bsd_fd_set *fdset)
8785 {
8786 
8787 UINT    index;
8788 
8789 
8790     /* Check the FD size.  */
8791     if (fd >= NX_BSD_SOCKFD_START)
8792     {
8793 
8794         /* Normalize the fd.  */
8795         fd =  fd - NX_BSD_SOCKFD_START;
8796 
8797         /* Now make sure it isn't too big.  */
8798         if (fd < NX_BSD_MAX_SOCKETS)
8799         {
8800 
8801             /* Calculate the index into the bit map.  */
8802             index =  (UINT)fd/32;
8803 
8804             /* Now calculate the bit position.  */
8805             fd =  fd % 32;
8806 
8807             /* Is the bit already set?  */
8808             if ((fdset -> fd_array[index] & (((ULONG) 1) << fd)) == 0)
8809             {
8810 
8811                 /* No, set the bit.  */
8812                 fdset -> fd_array[index] = fdset -> fd_array[index] | (((ULONG) 1) << fd);
8813 
8814                 /* Increment the counter.  */
8815                 fdset -> fd_count++;
8816             }
8817         }
8818     }
8819 }
8820 
8821 /**************************************************************************/
8822 /*                                                                        */
8823 /*  FUNCTION                                               RELEASE        */
8824 /*                                                                        */
8825 /*    FD_CLR                                              PORTABLE C      */
8826 /*                                                           6.3.0        */
8827 /*  AUTHOR                                                                */
8828 /*                                                                        */
8829 /*    Yuxin Zhou, Microsoft Corporation                                   */
8830 /*                                                                        */
8831 /*  DESCRIPTION                                                           */
8832 /*                                                                        */
8833 /*   This function removes a fd from a fd set.                            */
8834 /*                                                                        */
8835 /*  INPUT                                                                 */
8836 /*                                                                        */
8837 /*    fd                                    fd to remove.                 */
8838 /*    fd_set *fdset                         fd set.                       */
8839 /*                                                                        */
8840 /*  OUTPUT                                                                */
8841 /*                                                                        */
8842 /*    None                                                                */
8843 /*                                                                        */
8844 /*  CALLS                                                                 */
8845 /*                                                                        */
8846 /*    None                                                                */
8847 /*                                                                        */
8848 /*  CALLED BY                                                             */
8849 /*                                                                        */
8850 /*    Application Code                                                    */
8851 /*                                                                        */
8852 /*  RELEASE HISTORY                                                       */
8853 /*                                                                        */
8854 /*    DATE              NAME                      DESCRIPTION             */
8855 /*                                                                        */
8856 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8857 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8858 /*                                            resulting in version 6.1    */
8859 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
8860 /*                                            used new API/structs naming,*/
8861 /*                                            resulting in version 6.3.0  */
8862 /*                                                                        */
8863 /**************************************************************************/
NX_BSD_FD_CLR(INT fd,nx_bsd_fd_set * fdset)8864 VOID  NX_BSD_FD_CLR(INT fd, nx_bsd_fd_set *fdset)
8865 {
8866 
8867 UINT    index;
8868 
8869 
8870     /* Check the FD size.  */
8871     if (fd >= NX_BSD_SOCKFD_START)
8872     {
8873 
8874         /* Normalize the fd.  */
8875         fd =  fd - NX_BSD_SOCKFD_START;
8876 
8877         /* Now make sure it isn't too big.  */
8878         if ((fd < NX_BSD_MAX_SOCKETS) && (fdset -> fd_count))
8879         {
8880 
8881             /* Calculate the index into the bit map.  */
8882             index =  (UINT)fd/32;
8883 
8884             /* Now calculate the bit position.  */
8885             fd =  fd % 32;
8886 
8887             /* Determine if the bit is set.  */
8888             if (fdset -> fd_array[index] & (((ULONG) 1) << fd))
8889             {
8890 
8891                 /* Yes, clear the bit.  */
8892                 fdset -> fd_array[index] = fdset -> fd_array[index] & ~(((ULONG) 1) << fd);
8893 
8894                 /* Decrement the counter.  */
8895                 fdset -> fd_count--;
8896             }
8897         }
8898     }
8899 }
8900 
8901 
8902 /**************************************************************************/
8903 /*                                                                        */
8904 /*  FUNCTION                                               RELEASE        */
8905 /*                                                                        */
8906 /*    FD_ISSET                                            PORTABLE C      */
8907 /*                                                           6.1          */
8908 /*  AUTHOR                                                                */
8909 /*                                                                        */
8910 /*    Yuxin Zhou, Microsoft Corporation                                   */
8911 /*                                                                        */
8912 /*  DESCRIPTION                                                           */
8913 /*                                                                        */
8914 /*   This function tests to see if a fd is in the set.                    */
8915 /*                                                                        */
8916 /*  INPUT                                                                 */
8917 /*                                                                        */
8918 /*    fd                                    fd to add.                    */
8919 /*    fd_set *fdset                         fd set.                       */
8920 /*                                                                        */
8921 /*  OUTPUT                                                                */
8922 /*                                                                        */
8923 /*    NX_TRUE                               If fd is found in the set.    */
8924 /*    NX_FALSE                              If fd is not there in the set.*/
8925 /*                                                                        */
8926 /*  CALLS                                                                 */
8927 /*                                                                        */
8928 /*    None                                                                */
8929 /*                                                                        */
8930 /*  CALLED BY                                                             */
8931 /*                                                                        */
8932 /*    Application Code                                                    */
8933 /*                                                                        */
8934 /*  RELEASE HISTORY                                                       */
8935 /*                                                                        */
8936 /*    DATE              NAME                      DESCRIPTION             */
8937 /*                                                                        */
8938 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
8939 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
8940 /*                                            resulting in version 6.1    */
8941 /*                                                                        */
8942 /**************************************************************************/
NX_BSD_FD_ISSET(INT fd,nx_bsd_fd_set * fdset)8943 INT  NX_BSD_FD_ISSET(INT fd, nx_bsd_fd_set *fdset)
8944 {
8945 
8946 UINT    index;
8947 
8948 
8949     /* Check the FD size.  */
8950     if (fd >= NX_BSD_SOCKFD_START)
8951     {
8952 
8953         /* Normalize the fd.  */
8954         fd =  fd - NX_BSD_SOCKFD_START;
8955 
8956         /* Now make sure it isn't too big.  */
8957         if (fd < NX_BSD_MAX_SOCKETS)
8958         {
8959 
8960             /* Calculate the index into the bit map.  */
8961             index =  (UINT)fd/32;
8962 
8963             /* Now calculate the bit position.  */
8964             fd =  fd % 32;
8965 
8966             /* Finally, see if the bit is set.  */
8967             if (fdset -> fd_array[index] & (((ULONG) 1) << fd))
8968             {
8969 
8970                 /* Yes, return true!  */
8971                 return(NX_TRUE);
8972             }
8973         }
8974     }
8975 
8976     /* Otherwise, return false.  */
8977     return(NX_FALSE);
8978 }
8979 
8980 
8981 /**************************************************************************/
8982 /*                                                                        */
8983 /*  FUNCTION                                               RELEASE        */
8984 /*                                                                        */
8985 /*    FD_ZERO                                             PORTABLE C      */
8986 /*                                                           6.3.0        */
8987 /*  AUTHOR                                                                */
8988 /*                                                                        */
8989 /*    Yuxin Zhou, Microsoft Corporation                                   */
8990 /*                                                                        */
8991 /*  DESCRIPTION                                                           */
8992 /*                                                                        */
8993 /*   This function clears a fd set.                                       */
8994 /*                                                                        */
8995 /*  INPUT                                                                 */
8996 /*                                                                        */
8997 /*   fd_set *fdset                          fd set to clear.              */
8998 /*                                                                        */
8999 /*  OUTPUT                                                                */
9000 /*                                                                        */
9001 /*    None                                                                */
9002 /*                                                                        */
9003 /*  CALLS                                                                 */
9004 /*                                                                        */
9005 /*    None                                                                */
9006 /*                                                                        */
9007 /*  CALLED BY                                                             */
9008 /*                                                                        */
9009 /*    Application Code                                                    */
9010 /*                                                                        */
9011 /*  RELEASE HISTORY                                                       */
9012 /*                                                                        */
9013 /*    DATE              NAME                      DESCRIPTION             */
9014 /*                                                                        */
9015 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9016 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9017 /*                                            resulting in version 6.1    */
9018 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
9019 /*                                            used new API/structs naming,*/
9020 /*                                            resulting in version 6.3.0  */
9021 /*                                                                        */
9022 /**************************************************************************/
NX_BSD_FD_ZERO(nx_bsd_fd_set * fdset)9023 VOID  NX_BSD_FD_ZERO(nx_bsd_fd_set *fdset)
9024 {
9025 
9026 INT     i;
9027 
9028 
9029     /* Clear the count.  */
9030     fdset -> fd_count =  0;
9031 
9032     /* Loop to clear the fd set.  */
9033     for (i = 0; i < (NX_BSD_MAX_SOCKETS+31)/32; i++)
9034     {
9035         /* Clear an entry in the array.  */
9036         fdset -> fd_array[i] =  0;
9037     }
9038 }
9039 
9040 
9041 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
9042 /**************************************************************************/
9043 /*                                                                        */
9044 /*  FUNCTION                                               RELEASE        */
9045 /*                                                                        */
9046 /*    nx_bsd_raw_packet_filter                            PORTABLE C      */
9047 /*                                                           6.1.9        */
9048 /*  AUTHOR                                                                */
9049 /*                                                                        */
9050 /*    Yuxin Zhou, Microsoft Corporation                                   */
9051 /*                                                                        */
9052 /*  DESCRIPTION                                                           */
9053 /*                                                                        */
9054 /*    This function receives raw packets from NetX Duo and determines if  */
9055 /*    BSD will consume the packet (store on the BSD socket raw receive    */
9056 /*    queue) or if the packet is available to NetX Duo (not consumed).    */
9057 /*                                                                        */
9058 /*  INPUT                                                                 */
9059 /*                                                                        */
9060 /*    ip_ptr                               NetX Duo IP instance           */
9061 /*    protocol                             Received packet protocol       */
9062 /*    packet_ptr                           Pointer to the received packet */
9063 /*                                                                        */
9064 /*  OUTPUT                                                                */
9065 /*                                                                        */
9066 /*    0                                     Raw filter consumed the packet*/
9067 /*    1                                     Raw filter did not consume    */
9068 /*                                            packet.  Allow the caller to*/
9069 /*                                            process this packet         */
9070 /*                                                                        */
9071 /*  CALLS                                                                 */
9072 /*                                                                        */
9073 /*    nx_bsd_raw_receive_notify             Notify threads waiting to     */
9074 /*                                               receive a raw packet     */
9075 /*                                                                        */
9076 /*  CALLED BY                                                             */
9077 /*                                                                        */
9078 /*    NetX Duo                                                            */
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 /*  10-15-2021     Yuxin Zhou               Modified comment(s),          */
9088 /*                                            fixed NULL pointer access   */
9089 /*                                            for raw socket,             */
9090 /*                                            resulting in version 6.1.9  */
9091 /*                                                                        */
9092 /**************************************************************************/
nx_bsd_raw_packet_filter(NX_IP * ip_ptr,ULONG protocol,NX_PACKET * packet_ptr)9093 static UINT  nx_bsd_raw_packet_filter(NX_IP *ip_ptr, ULONG protocol, NX_PACKET *packet_ptr)
9094 {
9095 
9096 UINT index;
9097 NX_BSD_SOCKET * bsd_socket_ptr;
9098 
9099     /* Calculate the hash index in the raw socket protocol table. */
9100     index = (UINT) ((protocol + (protocol >> 8)) & NX_BSD_SOCKET_RAW_PROTOCOL_TABLE_MASK);
9101 
9102     /* Search the bound sockets in this index for particular protocol. */
9103     bsd_socket_ptr = nx_bsd_socket_raw_protocol_table[index];
9104 
9105     /* Was a BSD socket with this protocol found? */
9106     if (bsd_socket_ptr == NX_NULL)
9107     {
9108         /* No, let NetX Duo continue processing the packet. */
9109         return 1;
9110     }
9111 
9112     do
9113     {
9114         /* Determine if the protocol is matched. */
9115         if ((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE) &&
9116             (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET ) &&
9117             (bsd_socket_ptr -> nx_bsd_socket_protocol == protocol))
9118         {
9119 
9120             /* This packet protocol matches the BSD socket. */
9121             /* Make sure the queue_next is zero'ed out. */
9122             packet_ptr -> nx_packet_queue_next = NX_NULL;
9123 
9124             /* Add the packet to the BSD socket raw packet receive queue.
9125                Are there any packets on this queue yet?  */
9126             if (bsd_socket_ptr -> nx_bsd_socket_received_packet == NX_NULL)
9127             {
9128 
9129                 /* No, this will be the only one. */
9130                 bsd_socket_ptr -> nx_bsd_socket_received_packet = packet_ptr;
9131                 bsd_socket_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
9132 
9133 
9134                 /* Set the packet count. */
9135                 bsd_socket_ptr -> nx_bsd_socket_received_byte_count = packet_ptr -> nx_packet_length;
9136                 bsd_socket_ptr -> nx_bsd_socket_received_packet_count = 1;
9137             }
9138             else
9139             {
9140                 /* Yes; add this packet to the end of the queue. */
9141 
9142                 /* Check if the queue is currently full. */
9143                 if (bsd_socket_ptr -> nx_bsd_socket_received_byte_count_max &&
9144                     (bsd_socket_ptr -> nx_bsd_socket_received_byte_count >=
9145                     bsd_socket_ptr -> nx_bsd_socket_received_byte_count_max))
9146                 {
9147 
9148                     /* Release the packet here, and tell NetX Duo the packet is 'consumed'. */
9149                     nx_packet_release(packet_ptr);
9150 
9151                     return 0;
9152                 }
9153 
9154                 /* Drop the packet if the receive queue exceeds max depth.*/
9155                 if(bsd_socket_ptr -> nx_bsd_socket_received_packet_count >=
9156                    bsd_socket_ptr -> nx_bsd_socket_received_packet_count_max)
9157                 {
9158                     /* Release the packet here, and tell NetX Duo the packet is 'consumed'. */
9159                     nx_packet_release(packet_ptr);
9160 
9161                     return 0;
9162                 }
9163 
9164                 /* Add this packet to the end of the BSD raw receive queue. */
9165                 (bsd_socket_ptr -> nx_bsd_socket_received_packet_tail) -> nx_packet_queue_next = packet_ptr;
9166                 bsd_socket_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
9167 
9168 
9169                 /* Update our packet count. */
9170                 bsd_socket_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
9171                 bsd_socket_ptr -> nx_bsd_socket_received_packet_count++;
9172             }
9173 
9174             /* Notify any suspended threads waiting on this receive event. */
9175             nx_bsd_raw_receive_notify(ip_ptr, (UINT)(bsd_socket_ptr -> nx_bsd_socket_id));
9176 
9177             return 0;
9178         }
9179 
9180     }while(bsd_socket_ptr != nx_bsd_socket_raw_protocol_table[index]);
9181 
9182     /* Was a BSD socket with this protocol found? */
9183     if (bsd_socket_ptr == nx_bsd_socket_raw_protocol_table[index])
9184     {
9185         /* No, let NetX Duo continue processing the packet. */
9186         return 1;
9187     }
9188 
9189     return(NX_SUCCESS);
9190 }
9191 
9192 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
9193 
9194 
9195 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
9196 /**************************************************************************/
9197 /*                                                                        */
9198 /*  FUNCTION                                               RELEASE        */
9199 /*                                                                        */
9200 /*    nx_bsd_raw_receive_notify                           PORTABLE C      */
9201 /*                                                           6.1          */
9202 /*  AUTHOR                                                                */
9203 /*                                                                        */
9204 /*    Yuxin Zhou, Microsoft Corporation                                   */
9205 /*                                                                        */
9206 /*  DESCRIPTION                                                           */
9207 /*                                                                        */
9208 /*    This is the NetX Duo callback function for raw socket receive       */
9209 /*    operation.                                                          */
9210 /*                                                                        */
9211 /*  INPUT                                                                 */
9212 /*                                                                        */
9213 /*    ip_ptr                               NetX Duo IP instance           */
9214 /*    bsd_socket_index                     Index of the raw socket which  */
9215 /*                                            received the data packet    */
9216 /*                                                                        */
9217 /*  OUTPUT                                                                */
9218 /*                                                                        */
9219 /*    None                                                                */
9220 /*                                                                        */
9221 /*  CALLS                                                                 */
9222 /*                                                                        */
9223 /*    FD_ZERO                               Clear a socket ready list     */
9224 /*    FD_ISSET                              Check a socket is ready       */
9225 /*    FD_SET                                Set a socket to check         */
9226 /*    tx_event_flags_get                    Get events                    */
9227 /*    tx_mutex_get                          Get protection                */
9228 /*    tx_mutex_put                          Release protection            */
9229 /*    tx_thread_identify                    Get current thread pointer    */
9230 /*                                                                        */
9231 /*  CALLED BY                                                             */
9232 /*                                                                        */
9233 /*    NetX                                                                */
9234 /*                                                                        */
9235 /*  RELEASE HISTORY                                                       */
9236 /*                                                                        */
9237 /*    DATE              NAME                      DESCRIPTION             */
9238 /*                                                                        */
9239 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9240 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9241 /*                                            resulting in version 6.1    */
9242 /*                                                                        */
9243 /**************************************************************************/
nx_bsd_raw_receive_notify(NX_IP * ip_ptr,UINT bsd_socket_index)9244 VOID  nx_bsd_raw_receive_notify(NX_IP *ip_ptr, UINT bsd_socket_index)
9245 {
9246     NX_PARAMETER_NOT_USED(ip_ptr);
9247 
9248     nx_bsd_select_wakeup(bsd_socket_index, FDSET_READ);
9249 
9250 }
9251 
9252 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
9253 
9254 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
9255 
9256 /**************************************************************************/
9257 /*                                                                        */
9258 /*  FUNCTION                                               RELEASE        */
9259 /*                                                                        */
9260 /*    nx_bsd_raw_packet_receive                           PORTABLE C      */
9261 /*                                                           6.3.0        */
9262 /*  AUTHOR                                                                */
9263 /*                                                                        */
9264 /*    Yuxin Zhou, Microsoft Corporation                                   */
9265 /*                                                                        */
9266 /*  DESCRIPTION                                                           */
9267 /*                                                                        */
9268 /*    This function retrieves a packet from the BSD raw socket receive    */
9269 /*    queue.                                                              */
9270 /*                                                                        */
9271 /*  INPUT                                                                 */
9272 /*                                                                        */
9273 /*    bsd_socket_ptr                       BSD raw socket                 */
9274 /*    packet_ptr                           Pointer to retrieved packet    */
9275 /*                                                                        */
9276 /*  OUTPUT                                                                */
9277 /*                                                                        */
9278 /*    NX_SUCCESS                           Packet successfully retrieved  */
9279 /*    NX_NO_PACKET                         No packet on receive queue     */
9280 /*    NX_NOT_ENABLED                       Not enabled for raw packets    */
9281 /*                                                                        */
9282 /*  CALLS                                                                 */
9283 /*                                                                        */
9284 /*    None                                                                */
9285 /*                                                                        */
9286 /*  CALLED BY                                                             */
9287 /*                                                                        */
9288 /*    select                              Checks for receive packets      */
9289 /*    recv                                Checks the specified socket for */
9290 /*                                           received packets             */
9291 /*                                                                        */
9292 /*  RELEASE HISTORY                                                       */
9293 /*                                                                        */
9294 /*    DATE              NAME                      DESCRIPTION             */
9295 /*                                                                        */
9296 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9297 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9298 /*                                            resulting in version 6.1    */
9299 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
9300 /*                                            used new API/structs naming,*/
9301 /*                                            resulting in version 6.3.0  */
9302 /*                                                                        */
9303 /**************************************************************************/
nx_bsd_raw_packet_receive(NX_BSD_SOCKET * bsd_socket_ptr,NX_PACKET ** packet_ptr)9304 UINT nx_bsd_raw_packet_receive(NX_BSD_SOCKET *bsd_socket_ptr, NX_PACKET **packet_ptr)
9305 {
9306 
9307 
9308     /* Sanity check. Check this is indeed a raw socket. */
9309     if (!(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET))
9310     {
9311         /* Set the socket error. */
9312         nx_bsd_set_errno(EPROTOTYPE);
9313 
9314         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
9315         return(NX_NOT_ENABLED);
9316     }
9317 
9318     /* Verify this socket is enabled for raw packet processing. */
9319     if (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET)
9320     {
9321 
9322         /* Are there any packets on the socket raw receive queue? */
9323         if (bsd_socket_ptr -> nx_bsd_socket_received_packet != NX_NULL)
9324         {
9325 
9326             /* Yes, return a pointer to the packet at the top of the queue. */
9327             *packet_ptr =  bsd_socket_ptr -> nx_bsd_socket_received_packet;
9328 
9329             /* Update the packet count. */
9330             bsd_socket_ptr -> nx_bsd_socket_received_byte_count -= (*packet_ptr) -> nx_packet_length;
9331             bsd_socket_ptr -> nx_bsd_socket_received_packet_count--;
9332 
9333 
9334             /* Remove this packet from the receive queue and update queue packet pointers. */
9335             bsd_socket_ptr -> nx_bsd_socket_received_packet =  (*packet_ptr) -> nx_packet_queue_next;
9336 
9337             /* If this was the last packet, set the tail pointer to NULL.  */
9338             if (bsd_socket_ptr -> nx_bsd_socket_received_packet == NX_NULL)
9339             {
9340                 bsd_socket_ptr -> nx_bsd_socket_received_packet_tail =  NX_NULL;
9341                 bsd_socket_ptr -> nx_bsd_socket_received_byte_count = 0;
9342                 bsd_socket_ptr -> nx_bsd_socket_received_packet_count = 0;
9343             }
9344         }
9345         else
9346         {
9347 
9348             /* No packets on the queue. Return the NetX Duo status. This is an internal call, so no BSD socket error to report. */
9349             return NX_NO_PACKET;
9350         }
9351     }
9352     else
9353     {
9354         return NX_NOT_ENABLED;
9355     }
9356 
9357     return NX_SUCCESS;
9358 }
9359 
9360 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
9361 
9362 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
9363 /**************************************************************************/
9364 /*                                                                        */
9365 /*  FUNCTION                                               RELEASE        */
9366 /*                                                                        */
9367 /*    nx_bsd_raw_packet_info_extract                      PORTABLE C      */
9368 /*                                                           6.1          */
9369 /*  AUTHOR                                                                */
9370 /*                                                                        */
9371 /*    Yuxin Zhou, Microsoft Corporation                                   */
9372 /*                                                                        */
9373 /*  DESCRIPTION                                                           */
9374 /*                                                                        */
9375 /*    This function extracts the source IP address and interface index    */
9376 /*    from the received packet.                                           */
9377 /*                                                                        */
9378 /*  INPUT                                                                 */
9379 /*                                                                        */
9380 /*    packet_ptr                            Pointer to received raw packet*/
9381 /*    address                               Pointer to sender IP address  */
9382 /*    interface_index                       Pointer to network index      */
9383 /*                                            packet received on          */
9384 /*                                                                        */
9385 /*  OUTPUT                                                                */
9386 /*                                                                        */
9387 /*    NX_SUCCESS                           Successful completion status   */
9388 /*                                                                        */
9389 /*  CALLS                                                                 */
9390 /*                                                                        */
9391 /*    COPY_IPV6_ADDRESS                    Copy IPv6 address              */
9392 /*                                                                        */
9393 /*  CALLED BY                                                             */
9394 /*                                                                        */
9395 /*    Application Code                                                    */
9396 /*                                                                        */
9397 /*  RELEASE HISTORY                                                       */
9398 /*                                                                        */
9399 /*    DATE              NAME                      DESCRIPTION             */
9400 /*                                                                        */
9401 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9402 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9403 /*                                            resulting in version 6.1    */
9404 /*                                                                        */
9405 /**************************************************************************/
nx_bsd_raw_packet_info_extract(NX_PACKET * packet_ptr,NXD_ADDRESS * address,UINT * interface_index)9406 UINT  nx_bsd_raw_packet_info_extract(NX_PACKET *packet_ptr, NXD_ADDRESS *address, UINT *interface_index)
9407 {
9408 
9409 NX_INTERFACE    *if_ptr = NX_NULL;
9410 
9411 
9412 #ifndef NX_DISABLE_IPV4
9413     /* Determine what IP version the packet is. */
9414     if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
9415     {
9416 
9417         NX_IPV4_HEADER *ip_header_ptr;
9418 
9419         /* Set a pointer to the IPv4 header. */
9420         ip_header_ptr = (NX_IPV4_HEADER  *)(packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_IPV4_HEADER));
9421 
9422         /* Fill in the IP address information. */
9423         address -> nxd_ip_version = NX_IP_VERSION_V4;
9424         address -> nxd_ip_address.v4 = ip_header_ptr -> nx_ip_header_source_ip;
9425 
9426         /* Pick up the packet interface. */
9427         if_ptr = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
9428     }
9429 #endif /* NX_DISABLE_IPV4 */
9430 #ifdef FEATURE_NX_IPV6
9431     if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
9432     {
9433 
9434         NX_IPV6_HEADER *ipv6_header_ptr;
9435 
9436         ipv6_header_ptr = (NX_IPV6_HEADER  *)(packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_IPV6_HEADER));
9437 
9438         /* Fill in the IPv6 address information. */
9439         address -> nxd_ip_version = NX_IP_VERSION_V6;
9440 
9441         /* Copy the IPv6 address. */
9442         address -> nxd_ip_address.v6[0] = ipv6_header_ptr -> nx_ip_header_source_ip[0];
9443         address -> nxd_ip_address.v6[1] = ipv6_header_ptr -> nx_ip_header_source_ip[1];
9444         address -> nxd_ip_address.v6[2] = ipv6_header_ptr -> nx_ip_header_source_ip[2];
9445         address -> nxd_ip_address.v6[3] = ipv6_header_ptr -> nx_ip_header_source_ip[3];
9446 
9447         /* Pick up the packet interface. */
9448         if_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
9449     }
9450 #endif
9451 
9452     /* The last piece of information is the packet interface. If the return pointer is NULL we are done! */
9453     if(interface_index == NX_NULL)
9454         return(NX_SUCCESS);
9455 
9456     /* Search for interface index number.  Initialize interface value as
9457        invalid (0xFFFFFFFF).  Once we find valid interface, we will update
9458        the returned value. */
9459     *interface_index = 0xFFFFFFFF;
9460 
9461     if(if_ptr == NX_NULL)
9462     {
9463         /* No interface attached.  Done here, and return success. */
9464         return(NX_SUCCESS);
9465     }
9466 
9467     /* Compute the index by difference of the packet's interface from the primary interface, and dividing by the size. */
9468     *interface_index = if_ptr -> nx_interface_index;
9469 
9470     return(NX_SUCCESS);
9471 }
9472 
9473 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
9474 
9475 /**************************************************************************/
9476 /*                                                                        */
9477 /*  FUNCTION                                               RELEASE        */
9478 /*                                                                        */
9479 /*    nx_bsd_set_socket_timed_wait_callback               PORTABLE C      */
9480 /*                                                           6.1          */
9481 /*  AUTHOR                                                                */
9482 /*                                                                        */
9483 /*    Yuxin Zhou, Microsoft Corporation                                   */
9484 /*                                                                        */
9485 /*  DESCRIPTION                                                           */
9486 /*                                                                        */
9487 /*    This function is called when a BSD TCP socket has closed. If the    */
9488 /*    BSD socket associated with the TCP socket is not enabled for        */
9489 /*    REUSEADDR, this function will put the BSD socket in the TIMED WAIT  */
9490 /*    state.                                                              */
9491 /*                                                                        */
9492 /*    When this time out expires, the BSD socket is removed from the TIME */
9493 /*    WAIT State and available to the host application.                   */
9494 /*                                                                        */
9495 /*    Note: only sockets not enabled with REUSEADDR are placed in the WAIT*/
9496 /*    STATE. All other BSD sockets are immediately available upon closing.*/
9497 /*                                                                        */
9498 /*  INPUT                                                                 */
9499 /*                                                                        */
9500 /*    tcp_socket_ptr                       TCP socket state being closed  */
9501 /*                                                                        */
9502 /*  OUTPUT                                                                */
9503 /*                                                                        */
9504 /*    None                                                                */
9505 /*                                                                        */
9506 /*  CALLS                                                                 */
9507 /*                                                                        */
9508 /*    tx_thread_identify                   Identify socket owning thread  */
9509 /*    tx_mutex_get                         Obtain BSD mutex protection    */
9510 /*    tx_mutex_put                         Release BSD mutex protection   */
9511 /*                                                                        */
9512 /*  CALLED BY                                                             */
9513 /*                                                                        */
9514 /*    NetX                                                                */
9515 /*                                                                        */
9516 /*  RELEASE HISTORY                                                       */
9517 /*                                                                        */
9518 /*    DATE              NAME                      DESCRIPTION             */
9519 /*                                                                        */
9520 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9521 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9522 /*                                            resulting in version 6.1    */
9523 /*                                                                        */
9524 /**************************************************************************/
nx_bsd_socket_timed_wait_callback(NX_TCP_SOCKET * tcp_socket_ptr)9525 VOID  nx_bsd_socket_timed_wait_callback(NX_TCP_SOCKET *tcp_socket_ptr)
9526 {
9527     NX_PARAMETER_NOT_USED(tcp_socket_ptr);
9528 
9529     /* Logic has been removed elsewhere but for compatibility with
9530        NetX we leave this function stub. */
9531 
9532     return;
9533 }
9534 
9535 
9536 
9537 /**************************************************************************/
9538 /*                                                                        */
9539 /*  FUNCTION                                               RELEASE        */
9540 /*                                                                        */
9541 /*    nx_packet_data_extract_offset                       PORTABLE C      */
9542 /*                                                           6.1          */
9543 /*  AUTHOR                                                                */
9544 /*                                                                        */
9545 /*    Yuxin Zhou, Microsoft Corporation                                   */
9546 /*                                                                        */
9547 /*  DESCRIPTION                                                           */
9548 /*                                                                        */
9549 /*    This function copies data from a NetX packet (or packet chain) into */
9550 /*    the supplied user buffer.                                           */
9551 /*                                                                        */
9552 /*    This basically defines the data extract service in the BSD source   */
9553 /*    code if it is not provided in the NetX or NetX Duo library already. */
9554 /*                                                                        */
9555 /*  INPUT                                                                 */
9556 /*                                                                        */
9557 /*    packet_ptr                        Pointer to the source packet      */
9558 /*    buffer_start                      Pointer to destination data area  */
9559 /*    buffer_length                     Size in bytes                     */
9560 /*    bytes_copied                      Number of bytes copied            */
9561 /*                                                                        */
9562 /*  OUTPUT                                                                */
9563 /*                                                                        */
9564 /*    status                            Completion status                 */
9565 /*                                                                        */
9566 /*  CALLS                                                                 */
9567 /*                                                                        */
9568 /*    None                                                                */
9569 /*                                                                        */
9570 /*  CALLED BY                                                             */
9571 /*                                                                        */
9572 /*    Application Code                                                    */
9573 /*                                                                        */
9574 /*  RELEASE HISTORY                                                       */
9575 /*                                                                        */
9576 /*    DATE              NAME                      DESCRIPTION             */
9577 /*                                                                        */
9578 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9579 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
9580 /*                                            verified memcpy use cases,  */
9581 /*                                            resulting in version 6.1    */
9582 /*                                                                        */
9583 /**************************************************************************/
9584 #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)9585 UINT  nx_packet_data_extract_offset(NX_PACKET *packet_ptr, ULONG offset, VOID *buffer_start, ULONG buffer_length, ULONG *bytes_copied)
9586 {
9587 
9588 ULONG       remaining_bytes;
9589 UCHAR       *source_ptr;
9590 UCHAR       *destination_ptr;
9591 ULONG       offset_bytes;
9592 #ifndef NX_DISABLE_PACKET_CHAIN
9593 ULONG       packet_fragment_length;
9594 #endif
9595 ULONG       bytes_to_copy;
9596 NX_PACKET   *working_packet_ptr;
9597 
9598     working_packet_ptr =  packet_ptr;
9599 
9600     /* Check for an invalid offset or packet length.  */
9601     if(offset >= working_packet_ptr -> nx_packet_length)
9602     {
9603         /* Note: A zero offset with a packet of zero length is ok. */
9604         if ((offset == 0) && (working_packet_ptr -> nx_packet_length == 0))
9605         {
9606             *bytes_copied = 0;
9607             return(NX_SUCCESS);
9608         }
9609 
9610         /* Otherwise, this is an invalid offset or packet length. */
9611         return(NX_PACKET_OFFSET_ERROR);
9612     }
9613 
9614     /* Initialize the source pointer to NULL.  */
9615     source_ptr =  NX_NULL;
9616 
9617     /* Traverse packet chain to offset.  */
9618     offset_bytes =  offset;
9619 #ifndef NX_DISABLE_PACKET_CHAIN
9620     while (working_packet_ptr)
9621     {
9622         packet_fragment_length =  (working_packet_ptr -> nx_packet_append_ptr - working_packet_ptr -> nx_packet_prepend_ptr) ;
9623 
9624         /* Determine if we are at the offset location fragment in the packet chain  */
9625         if (packet_fragment_length > offset_bytes)
9626         {
9627             /* Setup loop to copy from this packet.  */
9628             source_ptr =  working_packet_ptr -> nx_packet_prepend_ptr + offset_bytes;
9629 
9630             /* Yes, get out of this  loop.  */
9631             break;
9632         }
9633 
9634         /* Decrement the remaining offset bytes*/
9635         offset_bytes = offset_bytes - packet_fragment_length ;
9636 
9637         /* Move to next packet.  */
9638         working_packet_ptr =  working_packet_ptr -> nx_packet_next;
9639     }
9640 #else /* NX_DISABLE_PACKET_CHAIN */
9641 
9642     /* Setup loop to copy from this packet.  */
9643     source_ptr =  working_packet_ptr -> nx_packet_prepend_ptr + offset_bytes;
9644 
9645 #endif /* NX_DISABLE_PACKET_CHAIN */
9646 
9647     /* Check for a valid source pointer.  */
9648     if (source_ptr == NX_NULL)
9649         return(NX_PACKET_OFFSET_ERROR);
9650 
9651     /* Setup the destination pointer.  */
9652     destination_ptr =  buffer_start;
9653     bytes_to_copy =   (packet_ptr->nx_packet_length - offset);
9654 
9655     /* Pickup the amount of bytes to copy.  */
9656     if( bytes_to_copy < buffer_length)
9657     {
9658         *bytes_copied =  bytes_to_copy;     /* the amount of bytes returned to the caller */
9659         remaining_bytes =  bytes_to_copy;   /* for use in the copy loop */
9660     }
9661     else
9662     {
9663         *bytes_copied =  buffer_length;
9664         remaining_bytes =  buffer_length;
9665     }
9666 
9667 #ifndef NX_DISABLE_PACKET_CHAIN
9668     /* Loop to copy bytes from packet(s).  */
9669     while (working_packet_ptr && remaining_bytes)
9670     {
9671 #endif /* NX_DISABLE_PACKET_CHAIN */
9672 
9673         /* Calculate bytes to copy.  */
9674         bytes_to_copy = working_packet_ptr -> nx_packet_append_ptr - source_ptr;
9675         if(remaining_bytes < bytes_to_copy)
9676             bytes_to_copy = remaining_bytes;
9677 
9678         /* Copy data from this packet.  */
9679         memcpy(destination_ptr, source_ptr, bytes_to_copy); /* Use case of memcpy is verified. */
9680 
9681         /* Update the pointers. */
9682         destination_ptr += bytes_to_copy;
9683         remaining_bytes -= bytes_to_copy;
9684 
9685 #ifndef NX_DISABLE_PACKET_CHAIN
9686         /* Move to next packet.  */
9687         working_packet_ptr =  working_packet_ptr -> nx_packet_next;
9688 
9689         /* Check for a next packet.  */
9690         if (working_packet_ptr)
9691         {
9692 
9693             /* Setup new source pointer.  */
9694             source_ptr = working_packet_ptr -> nx_packet_prepend_ptr;
9695         }
9696     }
9697 #endif /* NX_DISABLE_PACKET_CHAIN */
9698 
9699     /* Return successful completion.  */
9700     return(NX_SUCCESS);
9701 
9702 }
9703 #endif /* NX_BSD_INCLUDE_DATA_EXTRACT_OFFSET */
9704 
9705 /**************************************************************************/
9706 /*                                                                        */
9707 /*  FUNCTION                                               RELEASE        */
9708 /*                                                                        */
9709 /*    nx_bsd_timer_entry                                  PORTABLE C      */
9710 /*                                                           6.1          */
9711 /*  AUTHOR                                                                */
9712 /*                                                                        */
9713 /*    Yuxin Zhou, Microsoft Corporation                                   */
9714 /*                                                                        */
9715 /*  DESCRIPTION                                                           */
9716 /*                                                                        */
9717 /*    This function is called when the nx_bsd_socket_wait_timer expires.  */
9718 /*    It signals the BSD thread task to check and decrement the time      */
9719 /*    remaining on all sockets suspended in the wait state.               */
9720 /*                                                                        */
9721 /*  INPUT                                                                 */
9722 /*                                                                        */
9723 /*    info                                 Timer thread data (not used)   */
9724 /*                                                                        */
9725 /*  OUTPUT                                                                */
9726 /*                                                                        */
9727 /*    None                                                                */
9728 /*                                                                        */
9729 /*  CALLS                                                                 */
9730 /*                                                                        */
9731 /*    tx_event_flags_set                   Sets the WAIT event in the BSD */
9732 /*                                              event group               */
9733 /*                                                                        */
9734 /*  CALLED BY                                                             */
9735 /*                                                                        */
9736 /*    ThreadX                                                             */
9737 /*                                                                        */
9738 /*  RELEASE HISTORY                                                       */
9739 /*                                                                        */
9740 /*    DATE              NAME                      DESCRIPTION             */
9741 /*                                                                        */
9742 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9743 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9744 /*                                            resulting in version 6.1    */
9745 /*                                                                        */
9746 /**************************************************************************/
9747 #ifdef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
nx_bsd_timer_entry(ULONG info)9748 VOID  nx_bsd_timer_entry(ULONG info)
9749 {
9750     nx_bsd_timeout_process();
9751 }
9752 #endif
9753 
9754 
9755 /**************************************************************************/
9756 /*                                                                        */
9757 /*  FUNCTION                                               RELEASE        */
9758 /*                                                                        */
9759 /*    nx_bsd_socket_set_inherited_settings                PORTABLE C      */
9760 /*                                                           6.1          */
9761 /*  AUTHOR                                                                */
9762 /*                                                                        */
9763 /*    Yuxin Zhou, Microsoft Corporation                                   */
9764 /*                                                                        */
9765 /*  DESCRIPTION                                                           */
9766 /*                                                                        */
9767 /*    This function applies the socket options of the specified parent    */
9768 /*    (master) socket to the specified child (secondary) socket, if BSD   */
9769 /*    extended socket options are enabled. If they are not, this function */
9770 /*    has no effect.                                                      */
9771 /*                                                                        */
9772 /*  INPUT                                                                 */
9773 /*                                                                        */
9774 /*    master_sock_id                       Source of socket options       */
9775 /*    secondary_sock_id                    Socket inheriting options      */
9776 /*                                                                        */
9777 /*  OUTPUT                                                                */
9778 /*                                                                        */
9779 /*    NX_SUCCESS                          Successful completion           */
9780 /*                                                                        */
9781 /*  CALLS                                                                 */
9782 /*                                                                        */
9783 /*    None                                                                */
9784 /*                                                                        */
9785 /*  CALLED BY                                                             */
9786 /*                                                                        */
9787 /*    ThreadX                                                             */
9788 /*                                                                        */
9789 /*  RELEASE HISTORY                                                       */
9790 /*                                                                        */
9791 /*    DATE              NAME                      DESCRIPTION             */
9792 /*                                                                        */
9793 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9794 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9795 /*                                            resulting in version 6.1    */
9796 /*                                                                        */
9797 /**************************************************************************/
nx_bsd_socket_set_inherited_settings(UINT master_sock_id,UINT secondary_sock_id)9798 UINT nx_bsd_socket_set_inherited_settings(UINT master_sock_id, UINT secondary_sock_id)
9799 {
9800 
9801     /* Update the secondary socket options from the master socket. */
9802     if(nx_bsd_socket_array[master_sock_id].nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING)
9803         nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING;
9804     else
9805         nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING);
9806 
9807     if(nx_bsd_socket_array[master_sock_id].nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR)
9808         nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR;
9809     else
9810         nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR);
9811 
9812 #ifdef NX_ENABLE_TCP_WINDOW_SCALING
9813     nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_maximum =
9814                                                          nx_bsd_socket_array[master_sock_id].nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_maximum;
9815 #endif
9816 
9817 
9818     /* Does this version of NetX Duo support TCP keep alive? */
9819     /* Is NetX Duo currently enabled for TCP keep alive? */
9820 #ifdef NX_ENABLE_TCP_KEEPALIVE
9821 
9822     nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled =
9823                         nx_bsd_socket_array[master_sock_id].nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled;
9824 
9825 #endif /* NX_ENABLE_TCP_KEEPALIVE */
9826 
9827 
9828     return NX_SUCCESS;
9829 }
9830 
9831 
9832 /**************************************************************************/
9833 /*                                                                        */
9834 /*  FUNCTION                                               RELEASE        */
9835 /*                                                                        */
9836 /*    nx_bsd_isspace                                      PORTABLE C      */
9837 /*                                                           6.1          */
9838 /*  AUTHOR                                                                */
9839 /*                                                                        */
9840 /*    Yuxin Zhou, Microsoft Corporation                                   */
9841 /*                                                                        */
9842 /*  DESCRIPTION                                                           */
9843 /*                                                                        */
9844 /*    This function determines if the input character is white space      */
9845 /*    (ascii characters 0x09 - 0x0D or space (0x20).                      */
9846 /*                                                                        */
9847 /*  INPUT                                                                 */
9848 /*                                                                        */
9849 /*    c                                    Input character to examine     */
9850 /*                                                                        */
9851 /*  OUTPUT                                                                */
9852 /*                                                                        */
9853 /*    NX_TRUE                              Input character is white space */
9854 /*    NX_FALSE                             Input character not white space*/
9855 /*                                                                        */
9856 /*  CALLS                                                                 */
9857 /*                                                                        */
9858 /*    None                                                                */
9859 /*                                                                        */
9860 /*  CALLED BY                                                             */
9861 /*                                                                        */
9862 /*    ThreadX                                                             */
9863 /*                                                                        */
9864 /*  RELEASE HISTORY                                                       */
9865 /*                                                                        */
9866 /*    DATE              NAME                      DESCRIPTION             */
9867 /*                                                                        */
9868 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9869 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9870 /*                                            resulting in version 6.1    */
9871 /*                                                                        */
9872 /**************************************************************************/
nx_bsd_isspace(UCHAR c)9873 static UINT nx_bsd_isspace(UCHAR c)
9874 {
9875 
9876     /* Check for horizontal, vertical tabs, carriage return or formfeed characters. */
9877     if ((c >= 0x09) && (c <= 0x0D))
9878     {
9879         return NX_TRUE;
9880     }
9881     /* Check for a single space character*/
9882     else if (c == 20)
9883     {
9884         return NX_TRUE;
9885     }
9886     else
9887         /* Not a white space character. */
9888         return NX_FALSE;
9889 }
9890 
9891 
9892 /**************************************************************************/
9893 /*                                                                        */
9894 /*  FUNCTION                                               RELEASE        */
9895 /*                                                                        */
9896 /*    nx_bsd_islower                                      PORTABLE C      */
9897 /*                                                           6.1          */
9898 /*  AUTHOR                                                                */
9899 /*                                                                        */
9900 /*    Yuxin Zhou, Microsoft Corporation                                   */
9901 /*                                                                        */
9902 /*  DESCRIPTION                                                           */
9903 /*                                                                        */
9904 /*    This function determines if the input character is lower case       */
9905 /*    alphabetic character.                                               */
9906 /*                                                                        */
9907 /*  INPUT                                                                 */
9908 /*                                                                        */
9909 /*    c                                    Input character to examine     */
9910 /*                                                                        */
9911 /*  OUTPUT                                                                */
9912 /*                                                                        */
9913 /*    NX_TRUE                              Input character is lower case  */
9914 /*    NX_FALSE                             Input character not lower case */
9915 /*                                                                        */
9916 /*  CALLS                                                                 */
9917 /*                                                                        */
9918 /*    None                                                                */
9919 /*                                                                        */
9920 /*  CALLED BY                                                             */
9921 /*                                                                        */
9922 /*    ThreadX                                                             */
9923 /*                                                                        */
9924 /*  RELEASE HISTORY                                                       */
9925 /*                                                                        */
9926 /*    DATE              NAME                      DESCRIPTION             */
9927 /*                                                                        */
9928 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9929 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9930 /*                                            resulting in version 6.1    */
9931 /*                                                                        */
9932 /**************************************************************************/
nx_bsd_islower(UCHAR c)9933 static UINT nx_bsd_islower(UCHAR c)
9934 {
9935 
9936     /* Check if characters is any character 'a' through 'z'. */
9937     if ((c >= 0x61) && (c <= 0x7A))
9938     {
9939 
9940         return NX_TRUE;
9941     }
9942     else
9943         return NX_FALSE;
9944 
9945 }
9946 
9947 /**************************************************************************/
9948 /*                                                                        */
9949 /*  FUNCTION                                               RELEASE        */
9950 /*                                                                        */
9951 /*    nx_bsd_isdigit                                      PORTABLE C      */
9952 /*                                                           6.1          */
9953 /*  AUTHOR                                                                */
9954 /*                                                                        */
9955 /*    Yuxin Zhou, Microsoft Corporation                                   */
9956 /*                                                                        */
9957 /*  DESCRIPTION                                                           */
9958 /*                                                                        */
9959 /*    This function determines if the input character is a digit (0-9)    */
9960 /*    Does not include hex digits, (see nx_bsd_isxdigit).                 */
9961 /*                                                                        */
9962 /*  INPUT                                                                 */
9963 /*                                                                        */
9964 /*    c                                    Input character to examine     */
9965 /*                                                                        */
9966 /*  OUTPUT                                                                */
9967 /*                                                                        */
9968 /*    NX_TRUE                              Input character is a digit     */
9969 /*    NX_FALSE                             Input character not a digit    */
9970 /*                                                                        */
9971 /*  CALLS                                                                 */
9972 /*                                                                        */
9973 /*    None                                                                */
9974 /*                                                                        */
9975 /*  CALLED BY                                                             */
9976 /*                                                                        */
9977 /*    ThreadX                                                             */
9978 /*                                                                        */
9979 /*  RELEASE HISTORY                                                       */
9980 /*                                                                        */
9981 /*    DATE              NAME                      DESCRIPTION             */
9982 /*                                                                        */
9983 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
9984 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
9985 /*                                            resulting in version 6.1    */
9986 /*                                                                        */
9987 /**************************************************************************/
nx_bsd_isdigit(UCHAR c)9988 static UINT nx_bsd_isdigit(UCHAR c)
9989 {
9990 
9991     /* Is the character any digit between 0 and 9? */
9992     if ((c >= 0x30) && (c <= 0x39))
9993     {
9994         return NX_TRUE;
9995     }
9996     else
9997         return NX_FALSE;
9998 }
9999 
10000 
10001 /**************************************************************************/
10002 /*                                                                        */
10003 /*  FUNCTION                                               RELEASE        */
10004 /*                                                                        */
10005 /*    nx_bsd_isxdigit                                     PORTABLE C      */
10006 /*                                                           6.1          */
10007 /*  AUTHOR                                                                */
10008 /*                                                                        */
10009 /*    Yuxin Zhou, Microsoft Corporation                                   */
10010 /*                                                                        */
10011 /*  DESCRIPTION                                                           */
10012 /*                                                                        */
10013 /*    This function determines if the input character is a digit (0-9)    */
10014 /*    or hex digit (A - F, or a-f).  For decimal digits, see              */
10015 /*    nx_bsd_isdigit.                                                     */
10016 /*                                                                        */
10017 /*  INPUT                                                                 */
10018 /*                                                                        */
10019 /*    c                                    Input character to examine     */
10020 /*                                                                        */
10021 /*  OUTPUT                                                                */
10022 /*                                                                        */
10023 /*    NX_TRUE                              Input character is hex digit   */
10024 /*    NX_FALSE                             Input character not hex digit  */
10025 /*                                                                        */
10026 /*  CALLS                                                                 */
10027 /*                                                                        */
10028 /*    None                                                                */
10029 /*                                                                        */
10030 /*  CALLED BY                                                             */
10031 /*                                                                        */
10032 /*    ThreadX                                                             */
10033 /*                                                                        */
10034 /*  RELEASE HISTORY                                                       */
10035 /*                                                                        */
10036 /*    DATE              NAME                      DESCRIPTION             */
10037 /*                                                                        */
10038 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10039 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10040 /*                                            resulting in version 6.1    */
10041 /*                                                                        */
10042 /**************************************************************************/
nx_bsd_isxdigit(UCHAR c)10043 static UINT nx_bsd_isxdigit(UCHAR c)
10044 {
10045 
10046     /* Is the character any digit between 0 - 9? */
10047     if ((c >= 0x30) && (c <= 0x39))
10048     {
10049         return NX_TRUE;
10050     }
10051 
10052     /* Or is the character any base 16 digit A-F? */
10053     if ((c >= 0x41) && (c <= 0x46))
10054     {
10055         return NX_TRUE;
10056     }
10057 
10058     /* Lastly, check if character is any base 16 digit a-f? */
10059     if ((c >= 0x61) && (c <= 0x66))
10060     {
10061         return NX_TRUE;
10062     }
10063     else
10064         return NX_FALSE;
10065 }
10066 
10067 /**************************************************************************/
10068 /*                                                                        */
10069 /*  FUNCTION                                               RELEASE        */
10070 /*                                                                        */
10071 /*    set_errno                                           PORTABLE C      */
10072 /*                                                           6.3.0        */
10073 /*  AUTHOR                                                                */
10074 /*                                                                        */
10075 /*    Yuxin Zhou, Microsoft Corporation                                   */
10076 /*                                                                        */
10077 /*  DESCRIPTION                                                           */
10078 /*                                                                        */
10079 /*    This function sets the error on the current socket (thread) for     */
10080 /*    sockets enabled with BSD extended socket options. For sockets not   */
10081 /*    enabled with extended features, this function has no effect.        */
10082 /*                                                                        */
10083 /*  INPUT                                                                 */
10084 /*                                                                        */
10085 /*    tx_errno                                Socket error status code    */
10086 /*                                                                        */
10087 /*  OUTPUT                                                                */
10088 /*                                                                        */
10089 /*    None                                                                */
10090 /*                                                                        */
10091 /*  CALLS                                                                 */
10092 /*                                                                        */
10093 /*    None                                                                */
10094 /*                                                                        */
10095 /*  CALLED BY                                                             */
10096 /*                                                                        */
10097 /*    ThreadX                                                             */
10098 /*                                                                        */
10099 /*  RELEASE HISTORY                                                       */
10100 /*                                                                        */
10101 /*    DATE              NAME                      DESCRIPTION             */
10102 /*                                                                        */
10103 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10104 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10105 /*                                            resulting in version 6.1    */
10106 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
10107 /*                                            used new API/structs naming,*/
10108 /*                                            resulting in version 6.3.0  */
10109 /*                                                                        */
10110 /**************************************************************************/
nx_bsd_set_errno(INT tx_errno)10111 VOID nx_bsd_set_errno(INT tx_errno)
10112 {
10113 
10114 TX_INTERRUPT_SAVE_AREA
10115 TX_THREAD       *current_thread_ptr;
10116 
10117 
10118       TX_DISABLE
10119 
10120       current_thread_ptr =  tx_thread_identify();
10121       current_thread_ptr -> bsd_errno = tx_errno;
10122 
10123       TX_RESTORE
10124 
10125       return;
10126 }
10127 
10128 /**************************************************************************/
10129 /*                                                                        */
10130 /*  FUNCTION                                               RELEASE        */
10131 /*                                                                        */
10132 /*    get_errno                                           PORTABLE C      */
10133 /*                                                           6.1          */
10134 /*  AUTHOR                                                                */
10135 /*                                                                        */
10136 /*    Yuxin Zhou, Microsoft Corporation                                   */
10137 /*                                                                        */
10138 /*  DESCRIPTION                                                           */
10139 /*                                                                        */
10140 /*    This function retrieves the error on the current socket (thread) for*/
10141 /*    sockets enabled with BSD extended socket options. For sockets not   */
10142 /*    enabled with extended features, this function has no effect.        */
10143 /*                                                                        */
10144 /*  INPUT                                                                 */
10145 /*                                                                        */
10146 /*    None                                                                */
10147 /*                                                                        */
10148 /*  OUTPUT                                                                */
10149 /*                                                                        */
10150 /*    Socket error status code                                            */
10151 /*                                                                        */
10152 /*  CALLS                                                                 */
10153 /*                                                                        */
10154 /*    None                                                                */
10155 /*                                                                        */
10156 /*  CALLED BY                                                             */
10157 /*                                                                        */
10158 /*    ThreadX                                                             */
10159 /*                                                                        */
10160 /*  RELEASE HISTORY                                                       */
10161 /*                                                                        */
10162 /*    DATE              NAME                      DESCRIPTION             */
10163 /*                                                                        */
10164 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10165 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10166 /*                                            resulting in version 6.1    */
10167 /*                                                                        */
10168 /**************************************************************************/
_nxd_get_errno()10169 INT _nxd_get_errno()
10170 {
10171 
10172 TX_INTERRUPT_SAVE_AREA
10173 INT val;
10174 TX_THREAD       *current_thread_ptr;
10175 
10176 
10177     TX_DISABLE
10178 
10179     current_thread_ptr =  tx_thread_identify();
10180     val = current_thread_ptr -> bsd_errno;
10181 
10182     TX_RESTORE
10183 
10184     return (val);
10185 }
10186 
10187 
10188 /**************************************************************************/
10189 /*                                                                        */
10190 /*  FUNCTION                                               RELEASE        */
10191 /*                                                                        */
10192 /*    nx_bsd_select_wakeup                                PORTABLE C      */
10193 /*                                                           6.3.0        */
10194 /*  AUTHOR                                                                */
10195 /*                                                                        */
10196 /*    Yuxin Zhou, Microsoft Corporation                                   */
10197 /*                                                                        */
10198 /*  DESCRIPTION                                                           */
10199 /*                                                                        */
10200 /*    This function checks the suspend list for a given socket being      */
10201 /*    readable or writeable.                                              */
10202 /*                                                                        */
10203 /*  INPUT                                                                 */
10204 /*                                                                        */
10205 /*    sock_id                               BSD socket ID                 */
10206 /*    fd_sets                               The FD set to check           */
10207 /*                                                                        */
10208 /*  OUTPUT                                                                */
10209 /*                                                                        */
10210 /*    None                                                                */
10211 /*                                                                        */
10212 /*  CALLS                                                                 */
10213 /*                                                                        */
10214 /*    FD_ZERO                               Zeros out an FD Set           */
10215 /*    FD_SET                                Set a socket in the FDSET     */
10216 /*    TX_DISABLE                            Disable Interrupt             */
10217 /*    TX_RESTORE                            Enable Interrupt              */
10218 /*    tx_event_flags_set                    Set an event flag             */
10219 /*                                                                        */
10220 /*  CALLED BY                                                             */
10221 /*                                                                        */
10222 /*    nx_bsd_timeout_process                                              */
10223 /*    nx_bsd_tcp_receive_notify                                           */
10224 /*    nx_bsd_tcp_establish_notify                                         */
10225 /*    nx_bsd_tcp_socket_disconnect_notify                                 */
10226 /*    nx_bsd_raw_receive_notify                                           */
10227 /*    nx_bsd_udp_packet_received                                          */
10228 /*                                                                        */
10229 /*  RELEASE HISTORY                                                       */
10230 /*                                                                        */
10231 /*    DATE              NAME                      DESCRIPTION             */
10232 /*                                                                        */
10233 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10234 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10235 /*                                            resulting in version 6.1    */
10236 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
10237 /*                                            used new API/structs naming,*/
10238 /*                                            resulting in version 6.3.0  */
10239 /*                                                                        */
10240 /**************************************************************************/
nx_bsd_select_wakeup(UINT sock_id,UINT fd_sets)10241 static VOID nx_bsd_select_wakeup(UINT sock_id, UINT fd_sets)
10242 {
10243 TX_INTERRUPT_SAVE_AREA
10244 nx_bsd_fd_set           local_fd;
10245 TX_THREAD               *suspended_thread;
10246 ULONG                   suspended_count;
10247 ULONG                   original_suspended_count;
10248 NX_BSD_SOCKET_SUSPEND   *suspend_info;
10249 
10250 
10251     /* At this point the thread should NOT own the IP mutex, and it must own the
10252        BSD mutex. */
10253 
10254 
10255     NX_BSD_FD_ZERO(&local_fd);
10256     NX_BSD_FD_SET((INT)sock_id + NX_BSD_SOCKFD_START, &local_fd);
10257 
10258     /* Disable interrupts temporarily.  */
10259     TX_DISABLE
10260 
10261     /* Setup the head pointer and the count.  */
10262     suspended_thread =   nx_bsd_events.tx_event_flags_group_suspension_list;
10263     suspended_count =    nx_bsd_events.tx_event_flags_group_suspended_count;
10264 
10265     /* Save the original suspended count.  */
10266     original_suspended_count =  suspended_count;
10267 
10268     /* Loop to examine all threads suspended on select via the BSD event flag group.  */
10269     while (suspended_count--)
10270     {
10271 
10272         /* Determine if this thread is suspended on select.  */
10273         if (suspended_thread -> tx_thread_suspend_info == NX_BSD_SELECT_EVENT)
10274         {
10275 
10276             /* Yes, this thread is suspended on select.  */
10277 
10278             /* Pickup a pointer to its select suspend structure.  */
10279             suspend_info =  (NX_BSD_SOCKET_SUSPEND *) suspended_thread -> tx_thread_additional_suspend_info;
10280 
10281             /* Now determine if this thread was waiting for this socket.  */
10282             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)))
10283             {
10284 
10285                 /* Copy the local fd over so that the return shows the receive socket.  */
10286                 suspend_info -> nx_bsd_socket_suspend_read_fd_set = local_fd;
10287 
10288                 /* Adjust the suspension type so that the event flag set below will wakeup the thread
10289                    selecting.  */
10290                 suspended_thread -> tx_thread_suspend_info =  NX_BSD_RECEIVE_EVENT;
10291             }
10292 
10293             /* Now determine if this thread was waiting for this socket.  */
10294             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)))
10295             {
10296 
10297                 /* Copy the local fd over so that the return shows the receive socket.  */
10298                 suspend_info -> nx_bsd_socket_suspend_write_fd_set = local_fd;
10299 
10300                 /* Adjust the suspension type so that the event flag set below will wakeup the thread
10301                    selecting.  */
10302                 suspended_thread -> tx_thread_suspend_info =  NX_BSD_RECEIVE_EVENT;
10303             }
10304 
10305             /* Now determine if this thread was waiting for this socket.  */
10306             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)))
10307             {
10308 
10309                 /* Copy the local fd over so that the return shows the receive socket.  */
10310                 suspend_info -> nx_bsd_socket_suspend_exception_fd_set = local_fd;
10311 
10312                 /* Adjust the suspension type so that the event flag set below will wakeup the thread
10313                    selecting.  */
10314                 suspended_thread -> tx_thread_suspend_info =  NX_BSD_RECEIVE_EVENT;
10315             }
10316 
10317             /* Clear FD that is not set. */
10318             if (suspended_thread -> tx_thread_suspend_info == NX_BSD_RECEIVE_EVENT)
10319             {
10320                 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)))
10321                 {
10322 
10323                     /* Clear read FD. */
10324                     NX_BSD_FD_CLR((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_read_fd_set);
10325                 }
10326 
10327                 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)))
10328                 {
10329 
10330                     /* Clear write FD. */
10331                     NX_BSD_FD_CLR((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_write_fd_set);
10332                 }
10333 
10334                 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)))
10335                 {
10336 
10337                     /* Clear exception FD. */
10338                     NX_BSD_FD_CLR((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_exception_fd_set);
10339                 }
10340             }
10341         }
10342 
10343         /* Now move to the next event.  */
10344         suspended_thread =  suspended_thread -> tx_thread_suspended_next;
10345 
10346         /* Restore interrupts.  */
10347         TX_RESTORE
10348 
10349         /* Disable interrupts again.  */
10350         TX_DISABLE
10351 
10352         /* Determine if something changes on the suspension list... this could have happened if there
10353            was a timeout or a wait abort on the thread.  */
10354         if (original_suspended_count != nx_bsd_events.tx_event_flags_group_suspended_count)
10355         {
10356 
10357             /* Something changed, so simply restart the search.  */
10358 
10359             /* Setup the head pointer and the count.  */
10360             suspended_thread =   nx_bsd_events.tx_event_flags_group_suspension_list;
10361             suspended_count =    nx_bsd_events.tx_event_flags_group_suspended_count;
10362 
10363             /* Save the original suspended count.  */
10364             original_suspended_count =  suspended_count;
10365         }
10366     }
10367 
10368     /* Restore interrupts.  */
10369     TX_RESTORE
10370 
10371     /* Wakeup all threads that are attempting to perform a receive or that had their select satisfied.  */
10372     tx_event_flags_set(&nx_bsd_events, NX_BSD_RECEIVE_EVENT, TX_OR);
10373 
10374     return;
10375 
10376 }
10377 
10378 /**************************************************************************/
10379 /*                                                                        */
10380 /*  FUNCTION                                               RELEASE        */
10381 /*                                                                        */
10382 /*    nx_bsd_set_error_code                               PORTABLE C      */
10383 /*                                                           6.3.0        */
10384 /*  AUTHOR                                                                */
10385 /*                                                                        */
10386 /*    Yuxin Zhou, Microsoft Corporation                                   */
10387 /*                                                                        */
10388 /*  DESCRIPTION                                                           */
10389 /*                                                                        */
10390 /*    This is sets the BSD error code based on NetX Duo API return code   */
10391 /*                                                                        */
10392 /*  INPUT                                                                 */
10393 /*                                                                        */
10394 /*    bsd_socket_ptr                        Pointer to the BSD socket     */
10395 /*    status_code                           NetX Duo API return code      */
10396 /*                                                                        */
10397 /*  OUTPUT                                                                */
10398 /*                                                                        */
10399 /*    None                                                                */
10400 /*                                                                        */
10401 /*  CALLS                                                                 */
10402 /*                                                                        */
10403 /*    set_errno                             Sets the BSD errno            */
10404 /*                                                                        */
10405 /*  CALLED BY                                                             */
10406 /*                                                                        */
10407 /*    connect                                                             */
10408 /*    bind                                                                */
10409 /*                                                                        */
10410 /*  RELEASE HISTORY                                                       */
10411 /*                                                                        */
10412 /*    DATE              NAME                      DESCRIPTION             */
10413 /*                                                                        */
10414 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10415 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10416 /*                                            resulting in version 6.1    */
10417 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
10418 /*                                            used new API/structs naming,*/
10419 /*                                            resulting in version 6.3.0  */
10420 /*                                                                        */
10421 /**************************************************************************/
nx_bsd_set_error_code(NX_BSD_SOCKET * bsd_socket_ptr,UINT status_code)10422 static VOID nx_bsd_set_error_code(NX_BSD_SOCKET *bsd_socket_ptr, UINT status_code)
10423 {
10424     switch(status_code)
10425     {
10426         case NX_NOT_CLOSED:
10427             /* TCP connection is not closed state. */
10428             nx_bsd_set_errno(EISCONN);
10429             break;
10430 
10431         case NX_PTR_ERROR:
10432         case NX_INVALID_PORT:
10433             /* Invalid arguement. */
10434             nx_bsd_set_errno(EINVAL);
10435             break;
10436 
10437         case NX_MAX_LISTEN:
10438             nx_bsd_set_errno(ENOBUFS);
10439             break;
10440 
10441         case NX_PORT_UNAVAILABLE:
10442         case NX_NO_FREE_PORTS:
10443             nx_bsd_set_errno(EADDRNOTAVAIL);
10444             break;
10445 
10446         case NX_ALREADY_BOUND:
10447             nx_bsd_set_errno(EINVAL);
10448             break;
10449 
10450         case NX_WAIT_ABORTED:
10451             nx_bsd_set_errno(ETIMEDOUT);
10452             break;
10453 
10454         case NX_NOT_CONNECTED:
10455             /* NX TCP connect service may return NX_NOT_CONNECTED if the timeout is WAIT_FOREVER. */
10456             nx_bsd_set_errno(ECONNREFUSED);
10457             break;
10458 
10459         case NX_IN_PROGRESS:
10460             /* The NetX "in progress" status is the equivalent of the non blocking BSD socket waiting
10461                to connect. This can only happen if timeout is NX_NO_WAIT.*/
10462             if (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING)
10463             {
10464                 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
10465                 nx_bsd_set_errno(EINPROGRESS);
10466             }
10467             else
10468                 nx_bsd_set_errno(EINTR);
10469             break;
10470 
10471         case NX_INVALID_INTERFACE:
10472         case NX_IP_ADDRESS_ERROR:
10473             nx_bsd_set_errno(ENETUNREACH);
10474             break;
10475 
10476         case NX_NOT_ENABLED:
10477             nx_bsd_set_errno(EPROTONOSUPPORT);
10478             break;
10479 
10480         case NX_NOT_BOUND:
10481         case NX_DUPLICATE_LISTEN:
10482         default:
10483             nx_bsd_set_errno(EINVAL);
10484             break;
10485     }
10486 
10487     return;
10488 }
10489 
10490 /**************************************************************************/
10491 /*                                                                        */
10492 /*  FUNCTION                                               RELEASE        */
10493 /*                                                                        */
10494 /*    nx_bsd_udp_packet_received                          PORTABLE C      */
10495 /*                                                           6.1          */
10496 /*  AUTHOR                                                                */
10497 /*                                                                        */
10498 /*    Yuxin Zhou, Microsoft Corporation                                   */
10499 /*                                                                        */
10500 /*  DESCRIPTION                                                           */
10501 /*                                                                        */
10502 /*    This is executed as part of the UDP packet receive callback         */
10503 /*    function.                                                           */
10504 /*                                                                        */
10505 /*    This routine puts an incoming UDP packet into the appropriate       */
10506 /*    UDP BSD socket, taking into consideration that multiple BSD sockets */
10507 /*    may be mapped to the same NetX Duo UDP socket.                      */
10508 /*                                                                        */
10509 /*  INPUT                                                                 */
10510 /*                                                                        */
10511 /*    sockID                                The BSD socket descriptor     */
10512 /*    packet_ptr                            The incoming UDP packet       */
10513 /*                                                                        */
10514 /*  OUTPUT                                                                */
10515 /*                                                                        */
10516 /*    None                                                                */
10517 /*                                                                        */
10518 /*  CALLS                                                                 */
10519 /*                                                                        */
10520 /*    nx_packet_release                     Release a packet that is not  */
10521 /*                                            received by any sockets.    */
10522 /*    nx_bsd_select_wakeup                  Wake up any asychronous       */
10523 /*                                            receive call                */
10524 /*                                                                        */
10525 /*  CALLED BY                                                             */
10526 /*                                                                        */
10527 /*    nx_bsd_udp_receive_notify                                           */
10528 /*                                                                        */
10529 /*  RELEASE HISTORY                                                       */
10530 /*                                                                        */
10531 /*    DATE              NAME                      DESCRIPTION             */
10532 /*                                                                        */
10533 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10534 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10535 /*                                            resulting in version 6.1    */
10536 /*                                                                        */
10537 /**************************************************************************/
nx_bsd_udp_packet_received(INT sockID,NX_PACKET * packet_ptr)10538 static VOID nx_bsd_udp_packet_received(INT sockID, NX_PACKET *packet_ptr)
10539 {
10540 
10541 NX_BSD_SOCKET *bsd_ptr;
10542 ULONG          addr_family;
10543 NX_BSD_SOCKET *exact_match = NX_NULL;
10544 NX_BSD_SOCKET *receiver_match = NX_NULL;
10545 NX_BSD_SOCKET *wildcard_match = NX_NULL;
10546 NX_INTERFACE   *interface_ptr;
10547 
10548 
10549     bsd_ptr = &nx_bsd_socket_array[sockID];
10550 
10551 #ifndef NX_DISABLE_IPV4
10552     if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
10553     {
10554         addr_family = AF_INET;
10555         interface_ptr = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
10556     }
10557     else
10558 #endif /* NX_DISABLE_IPV4 */
10559 #ifdef FEATURE_NX_IPV6
10560     if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
10561     {
10562         addr_family = AF_INET6;
10563         interface_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
10564     }
10565     else
10566 #endif /* FEATURE_NX_IPV6 */
10567     {
10568 
10569         /* Invalid version.  Release the packet and return. */
10570         nx_packet_release(packet_ptr);
10571 
10572         return;
10573     }
10574 
10575     /* Start the search for the BSD socket we received this packet on from current input socket ID.  */
10576     bsd_ptr = &nx_bsd_socket_array[sockID];
10577 
10578     do
10579     {
10580         /* Skip the sockets with different address family. */
10581         if(bsd_ptr -> nx_bsd_socket_family == addr_family)
10582         {
10583             /* bsd_ptr points to a related UDP socket. */
10584             if(bsd_ptr -> nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
10585             {
10586                 wildcard_match = bsd_ptr;
10587             }
10588             else if(((ULONG)(interface_ptr) == bsd_ptr -> nx_bsd_socket_local_bind_interface) ||
10589                     ((ULONG)(packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr) == bsd_ptr -> nx_bsd_socket_local_bind_interface))
10590             {
10591 
10592                 receiver_match = bsd_ptr;
10593             }
10594             else
10595             {
10596 
10597                 /* Does not match the local interface. Move to the next entry. */
10598                 bsd_ptr = bsd_ptr -> nx_bsd_socket_next;
10599                 continue;
10600             }
10601 
10602             /* At this point this socket is either a wildcard match or a receiver match. */
10603 
10604             /* If the socket is connected, we check for sender's address match. */
10605             if(bsd_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
10606             {
10607 
10608                 nxd_udp_source_extract(packet_ptr,
10609                                        &bsd_ptr -> nx_bsd_socket_source_ip_address,
10610                                        (UINT *)&bsd_ptr -> nx_bsd_socket_source_port);
10611 
10612 #ifndef NX_DISABLE_IPV4
10613                 if(bsd_ptr -> nx_bsd_socket_family == AF_INET)
10614                 {
10615 
10616                     /* Now we can check for an exact match based on sender IP address and port. */
10617                     if((bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v4 ==
10618                         bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v4) &&
10619                        (bsd_ptr -> nx_bsd_socket_source_port ==
10620                         bsd_ptr -> nx_bsd_socket_peer_port))
10621                     {
10622                         exact_match = bsd_ptr;
10623                     }
10624                 }
10625 #endif /* NX_DISABLE_IPV4 */
10626 #ifdef FEATURE_NX_IPV6
10627                 if(bsd_ptr -> nx_bsd_socket_family == AF_INET6)
10628                 {
10629 
10630                     /* Now we can check for an exact match based on sender IP address and port. */
10631                     if((bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[0] ==
10632                         bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[0]) &&
10633                        (bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[1] ==
10634                         bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[1]) &&
10635                        (bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[2] ==
10636                         bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[2]) &&
10637                        (bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[3] ==
10638                         bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[3]) &&
10639                        (bsd_ptr -> nx_bsd_socket_source_port ==
10640                         bsd_ptr -> nx_bsd_socket_peer_port))
10641                     {
10642 
10643                         exact_match = bsd_ptr;
10644                     }
10645                 }
10646 #endif
10647 
10648                 if(exact_match != NX_NULL)
10649                     break;
10650 
10651                 if(receiver_match != NX_NULL)
10652                     receiver_match = NX_NULL;
10653 
10654                 if(wildcard_match != NX_NULL)
10655                     wildcard_match = NX_NULL;
10656             }
10657         }
10658 
10659         /* Move to the next entry. */
10660         bsd_ptr = bsd_ptr -> nx_bsd_socket_next;
10661 
10662     }while(bsd_ptr != &nx_bsd_socket_array[sockID]);
10663 
10664     /* Let bsd_ptr point to the matched socket. */
10665     if(exact_match != NX_NULL)
10666         bsd_ptr = exact_match;
10667     else if(receiver_match != NX_NULL)
10668         bsd_ptr = receiver_match;
10669     else if(wildcard_match != NX_NULL)
10670         bsd_ptr = wildcard_match;
10671     else
10672     {
10673         /* This packet is not for any of the BSD sockets. Release the packet and we are done. */
10674         nx_packet_release(packet_ptr);
10675 
10676         return;
10677     }
10678 
10679     /* Move the packet to the socket internal receive queue. */
10680 
10681     if(bsd_ptr -> nx_bsd_socket_received_byte_count_max &&
10682        (bsd_ptr -> nx_bsd_socket_received_byte_count >= bsd_ptr -> nx_bsd_socket_received_byte_count_max))
10683     {
10684 
10685         /* Receive buffer is full.  Release the packet and return. */
10686         nx_packet_release(packet_ptr);
10687 
10688         return;
10689     }
10690 
10691     /* Drop the packet if the receive queue exceeds max depth.*/
10692     if(bsd_ptr -> nx_bsd_socket_received_packet_count >=
10693        bsd_ptr -> nx_bsd_socket_received_packet_count_max)
10694     {
10695 
10696         /* Receive buffer is full.  Release the packet and return. */
10697         nx_packet_release(packet_ptr);
10698 
10699         return;
10700     }
10701     if(bsd_ptr -> nx_bsd_socket_received_packet)
10702     {
10703         bsd_ptr -> nx_bsd_socket_received_packet_tail -> nx_packet_queue_next = packet_ptr;
10704     }
10705     else
10706     {
10707 
10708         bsd_ptr -> nx_bsd_socket_received_packet = packet_ptr;
10709         bsd_ptr -> nx_bsd_socket_received_packet_offset = 0;
10710     }
10711 
10712     bsd_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
10713     bsd_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
10714     bsd_ptr -> nx_bsd_socket_received_packet_count++;
10715 
10716     nx_bsd_select_wakeup((UINT)(bsd_ptr -> nx_bsd_socket_id), FDSET_READ);
10717 
10718     return;
10719 }
10720 
10721 /**************************************************************************/
10722 /*                                                                        */
10723 /*  FUNCTION                                               RELEASE        */
10724 /*                                                                        */
10725 /*    nx_bsd_tcp_syn_received_notify                      PORTABLE C      */
10726 /*                                                           6.1          */
10727 /*  AUTHOR                                                                */
10728 /*                                                                        */
10729 /*    Yuxin Zhou, Microsoft Corporation                                   */
10730 /*                                                                        */
10731 /*  DESCRIPTION                                                           */
10732 /*                                                                        */
10733 /*    This function checks if the socket has a connection request.        */
10734 /*                                                                        */
10735 /*  INPUT                                                                 */
10736 /*                                                                        */
10737 /*    socket_ptr                           Socket receiving the packet    */
10738 /*    packet_ptr                           Pointer to the received packet */
10739 /*                                                                        */
10740 /*  OUTPUT                                                                */
10741 /*                                                                        */
10742 /*    0                                     Not a valid match             */
10743 /*    1                                     Valid match found             */
10744 /*                                                                        */
10745 /*  CALLS                                                                 */
10746 /*                                                                        */
10747 /*    None                                                                */
10748 /*                                                                        */
10749 /*  CALLED BY                                                             */
10750 /*                                                                        */
10751 /*    NetX Duo                                                            */
10752 /*                                                                        */
10753 /*  RELEASE HISTORY                                                       */
10754 /*                                                                        */
10755 /*    DATE              NAME                      DESCRIPTION             */
10756 /*                                                                        */
10757 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10758 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10759 /*                                            resulting in version 6.1    */
10760 /*                                                                        */
10761 /**************************************************************************/
nx_bsd_tcp_syn_received_notify(NX_TCP_SOCKET * socket_ptr,NX_PACKET * packet_ptr)10762 static UINT  nx_bsd_tcp_syn_received_notify(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr)
10763 {
10764 
10765 UINT            bsd_socket_index;
10766 INT             i;
10767 INT             sockID_find;
10768 ULONG           addr_family;
10769 INT             search_index;
10770 INT             receiver_match = NX_BSD_MAX_SOCKETS;
10771 INT             wildcard_match = NX_BSD_MAX_SOCKETS;
10772 NX_BSD_SOCKET  *bsd_socket_ptr;
10773 NX_INTERFACE   *interface_ptr;
10774 
10775 
10776     bsd_socket_index = (UINT)socket_ptr -> nx_tcp_socket_reserved_ptr;
10777 
10778     if(bsd_socket_index >= NX_BSD_MAX_SOCKETS)
10779     {
10780 
10781         /* Bad socket index... simply return!  */
10782         return(NX_FALSE);
10783     }
10784 
10785     nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
10786 
10787 #ifndef NX_DISABLE_IPV4
10788     if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
10789     {
10790         addr_family = AF_INET;
10791     }
10792     else
10793 #endif /* NX_DISABLE_IPV4 */
10794     {
10795         addr_family = AF_INET6;
10796     }
10797 
10798     /* Start the search at the position of the input socket. */
10799     search_index = (INT)bsd_socket_index;
10800 
10801     /* Get the packet interface. */
10802 #ifdef FEATURE_NX_IPV6
10803     if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
10804 #endif /* FEATURE_NX_IPV6 */
10805         interface_ptr = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
10806 #ifdef FEATURE_NX_IPV6
10807     else if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
10808         interface_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
10809     else
10810         return (NX_FALSE);
10811 #endif /* FEATURE_NX_IPV6 */
10812 
10813     for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
10814     {
10815 
10816         bsd_socket_ptr = &nx_bsd_socket_array[search_index];
10817 
10818         /* Skip the unrelated sockets. */
10819         if((bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP) &&
10820            (bsd_socket_ptr -> nx_bsd_socket_family == addr_family) &&
10821            ((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED) == 0) &&
10822            (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) &&
10823            (bsd_socket_ptr -> nx_bsd_socket_local_port == socket_ptr -> nx_tcp_socket_port) &&
10824            (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
10825         {
10826 
10827             if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
10828             {
10829 
10830                 wildcard_match = search_index;
10831             }
10832             else if(((ULONG)(interface_ptr) == bsd_socket_ptr -> nx_bsd_socket_local_bind_interface) ||
10833                     ((ULONG)(packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr) == bsd_socket_ptr -> nx_bsd_socket_local_bind_interface))
10834             {
10835 
10836                 receiver_match = search_index;
10837 
10838                 /* Found a receiver match, which is a tighter match than the wildcard match.
10839                    So we can get out of the loop. */
10840                 break;
10841             }
10842         }
10843 
10844         /*  Move to the next entry. */
10845         search_index++;
10846 
10847         if(search_index >= NX_BSD_MAX_SOCKETS)
10848             search_index = 0;
10849     }
10850 
10851     if(receiver_match != NX_BSD_MAX_SOCKETS)
10852         sockID_find = receiver_match;
10853     else if(wildcard_match != NX_BSD_MAX_SOCKETS)
10854         sockID_find = wildcard_match;
10855     else
10856     {
10857 
10858         /* No match found.  Simply return .*/
10859         return(NX_FALSE);
10860     }
10861 
10862     /*  Found the listening master socket.  Update the master socket ID of the input socket. */
10863     nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_union_id.nx_bsd_socket_master_socket_id = sockID_find;
10864 
10865     return(NX_TRUE);
10866 }
10867 
10868 /**************************************************************************/
10869 /*                                                                        */
10870 /*  FUNCTION                                               RELEASE        */
10871 /*                                                                        */
10872 /*    nx_bsd_tcp_create_listen_socket                     PORTABLE C      */
10873 /*                                                           6.3.0        */
10874 /*  AUTHOR                                                                */
10875 /*                                                                        */
10876 /*    Yuxin Zhou, Microsoft Corporation                                   */
10877 /*                                                                        */
10878 /*  DESCRIPTION                                                           */
10879 /*                                                                        */
10880 /*    This routine sets up the input socket as a listen socket.           */
10881 /*                                                                        */
10882 /*  INPUT                                                                 */
10883 /*                                                                        */
10884 /*    master_sockid                        Index to the master socket     */
10885 /*    backlog                              Size of the socket listen queue*/
10886 /*                                                                        */
10887 /*  OUTPUT                                                                */
10888 /*                                                                        */
10889 /*    NX_SOC_OK                             Successfully set up socket    */
10890 /*    NX_SOC_ERROR                          Error setting up the socket   */
10891 /*                                                                        */
10892 /*  CALLS                                                                 */
10893 /*                                                                        */
10894 /*    socket                                Allocate a BSD socket         */
10895 /*    nx_bsd_socket_set_inherited_settings  Apply master socket options   */
10896 /*    nx_tcp_server_socket_listen           Enable the socket to listen   **/
10897 /*    nx_tcp_server_socket_accept           Wait for connection request   */
10898 /*    nx_tcp_server_socket_relisten         Reset the socket to listen    */
10899 /*                                                                        */
10900 /*  CALLED BY                                                             */
10901 /*                                                                        */
10902 /*    NetX Duo                                                            */
10903 /*                                                                        */
10904 /*  RELEASE HISTORY                                                       */
10905 /*                                                                        */
10906 /*    DATE              NAME                      DESCRIPTION             */
10907 /*                                                                        */
10908 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
10909 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
10910 /*                                            resulting in version 6.1    */
10911 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
10912 /*                                            used new API/structs naming,*/
10913 /*                                            resulting in version 6.3.0  */
10914 /*                                                                        */
10915 /**************************************************************************/
nx_bsd_tcp_create_listen_socket(INT master_sockid,INT backlog)10916 static INT nx_bsd_tcp_create_listen_socket(INT master_sockid, INT backlog)
10917 {
10918 
10919 INT                 i;
10920 UINT                status;
10921 UINT                local_port;
10922 NX_BSD_SOCKET       *master_socket_ptr = &nx_bsd_socket_array[master_sockid];
10923 NX_BSD_SOCKET       *bsd_secondary_socket;
10924 NX_BSD_SOCKET       *bsd_socket_ptr;
10925 NX_TCP_SOCKET       *sec_socket_ptr;
10926 INT                 secondary_sockID = NX_BSD_MAX_SOCKETS;
10927 
10928 
10929     /* This is called from BSD internal code so the BSD mutex is obtained. */
10930 
10931     /* Search through the sockets to find a master socket that is listening on the same port. */
10932     for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
10933     {
10934 
10935         /* Skip the entry if it is not master socket */
10936         if((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) == 0)
10937             continue;
10938 
10939         /* Skip the current master socket. */
10940         if(i == master_sockid)
10941             continue;
10942 
10943         /* Skip the entry if it is not TCP */
10944         if(nx_bsd_socket_array[i].nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
10945             continue;
10946 
10947         /* Skip the entry if the the secondary socket id field is not valid. */
10948         if(nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id == NX_BSD_MAX_SOCKETS)
10949             continue;
10950 
10951         /* Check if another master socket is listening on the same port.  */
10952         if((nx_bsd_socket_array[i].nx_bsd_socket_local_port == master_socket_ptr -> nx_bsd_socket_local_port) &&
10953            (nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id
10954             != (master_socket_ptr -> nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id)) &&
10955            (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN))
10956         {
10957 
10958             /* This one is. Point to the same secondary socket. */
10959             (master_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id =
10960               nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id;
10961             master_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ENABLE_LISTEN;
10962             master_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET);
10963             master_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_client_type =  NX_FALSE;
10964             master_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_SERVER_MASTER_SOCKET;
10965 
10966             return(NX_SOC_OK);
10967         }
10968     }
10969 
10970     /* Did not find an existing master socket for listening. */
10971 
10972     /* Check for a valid backlog. */
10973     if(backlog)
10974     {
10975 
10976         /* Check backlog argument is within limits.  */
10977         if (backlog > NX_BSD_MAX_LISTEN_BACKLOG)
10978         {
10979 
10980             /* Error, invalid backlog.  */
10981             /* Set the socket error if extended socket options enabled. */
10982             nx_bsd_set_errno(ENOBUFS);
10983 
10984             /* Return error code.  */
10985             NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
10986             return(NX_SOC_ERROR);
10987         }
10988     }
10989 
10990     /* Now create a dedicated secondary socket to listen for next client connection.  */
10991     secondary_sockID =  nx_bsd_socket((INT)(master_socket_ptr -> nx_bsd_socket_family), SOCK_STREAM, IPPROTO_TCP);
10992 
10993     /* Determine if there was an error.  */
10994     if (secondary_sockID == NX_SOC_ERROR)
10995     {
10996 
10997         /* Secondary socket create failed. Note: The socket thread error is set in socket().  */
10998         nx_bsd_set_errno(ENOMEM);
10999 
11000         /* Return error code.  */
11001         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
11002         return(NX_SOC_ERROR);
11003     }
11004 
11005     /* Adjust the secondary socket ID.  */
11006     secondary_sockID =  secondary_sockID - NX_BSD_SOCKFD_START;
11007 
11008     /* The master server socket will never connect to a client! For each successful
11009        client connection there will be a new secondary server socket and
11010        each such socket is associated with this master server socket. This is
11011        the difference between NetX and BSD sockets. The NetX listen() service is used
11012        with this secondary server socket.  */
11013 
11014     /* Set a pointer to the secondary socket. */
11015     bsd_secondary_socket = &nx_bsd_socket_array[secondary_sockID];
11016 
11017     /* Apply the master socket options to the secondary socket. */
11018     nx_bsd_socket_set_inherited_settings((UINT)master_sockid, (UINT)secondary_sockID);
11019 
11020     local_port = master_socket_ptr -> nx_bsd_socket_local_port;
11021 
11022     /* Invalidate the secondary master socket ID. */
11023     (bsd_secondary_socket -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id = NX_BSD_MAX_SOCKETS;
11024 
11025     /* Now call listen for the secondary server socket.  */
11026     if(backlog)
11027         status = nx_tcp_server_socket_listen(nx_bsd_default_ip, local_port, bsd_secondary_socket -> nx_bsd_socket_tcp_socket, (UINT)backlog, NX_NULL);
11028     else
11029     {
11030 
11031         /* Since a zero backlog is specified, this secondary socket needs to share with another master socket. */
11032         bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port = local_port;
11033 
11034         /* Check if a listen request is queued up for this socket. */
11035         nx_bsd_tcp_pending_connection(local_port, bsd_secondary_socket -> nx_bsd_socket_tcp_socket);
11036 
11037         status =  nx_tcp_server_socket_relisten(nx_bsd_default_ip, local_port, bsd_secondary_socket -> nx_bsd_socket_tcp_socket);
11038     }
11039 
11040     /* Check for an error.  */
11041     if ((status != NX_SUCCESS) && (status != NX_CONNECTION_PENDING))
11042     {
11043 
11044         /* Error, listen or relisten failed.  */
11045 
11046         /* Set the socket error depending on the NetX error status returned.  */
11047         nx_bsd_set_error_code(master_socket_ptr, status);
11048 
11049         /* Return error code.  */
11050         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
11051         return(NX_SOC_ERROR);
11052     }
11053 
11054     /* Now mark this as a master server socket listening to client connections.  */
11055     master_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ENABLE_LISTEN;
11056     master_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET);
11057     master_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_client_type =  NX_FALSE;
11058     master_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_SERVER_MASTER_SOCKET;
11059 
11060     /* This is a master socket.  So we use the nx_bsd_socket_master_socket_id field to
11061        record the secondary socket that is doing the real listen/accept work. */
11062     (master_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = secondary_sockID;
11063 
11064     /* Mark the secondary server socket as assigned to this master server socket.   */
11065     bsd_secondary_socket -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_ACCEPTING);
11066     bsd_secondary_socket -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET;
11067     bsd_secondary_socket -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ENABLE_LISTEN;
11068     bsd_secondary_socket -> nx_bsd_socket_local_port              =  (USHORT)local_port;
11069 
11070     /* If the master server socket is marked as non-blocking, we need to
11071        start the NetX accept process here. */
11072 
11073     sec_socket_ptr = bsd_secondary_socket -> nx_bsd_socket_tcp_socket;
11074 
11075     /* Allow accept from remote. */
11076     nx_tcp_server_socket_accept(sec_socket_ptr, 0);
11077 
11078     /* Set the master socket of other BSD TCP sockets that bind to the same port to the same secondary socket. */
11079     for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
11080     {
11081 
11082         bsd_socket_ptr = &nx_bsd_socket_array[i];
11083 
11084         if((bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP) &&
11085            (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CLIENT)) &&
11086            (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) &&
11087            (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN) &&
11088            (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND) &&
11089            (bsd_socket_ptr -> nx_bsd_socket_local_port == local_port))
11090         {
11091 
11092             (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = secondary_sockID;
11093         }
11094     }
11095 
11096     /* Check the relisten/listen status. */
11097     if(status == NX_CONNECTION_PENDING)
11098     {
11099 
11100         /* Set the connection pending flag. */
11101         bsd_secondary_socket -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
11102 
11103     }
11104 
11105     return(NX_SOC_OK);
11106 }
11107 
11108 /**************************************************************************/
11109 /*                                                                        */
11110 /*  FUNCTION                                               RELEASE        */
11111 /*                                                                        */
11112 /*    nx_bsd_tcp_pending_connection                       PORTABLE C      */
11113 /*                                                           6.1          */
11114 /*  AUTHOR                                                                */
11115 /*                                                                        */
11116 /*    Yuxin Zhou, Microsoft Corporation                                   */
11117 /*                                                                        */
11118 /*  DESCRIPTION                                                           */
11119 /*                                                                        */
11120 /*    This routine checks if the BSD TCP socket has a listen request      */
11121 /*    queued up on in the specified port.                                 */
11122 /*                                                                        */
11123 /*  INPUT                                                                 */
11124 /*                                                                        */
11125 /*    local_port                           Listening port                 */
11126 /*    socket_ptr                           Socket to check                */
11127 /*                                                                        */
11128 /*  OUTPUT                                                                */
11129 /*                                                                        */
11130 /*    None                                                                */
11131 /*                                                                        */
11132 /*  CALLS                                                                 */
11133 /*                                                                        */
11134 /*    nx_bsd_tcp_syn_received_notify        Match connection request      */
11135 /*                                             (packet) to input socket   */
11136 /*    nx_packet_receive                     Release packet to packet pool */
11137 /*                                                                        */
11138 /*  CALLED BY                                                             */
11139 /*                                                                        */
11140 /*    NetX Duo                                                            */
11141 /*                                                                        */
11142 /*  RELEASE HISTORY                                                       */
11143 /*                                                                        */
11144 /*    DATE              NAME                      DESCRIPTION             */
11145 /*                                                                        */
11146 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
11147 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
11148 /*                                            resulting in version 6.1    */
11149 /*                                                                        */
11150 /**************************************************************************/
nx_bsd_tcp_pending_connection(UINT local_port,NX_TCP_SOCKET * socket_ptr)11151 static VOID nx_bsd_tcp_pending_connection(UINT local_port, NX_TCP_SOCKET *socket_ptr)
11152 {
11153 
11154 struct NX_TCP_LISTEN_STRUCT *listen_ptr;
11155 NX_PACKET                   *packet_ptr;
11156 NX_TCP_HEADER               *tcp_header_ptr;
11157 UINT                         ret;
11158 
11159 
11160     listen_ptr = nx_bsd_default_ip -> nx_ip_tcp_active_listen_requests;
11161 
11162     if(listen_ptr)
11163     {
11164 
11165         do
11166         {
11167 
11168             if((listen_ptr -> nx_tcp_listen_port == local_port) &&
11169                (listen_ptr -> nx_tcp_listen_queue_current))
11170             {
11171 
11172                 do
11173                 {
11174 
11175                     packet_ptr = listen_ptr -> nx_tcp_listen_queue_head;
11176 
11177                     tcp_header_ptr = (NX_TCP_HEADER*)packet_ptr -> nx_packet_prepend_ptr;
11178 
11179                     if(tcp_header_ptr -> nx_tcp_header_word_3 & NX_TCP_SYN_BIT)
11180                     {
11181 
11182                         ret = nx_bsd_tcp_syn_received_notify(socket_ptr, packet_ptr);
11183 
11184                         /* Yes. We are done. */
11185                         if(ret == NX_TRUE)
11186                         {
11187 
11188                             return;
11189                         }
11190 
11191                         listen_ptr -> nx_tcp_listen_queue_head = packet_ptr -> nx_packet_queue_next;
11192 
11193                         if(packet_ptr == listen_ptr -> nx_tcp_listen_queue_tail)
11194                         {
11195                             listen_ptr -> nx_tcp_listen_queue_tail = NX_NULL;
11196                         }
11197 
11198                         listen_ptr -> nx_tcp_listen_queue_current--;
11199 
11200                         nx_packet_release(packet_ptr);
11201 
11202                     }
11203                 } while(listen_ptr -> nx_tcp_listen_queue_head);
11204             }
11205 
11206             listen_ptr = listen_ptr -> nx_tcp_listen_next;
11207 
11208         }while(listen_ptr != nx_bsd_default_ip -> nx_ip_tcp_active_listen_requests);
11209     }
11210 }
11211 
11212 /**************************************************************************/
11213 /*                                                                        */
11214 /*  FUNCTION                                               RELEASE        */
11215 /*                                                                        */
11216 /*    nx_bsd_find_interface_by_source_addr                PORTABLE C      */
11217 /*                                                           6.1          */
11218 /*  AUTHOR                                                                */
11219 /*                                                                        */
11220 /*    Yuxin Zhou, Microsoft Corporation                                   */
11221 /*                                                                        */
11222 /*  DESCRIPTION                                                           */
11223 /*                                                                        */
11224 /*    This function finds the interface index value of a given IPv4 or    */
11225 /*    IPv6 source address.                                                */
11226 /*                                                                        */
11227 /*  INPUT                                                                 */
11228 /*                                                                        */
11229 /*    addr_family                           Address Family                */
11230 /*    ip_addr                               Pointer to an array of IPv4   */
11231 /*                                            or IPv6 address             */
11232 /*                                                                        */
11233 /*  OUTPUT                                                                */
11234 /*                                                                        */
11235 /*    Index value                                                         */
11236 /*                                                                        */
11237 /*  CALLS                                                                 */
11238 /*                                                                        */
11239 /*    None                                                                */
11240 /*                                                                        */
11241 /*  CALLED BY                                                             */
11242 /*                                                                        */
11243 /*    nx_bsd_send_internal                                                */
11244 /*                                                                        */
11245 /*  RELEASE HISTORY                                                       */
11246 /*                                                                        */
11247 /*    DATE              NAME                      DESCRIPTION             */
11248 /*                                                                        */
11249 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
11250 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
11251 /*                                            resulting in version 6.1    */
11252 /*                                                                        */
11253 /**************************************************************************/
nx_bsd_find_interface_by_source_addr(UINT addr_family,ULONG * ip_addr)11254 static INT   nx_bsd_find_interface_by_source_addr(UINT addr_family, ULONG* ip_addr)
11255 {
11256 INT i;
11257 #ifndef NX_DISABLE_IPV4
11258 ULONG ipv4_addr;
11259 #endif /* NX_DISABLE_IPV4 */
11260 #ifdef FEATURE_NX_IPV6
11261 ULONG ipv6_addr[4];
11262 #endif
11263 
11264 #ifndef NX_DISABLE_IPV4
11265     if(addr_family == AF_INET)
11266     {
11267         ipv4_addr = *ip_addr;
11268         NX_CHANGE_ULONG_ENDIAN(ipv4_addr);
11269 
11270         for(i = 0; i < NX_MAX_IP_INTERFACES; i++)
11271         {
11272             if((nx_bsd_default_ip -> nx_ip_interface[i].nx_interface_valid) &&
11273                (nx_bsd_default_ip -> nx_ip_interface[i].nx_interface_ip_address == ipv4_addr))
11274                 return i;
11275         }
11276     }
11277 #endif /* NX_DISABLE_IPV4 */
11278 #ifdef FEATURE_NX_IPV6
11279     if(addr_family == AF_INET6)
11280     {
11281         ipv6_addr[0] = *(ip_addr);
11282         ipv6_addr[1] = *(ip_addr + 1);
11283         ipv6_addr[2] = *(ip_addr + 2);
11284         ipv6_addr[3] = *(ip_addr + 3);
11285         NX_IPV6_ADDRESS_CHANGE_ENDIAN(ipv6_addr);
11286 
11287         for(i = 0; i < NX_MAX_IPV6_ADDRESSES; i++)
11288         {
11289 
11290             if((nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address_valid) &&
11291                (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address_attached -> nx_interface_valid) &&
11292                (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address[0] == ipv6_addr[0]) &&
11293                (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address[1] == ipv6_addr[1]) &&
11294                (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address[2] == ipv6_addr[2]) &&
11295                (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address[3] == ipv6_addr[3]))
11296                 return i;
11297         }
11298     }
11299 #endif
11300 
11301     return((INT)(NX_BSD_LOCAL_IF_INADDR_ANY));
11302 
11303 }
11304 
11305 
11306 #ifndef NX_DISABLE_IPV4
11307 /**************************************************************************/
11308 /*                                                                        */
11309 /*  FUNCTION                                               RELEASE        */
11310 /*                                                                        */
11311 /*    _nxd_bsd_ipv4_packet_send                           PORTABLE C      */
11312 /*                                                           6.1          */
11313 /*  AUTHOR                                                                */
11314 /*                                                                        */
11315 /*    Yuxin Zhou, Microsoft Corporation                                   */
11316 /*                                                                        */
11317 /*  DESCRIPTION                                                           */
11318 /*                                                                        */
11319 /*    This function computes the IP header checksum and updates that into */
11320 /*    the ip header ,which is assumed to be already prepended in the      */
11321 /*    input packet buffer, and forwards it to the driver directly.        */
11322 /*                                                                        */
11323 /*  INPUT                                                                 */
11324 /*                                                                        */
11325 /*    packet_ptr                            Pointer to packet to send     */
11326 /*                                                                        */
11327 /*  OUTPUT                                                                */
11328 /*                                                                        */
11329 /*    None                                                                */
11330 /*                                                                        */
11331 /*  CALLS                                                                 */
11332 /*                                                                        */
11333 /*    _nx_ip_checksum_compute               Compute IP checksum           */
11334 /*    (_nx_arp_entry_allocate)              ARP entry allocate service    */
11335 /*    (_nx_arp_packet_send)                 Send an ARP packet            */
11336 /*    _nx_ip_packet_deferred_receive        Receive loopback packet       */
11337 /*    _nx_packet_copy                       Copy packet to input packet   */
11338 /*    _nx_packet_transmit_release           Release transmit packet       */
11339 /*    (nx_ip_fragment_processing)           Fragment processing           */
11340 /*    (ip_link_driver)                      User supplied link driver     */
11341 /*                                                                        */
11342 /*  CALLED BY                                                             */
11343 /*                                                                        */
11344 /*    nx_bsd_send_internal                                                */
11345 /*                                                                        */
11346 /*  RELEASE HISTORY                                                       */
11347 /*                                                                        */
11348 /*    DATE              NAME                      DESCRIPTION             */
11349 /*                                                                        */
11350 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
11351 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
11352 /*                                            resulting in version 6.1    */
11353 /*                                                                        */
11354 /**************************************************************************/
_nxd_bsd_ipv4_packet_send(NX_PACKET * packet_ptr)11355 static VOID  _nxd_bsd_ipv4_packet_send(NX_PACKET *packet_ptr)
11356 {
11357 
11358 TX_INTERRUPT_SAVE_AREA
11359 NX_IP_DRIVER            driver_request;
11360 NX_IPV4_HEADER         *ip_header_ptr;
11361 #ifndef NX_DISABLE_IP_TX_CHECKSUM
11362 ULONG                   checksum;
11363 ULONG                   val;
11364 #endif
11365 UINT                    index;
11366 NX_ARP                 *arp_ptr;
11367 NX_PACKET              *last_packet;
11368 NX_PACKET              *remove_packet;
11369 UINT                    queued_count;
11370 NX_PACKET              *packet_copy;
11371 ULONG                   network_mask;
11372 ULONG                   network;
11373 NX_IP *                 ip_ptr;
11374 ULONG                   destination_ip;
11375 
11376     ip_ptr = nx_bsd_default_ip;
11377 #ifndef NX_DISABLE_IP_INFO
11378 
11379     /* Increment the total send requests counter.  */
11380     ip_ptr -> nx_ip_total_packet_send_requests++;
11381 #endif
11382 
11383 
11384     /* Setup the IP header pointer.  */
11385     ip_header_ptr =  (NX_IPV4_HEADER *) packet_ptr -> nx_packet_prepend_ptr;
11386 
11387     destination_ip = ip_header_ptr -> nx_ip_header_destination_ip;
11388 
11389     /* Swap the destination address to host byte order.*/
11390     NX_CHANGE_ULONG_ENDIAN(destination_ip);
11391 
11392 #ifndef NX_DISABLE_IP_TX_CHECKSUM
11393     checksum = _nx_ip_checksum_compute(packet_ptr, NX_IP_VERSION_V4,
11394                                        /* Length is the size of IP header, including options */
11395                                        (UINT)((*(UCHAR*)ip_header_ptr & 0xf) << 2),
11396                                        /* IPv4 header checksum does not use src/dest addresses */
11397                                        NULL, NULL);
11398 
11399     val = (ULONG)(~checksum);
11400     val = val & NX_LOWER_16_MASK;
11401 
11402     /* Convert to network byte order. */
11403     NX_CHANGE_ULONG_ENDIAN(val);
11404 
11405     /* Now store the checksum in the IP header.  */
11406     ip_header_ptr -> nx_ip_header_word_2 =  ip_header_ptr -> nx_ip_header_word_2 | val;
11407 
11408 #endif
11409 
11410     /* Determine if physical mapping is needed by the link driver.  */
11411     if (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_address_mapping_needed )
11412     {
11413 
11414 
11415         network_mask = packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_network_mask;
11416         network = packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_network;
11417 
11418         /* Determine whether or not the destination address is out of  this local network.  */
11419         if (((destination_ip & network_mask) != network) ||
11420             ((destination_ip & ~network_mask) == ~network_mask) ||
11421              (destination_ip == packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_address))
11422         {
11423 
11424             /* We have an out-of-network destination IP address, check for a variety
11425                of out-of-network destinations.  */
11426 
11427             /* Determine if an IP limited or directed broadcast is requested.  */
11428             if ((destination_ip == NX_IP_LIMITED_BROADCAST) ||
11429                 (((destination_ip & network_mask) == network) &&
11430                  ((destination_ip & ~network_mask) == ~network_mask)))
11431             {
11432 
11433                 /* Build the driver request.  */
11434                 driver_request.nx_ip_driver_ptr =                   ip_ptr;
11435                 driver_request.nx_ip_driver_command =               NX_LINK_PACKET_BROADCAST;
11436                 driver_request.nx_ip_driver_packet =                packet_ptr;
11437                 driver_request.nx_ip_driver_physical_address_msw =  0xFFFFUL;
11438                 driver_request.nx_ip_driver_physical_address_lsw =  0xFFFFFFFFUL;
11439                 driver_request.nx_ip_driver_interface =             packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11440 
11441 #ifndef NX_DISABLE_FRAGMENTATION
11442                 /* Determine if fragmentation is needed.  */
11443                 if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
11444                 {
11445 
11446                     /* Fragmentation is needed, call the fragment routine if available. */
11447                     if (ip_ptr -> nx_ip_fragment_processing)
11448                     {
11449 
11450                         /* Call the IP fragment processing routine.  */
11451                         (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
11452                     }
11453                     else
11454                     {
11455 
11456 #ifndef NX_DISABLE_IP_INFO
11457 
11458                         /* Increment the IP send packets dropped count.  */
11459                         ip_ptr -> nx_ip_send_packets_dropped++;
11460 #endif
11461                         /* Just release the packet.  */
11462                         _nx_packet_transmit_release(packet_ptr);
11463                     }
11464 
11465                     /* In either case, this packet send is complete, just return.  */
11466                     return;
11467                 }
11468 #endif
11469 
11470 #ifndef NX_DISABLE_IP_INFO
11471 
11472                 /* Increment the IP packet sent count.  */
11473                 ip_ptr -> nx_ip_total_packets_sent++;
11474 
11475                 /* Increment the IP bytes sent count.  */
11476                 ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11477 #endif
11478 
11479                 /* Broadcast packet.  */
11480                 (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
11481 
11482                 return;
11483             }
11484 
11485             /* Determine if we have a loopback address.  */
11486             else if ((((destination_ip >= NX_IP_LOOPBACK_FIRST) &&
11487                        (destination_ip <= NX_IP_LOOPBACK_LAST))) ||
11488                        (destination_ip == ip_ptr -> nx_ip_interface[0].nx_interface_ip_address))
11489             {
11490 
11491                 /* Yes, we have an internal loopback address.  */
11492 
11493                 /* Copy the packet so it can be enqueued properly by the receive
11494                    processing.  */
11495                 if (_nx_packet_copy(packet_ptr, &packet_copy, ip_ptr -> nx_ip_default_packet_pool, NX_NO_WAIT) == NX_SUCCESS)
11496                 {
11497 
11498 #ifndef NX_DISABLE_IP_INFO
11499 
11500                     /* Increment the IP packet sent count.  */
11501                     ip_ptr -> nx_ip_total_packets_sent++;
11502 
11503                     /* Increment the IP bytes sent count.  */
11504                     ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11505 #endif
11506 
11507                     /* Send the packet to this IP's receive processing like it came in from the
11508                        driver.  */
11509                     _nx_ip_packet_deferred_receive(ip_ptr, packet_copy);
11510                 }
11511 #ifndef NX_DISABLE_IP_INFO
11512                 else
11513                 {
11514 
11515                     /* Increment the IP send packets dropped count.  */
11516                     ip_ptr -> nx_ip_send_packets_dropped++;
11517 
11518                     /* Increment the IP transmit resource error count.  */
11519                     ip_ptr -> nx_ip_transmit_resource_errors++;
11520                 }
11521 #endif
11522 
11523                 /* Release the transmit packet.  */
11524                 _nx_packet_transmit_release(packet_ptr);
11525                 return;
11526             }
11527 
11528             /* Determine if we have a class D multicast address.  */
11529             else if ((destination_ip & NX_IP_CLASS_D_MASK) == NX_IP_CLASS_D_TYPE)
11530             {
11531 
11532                 /* Yes, we have a class D multicast address.  Derive the physical mapping from
11533                    the class D address.  */
11534                 driver_request.nx_ip_driver_physical_address_msw =  NX_IP_MULTICAST_UPPER;
11535                 driver_request.nx_ip_driver_physical_address_lsw =  NX_IP_MULTICAST_LOWER | (destination_ip & NX_IP_MULTICAST_MASK);
11536                 driver_request.nx_ip_driver_interface =             packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11537 
11538                 /* Determine if the group address has been joined in this IP instance.  */
11539                 index =  0;
11540                 while (index < NX_MAX_MULTICAST_GROUPS)
11541                 {
11542 
11543                     /* Determine if the destination address matches the requested address.  */
11544                     if (ip_ptr -> nx_ipv4_multicast_entry[index].nx_ipv4_multicast_join_list == destination_ip)
11545                     {
11546 
11547                         /* Yes, break the loop!  */
11548                         break;
11549                     }
11550 
11551                     /* Increment the join list index.  */
11552                     index++;
11553                 }
11554 
11555                 /* Determine if the group was joined by this IP instance.  */
11556                 if (index < NX_MAX_MULTICAST_GROUPS)
11557                 {
11558 
11559                     /* Determine if the group has loopback enabled.  */
11560                     if (ip_ptr -> nx_ipv4_multicast_entry[index].nx_ipv4_multicast_loopback_enable)
11561                     {
11562 
11563                         /* Yes, loopback is enabled!  */
11564 
11565                         /* Copy the packet so we can send it via loopback.  */
11566                         if (_nx_packet_copy(packet_ptr, &packet_copy, ip_ptr -> nx_ip_default_packet_pool, NX_NO_WAIT) == NX_SUCCESS)
11567                         {
11568 
11569 #ifndef NX_DISABLE_IP_INFO
11570 
11571                             /* Increment the IP packet sent count.  */
11572                             ip_ptr -> nx_ip_total_packets_sent++;
11573 
11574                             /* Increment the IP bytes sent count.  */
11575                             ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11576 #endif
11577 
11578                             /* Packet copy was successful. Send the packet to this IP's receive processing like it came in from the
11579                                driver.  */
11580                             _nx_ip_packet_deferred_receive(ip_ptr, packet_copy);
11581                         }
11582 #ifndef NX_DISABLE_IP_INFO
11583                         else
11584                         {
11585 
11586                             /* Increment the IP send packets dropped count.  */
11587                             ip_ptr -> nx_ip_send_packets_dropped++;
11588 
11589                             /* Increment the IP transmit resource error count.  */
11590                             ip_ptr -> nx_ip_transmit_resource_errors++;
11591                         }
11592 #endif
11593                     }
11594                 }
11595 
11596                 /* Build the driver request.  */
11597                 driver_request.nx_ip_driver_ptr =      ip_ptr;
11598                 driver_request.nx_ip_driver_command =  NX_LINK_PACKET_SEND;
11599                 driver_request.nx_ip_driver_packet =   packet_ptr;
11600                 driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11601 
11602 #ifndef NX_DISABLE_FRAGMENTATION
11603                 /* Determine if fragmentation is needed.  */
11604                 if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
11605                 {
11606 
11607                     /* Fragmentation is needed, call the fragment routine if available. */
11608                     if (ip_ptr -> nx_ip_fragment_processing)
11609                     {
11610 
11611                         /* Call the IP fragment processing routine.  */
11612                         (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
11613                     }
11614                     else
11615                     {
11616 
11617 #ifndef NX_DISABLE_IP_INFO
11618 
11619                         /* Increment the IP send packets dropped count.  */
11620                         ip_ptr -> nx_ip_send_packets_dropped++;
11621 #endif
11622                         /* Just release the packet.  */
11623                         _nx_packet_transmit_release(packet_ptr);
11624                     }
11625 
11626                     /* In either case, this packet send is complete, just return.  */
11627                     return;
11628                 }
11629 #endif
11630 
11631 #ifndef NX_DISABLE_IP_INFO
11632 
11633                 /* Increment the IP packet sent count.  */
11634                 ip_ptr -> nx_ip_total_packets_sent++;
11635 
11636                 /* Increment the IP bytes sent count.  */
11637                 ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11638 #endif
11639 
11640                 /* Send the IP packet out on the network via the attached driver.  */
11641                 (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
11642 
11643                 /* Return to caller.  */
11644                 return;
11645             }
11646 
11647             /* Use default gateway. */
11648             else
11649             {
11650 
11651                 /* We have an out-of-network destination IP address, check to see if a
11652                    Gateway IP address has been specified.  */
11653                 if (ip_ptr -> nx_ip_gateway_address)
11654                 {
11655 
11656                     /* Remap the destination IP address to the Gateway IP address.  The ARP
11657                        processing below will handle getting the physical address for the
11658                        Gateway.  */
11659                     destination_ip =  ip_ptr -> nx_ip_gateway_address;
11660                 }
11661                 else
11662                 {
11663 
11664 #ifndef NX_DISABLE_IP_INFO
11665 
11666                     /* Increment the number of no route errors.  */
11667                     ip_ptr -> nx_ip_transmit_no_route_errors++;
11668 
11669                     /* Increment the IP send packets dropped count.  */
11670                     ip_ptr -> nx_ip_send_packets_dropped++;
11671 #endif
11672                     /* Just release the packet.  */
11673                     _nx_packet_transmit_release(packet_ptr);
11674 
11675                     /* In either case, this packet send is complete, just return.  */
11676                     return;
11677                 }
11678             }
11679         }
11680 
11681         /* Yes, look into the ARP Routing Table to derive the physical address.  */
11682 
11683         /* Calculate the hash index for the destination IP address.  */
11684         index =  (UINT) ((destination_ip + (destination_ip >> 8)) & NX_ARP_TABLE_MASK);
11685 
11686         /* Disable interrupts temporarily.  */
11687         TX_DISABLE
11688 
11689         /* Determine if there is an entry for this IP address.  */
11690         arp_ptr =  ip_ptr -> nx_ip_arp_table[index];
11691 
11692         /* Determine if this arp entry matches the destination IP address.  */
11693         if ((arp_ptr) && (arp_ptr -> nx_arp_ip_address == destination_ip))
11694         {
11695 
11696             /* Yes, we have an existing ARP mapping entry.  */
11697 
11698             /* Determine if there is a physical address.  */
11699             if (arp_ptr -> nx_arp_physical_address_msw | arp_ptr -> nx_arp_physical_address_lsw)
11700             {
11701 
11702                 /* Yes, we have a physical mapping.  Copy the physical address into the driver
11703                    request structure.  */
11704                 driver_request.nx_ip_driver_physical_address_msw =  arp_ptr -> nx_arp_physical_address_msw;
11705                 driver_request.nx_ip_driver_physical_address_lsw =  arp_ptr -> nx_arp_physical_address_lsw;
11706 
11707                 /* Restore interrupts.  */
11708                 TX_RESTORE
11709 
11710                 /* Build the driver request.  */
11711                 driver_request.nx_ip_driver_ptr =      ip_ptr;
11712                 driver_request.nx_ip_driver_command =  NX_LINK_PACKET_SEND;
11713                 driver_request.nx_ip_driver_packet =   packet_ptr;
11714                 driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11715 
11716 #ifndef NX_DISABLE_FRAGMENTATION
11717                 /* Determine if fragmentation is needed.  */
11718                 if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
11719                 {
11720 
11721                     /* Fragmentation is needed, call the fragment routine if available. */
11722                     if (ip_ptr -> nx_ip_fragment_processing)
11723                     {
11724 
11725                         /* Call the IP fragment processing routine.  */
11726                         (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
11727                     }
11728                     else
11729                     {
11730 
11731 #ifndef NX_DISABLE_IP_INFO
11732 
11733                         /* Increment the IP send packets dropped count.  */
11734                         ip_ptr -> nx_ip_send_packets_dropped++;
11735 #endif
11736 
11737                         /* Just release the packet.  */
11738                         _nx_packet_transmit_release(packet_ptr);
11739                     }
11740 
11741                     /* In either case, this packet send is complete, just return.  */
11742                     return;
11743                 }
11744 #endif
11745 
11746 #ifndef NX_DISABLE_IP_INFO
11747 
11748                 /* Increment the IP packet sent count.  */
11749                 ip_ptr -> nx_ip_total_packets_sent++;
11750 
11751                 /* Increment the IP bytes sent count.  */
11752                 ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11753 #endif
11754 
11755                 /* Send the IP packet out on the network via the attached driver.  */
11756                 (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
11757 
11758                 /* Return to caller.  */
11759                 return;
11760             }
11761             else
11762             {
11763 
11764                 /* Ensure the current packet's queue next pointer to NULL.  */
11765                 packet_ptr -> nx_packet_queue_next =  NX_NULL;
11766 
11767                 /* Determine if the queue is empty.  */
11768                 if (arp_ptr -> nx_arp_packets_waiting == NX_NULL)
11769                 {
11770 
11771                     /* Yes, we have an empty ARP packet queue.  Simply place the
11772                        packet at the head of the list.  */
11773                     arp_ptr -> nx_arp_packets_waiting =  packet_ptr;
11774 
11775                     /* Restore interrupts.  */
11776                     TX_RESTORE
11777                 }
11778                 else
11779                 {
11780 
11781                     /* Determine how many packets are on the ARP entry's packet
11782                        queue and remember the last packet in the queue.  We know
11783                        there is at least one on the queue and another that is
11784                        going to be queued.  */
11785                     last_packet =  arp_ptr -> nx_arp_packets_waiting;
11786                     queued_count = 0;
11787                     while (last_packet -> nx_packet_queue_next)
11788                     {
11789 
11790                         /* Increment the queued count.  */
11791                         queued_count++;
11792 
11793                         /* Move to the next packet in the queue.  */
11794                         last_packet =  last_packet -> nx_packet_queue_next;
11795                     }
11796 
11797                     /* Place the packet at the end of the list.  */
11798                     last_packet -> nx_packet_queue_next =  packet_ptr;
11799 
11800                     /* Default the remove packet pointer to NULL.  */
11801                     remove_packet =  NX_NULL;
11802 
11803                     /* Determine if the packets queued has exceeded the queue
11804                        depth.  */
11805                     if (queued_count >= NX_ARP_MAX_QUEUE_DEPTH)
11806                     {
11807 
11808                         /* Save the packet pointer at the head of the list.  */
11809                         remove_packet =  arp_ptr -> nx_arp_packets_waiting;
11810 
11811                         /* Remove the packet from the ARP queue.  */
11812                         arp_ptr -> nx_arp_packets_waiting =  remove_packet -> nx_packet_queue_next;
11813 
11814                         /* Clear the remove packet queue next pointer.  */
11815                         remove_packet -> nx_packet_queue_next =  NX_NULL;
11816 
11817 #ifndef NX_DISABLE_IP_INFO
11818 
11819                         /* Increment the IP transmit resource error count.  */
11820                         ip_ptr -> nx_ip_transmit_resource_errors++;
11821 
11822                         /* Increment the IP send packets dropped count.  */
11823                         ip_ptr -> nx_ip_send_packets_dropped++;
11824 #endif
11825                     }
11826 
11827                     /* Restore interrupts.  */
11828                     TX_RESTORE
11829 
11830                     /* Determine if there is a packet to remove.  */
11831                     if (remove_packet)
11832                     {
11833 
11834                         /* Yes, the packet queue depth for this ARP entry was exceeded
11835                            so release the packet that was removed from the queue.  */
11836                         _nx_packet_transmit_release(remove_packet);
11837                     }
11838                 }
11839 
11840                 /* Return to caller.  */
11841                 return;
11842             }
11843         }
11844         else
11845         {
11846 
11847             /* At this point, we need to search the ARP list for a match for the
11848                destination IP.  */
11849 
11850             /* First, restore interrupts.  */
11851             TX_RESTORE
11852 
11853             /* Pickup the first ARP entry.  */
11854             arp_ptr =  ip_ptr -> nx_ip_arp_table[index];
11855 
11856             /* Loop to look for an ARP match.  */
11857             while (arp_ptr)
11858             {
11859 
11860                 /* Check for an IP match.  */
11861                 if (arp_ptr -> nx_arp_ip_address == destination_ip)
11862                 {
11863 
11864                     /* Yes, we found a match.  Get out of the loop!  */
11865                     break;
11866                 }
11867 
11868                 /* Move to the next active ARP entry.  */
11869                 arp_ptr =  arp_ptr -> nx_arp_active_next;
11870 
11871                 /* Determine if we are at the end of the ARP list.  */
11872                 if (arp_ptr == ip_ptr -> nx_ip_arp_table[index])
11873                 {
11874                     /* Clear the ARP pointer.  */
11875                     arp_ptr =  NX_NULL;
11876                     break;
11877                 }
11878             }
11879 
11880             /* Determine if we actually found a matching ARP entry.  */
11881             if (arp_ptr)
11882             {
11883 
11884                 /* Yes, we found an ARP entry.  Now check and see if
11885                    it has an actual physical address.  */
11886                 if (arp_ptr -> nx_arp_physical_address_msw | arp_ptr -> nx_arp_physical_address_lsw)
11887                 {
11888 
11889                     /* Yes, we have a physical mapping.  Copy the physical address into the driver
11890                        request structure.  */
11891                     driver_request.nx_ip_driver_physical_address_msw =  arp_ptr -> nx_arp_physical_address_msw;
11892                     driver_request.nx_ip_driver_physical_address_lsw =  arp_ptr -> nx_arp_physical_address_lsw;
11893 
11894                     /* Disable interrupts.  */
11895                     TX_DISABLE
11896 
11897                     /* Move this ARP entry to the head of the list.  */
11898                     ip_ptr -> nx_ip_arp_table[index] =  arp_ptr;
11899 
11900                     /* Restore interrupts.  */
11901                     TX_RESTORE
11902 
11903                     /* Build the driver request message.  */
11904                     driver_request.nx_ip_driver_ptr =      ip_ptr;
11905                     driver_request.nx_ip_driver_command =  NX_LINK_PACKET_SEND;
11906                     driver_request.nx_ip_driver_packet =   packet_ptr;
11907                     driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11908 
11909 #ifndef NX_DISABLE_FRAGMENTATION
11910                     /* Determine if fragmentation is needed.  */
11911                     if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
11912                     {
11913 
11914                         /* Fragmentation is needed, call the fragment routine if available. */
11915                         if (ip_ptr -> nx_ip_fragment_processing)
11916                         {
11917 
11918                             /* Call the IP fragment processing routine.  */
11919                             (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
11920                         }
11921                         else
11922                         {
11923 
11924 #ifndef NX_DISABLE_IP_INFO
11925 
11926                             /* Increment the IP send packets dropped count.  */
11927                             ip_ptr -> nx_ip_send_packets_dropped++;
11928 #endif
11929 
11930                             /* Just release the packet.  */
11931                             _nx_packet_transmit_release(packet_ptr);
11932                         }
11933 
11934                         /* In either case, this packet send is complete, just return.  */
11935                         return;
11936                     }
11937 #endif
11938 
11939 #ifndef NX_DISABLE_IP_INFO
11940 
11941                     /* Increment the IP packet sent count.  */
11942                     ip_ptr -> nx_ip_total_packets_sent++;
11943 
11944                     /* Increment the IP bytes sent count.  */
11945                     ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11946 #endif
11947 
11948                     /* Send the IP packet out on the network via the attached driver.  */
11949                     (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
11950 
11951                     /* Return to caller.  */
11952                     return;
11953                 }
11954                 else
11955                 {
11956 
11957                     /* We don't have physical mapping.  */
11958 
11959                     /* Disable interrupts.  */
11960                     TX_DISABLE
11961 
11962                     /* Ensure the current packet's queue next pointer to NULL.  */
11963                     packet_ptr -> nx_packet_queue_next =  NX_NULL;
11964 
11965                     /* Determine if the queue is empty.  */
11966                     if (arp_ptr -> nx_arp_packets_waiting == NX_NULL)
11967                     {
11968 
11969                         /* Yes, we have an empty ARP packet queue.  Simply place the
11970                            packet at the head of the list.  */
11971                         arp_ptr -> nx_arp_packets_waiting =  packet_ptr;
11972 
11973                         /* Restore interrupts.  */
11974                         TX_RESTORE
11975                     }
11976                     else
11977                     {
11978 
11979 
11980                         /* Determine how many packets are on the ARP entry's packet
11981                            queue and remember the last packet in the queue.  We know
11982                            there is at least one on the queue and another that is
11983                            going to be queued.  */
11984                         last_packet =  arp_ptr -> nx_arp_packets_waiting;
11985                         queued_count = 0;
11986                         while (last_packet -> nx_packet_queue_next)
11987                         {
11988 
11989                             /* Increment the queued count.  */
11990                             queued_count++;
11991 
11992                             /* Move to the next packet in the queue.  */
11993                             last_packet =  last_packet -> nx_packet_queue_next;
11994                         }
11995 
11996                         /* Place the packet at the end of the list.  */
11997                         last_packet -> nx_packet_queue_next =  packet_ptr;
11998 
11999                         /* Default the remove packet pointer to NULL.  */
12000                         remove_packet =  NX_NULL;
12001 
12002                         /* Determine if the packets queued has exceeded the queue
12003                            depth.  */
12004                         if (queued_count >= NX_ARP_MAX_QUEUE_DEPTH)
12005                         {
12006 
12007                             /* Save the packet pointer at the head of the list.  */
12008                             remove_packet =  arp_ptr -> nx_arp_packets_waiting;
12009 
12010                             /* Remove the packet from the ARP queue.  */
12011                             arp_ptr -> nx_arp_packets_waiting =  remove_packet -> nx_packet_queue_next;
12012 
12013                             /* Clear the remove packet queue next pointer.  */
12014                             remove_packet -> nx_packet_queue_next =  NX_NULL;
12015 
12016 #ifndef NX_DISABLE_IP_INFO
12017 
12018                             /* Increment the IP transmit resource error count.  */
12019                             ip_ptr -> nx_ip_transmit_resource_errors++;
12020 
12021                             /* Increment the IP send packets dropped count.  */
12022                             ip_ptr -> nx_ip_send_packets_dropped++;
12023 #endif
12024                         }
12025 
12026                         /* Restore interrupts.  */
12027                         TX_RESTORE
12028 
12029                         /* Determine if there is a packet to remove.  */
12030                         if (remove_packet)
12031                         {
12032 
12033                             /* Yes, the packet queue depth for this ARP entry was exceeded
12034                                so release the packet that was removed from the queue.  */
12035                             _nx_packet_transmit_release(remove_packet);
12036                         }
12037                     }
12038 
12039                     /* Return to caller.  */
12040                     return;
12041                 }
12042             }
12043             else
12044             {
12045 
12046                 /* No ARP entry was found.  We need to allocate a new ARP entry, populate it, and
12047                    initiate an ARP request to get the specific physical mapping.  */
12048 
12049                 /* Allocate a new ARP entry.  */
12050                 if ((!ip_ptr -> nx_ip_arp_allocate) ||
12051                                     ((ip_ptr -> nx_ip_arp_allocate)(ip_ptr, &(ip_ptr -> nx_ip_arp_table[index]), NX_FALSE)))
12052                 {
12053 
12054                     /* Error, release the protection and the packet.  */
12055 
12056 #ifndef NX_DISABLE_IP_INFO
12057 
12058                     /* Increment the IP transmit resource error count.  */
12059                     ip_ptr -> nx_ip_transmit_resource_errors++;
12060 
12061                     /* Increment the IP send packets dropped count.  */
12062                     ip_ptr -> nx_ip_send_packets_dropped++;
12063 #endif
12064 
12065                     /* Release the packet.  */
12066                     _nx_packet_transmit_release(packet_ptr);
12067 
12068                     /* Just return!  */
12069                     return;
12070                 }
12071 
12072                 /* Otherwise, setup a pointer to the new ARP entry.  */
12073                 arp_ptr =  (ip_ptr -> nx_ip_arp_table[index]) -> nx_arp_active_previous;
12074 
12075                 /* Setup the IP address and clear the physical mapping.  */
12076                 arp_ptr -> nx_arp_ip_address =            destination_ip;
12077                 arp_ptr -> nx_arp_physical_address_msw =  0;
12078                 arp_ptr -> nx_arp_physical_address_lsw =  0;
12079                 arp_ptr -> nx_arp_entry_next_update =     NX_ARP_EXPIRATION_RATE;
12080                 arp_ptr -> nx_arp_retries =               0;
12081                 arp_ptr -> nx_arp_ip_interface =          packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
12082 
12083                 /* Ensure the queue next pointer is NULL for the packet before it
12084                    is placed on the ARP waiting queue.  */
12085                 packet_ptr -> nx_packet_queue_next =  NX_NULL;
12086 
12087                 /* Queue the packet for output.  */
12088                 arp_ptr -> nx_arp_packets_waiting =  packet_ptr;
12089 
12090                 /* Call ARP send to send an ARP request.  */
12091                 (ip_ptr -> nx_ip_arp_packet_send)(ip_ptr, destination_ip, packet_ptr -> nx_packet_address.nx_packet_interface_ptr);
12092                 return;
12093             }
12094         }
12095     }
12096     else
12097     {
12098 
12099         /* This IP instance does not require any IP-to-physical mapping.  */
12100 
12101         /* Determine if we have a loopback address.  */
12102         if ((((destination_ip >= NX_IP_LOOPBACK_FIRST) &&
12103               (destination_ip <= NX_IP_LOOPBACK_LAST))) ||
12104               (destination_ip == packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_address))
12105         {
12106 
12107             /* Yes, we have an internal loopback address.  */
12108 
12109             /* Copy the packet so it can be enqueued properly by the receive
12110                processing.  */
12111             if (_nx_packet_copy(packet_ptr, &packet_copy, ip_ptr -> nx_ip_default_packet_pool, NX_NO_WAIT) == NX_SUCCESS)
12112             {
12113 
12114 #ifndef NX_DISABLE_IP_INFO
12115 
12116                 /* Increment the IP packet sent count.  */
12117                 ip_ptr -> nx_ip_total_packets_sent++;
12118 
12119                 /* Increment the IP bytes sent count.  */
12120                 ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
12121 #endif
12122 
12123                 /* Send the packet to this IP's receive processing like it came in from the
12124                    driver.  */
12125                 _nx_ip_packet_deferred_receive(ip_ptr, packet_copy);
12126             }
12127 #ifndef NX_DISABLE_IP_INFO
12128             else
12129             {
12130 
12131                 /* Increment the IP transmit resource error count.  */
12132                 ip_ptr -> nx_ip_transmit_resource_errors++;
12133 
12134                 /* Increment the IP send packets dropped count.  */
12135                 ip_ptr -> nx_ip_send_packets_dropped++;
12136             }
12137 #endif
12138 
12139             /* Release the transmit packet.  */
12140             _nx_packet_transmit_release(packet_ptr);
12141             return;
12142         }
12143 
12144         /* Build the driver request.  */
12145         driver_request.nx_ip_driver_ptr =      ip_ptr;
12146         driver_request.nx_ip_driver_command =  NX_LINK_PACKET_SEND;
12147         driver_request.nx_ip_driver_packet =   packet_ptr;
12148         driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
12149 
12150 #ifndef NX_DISABLE_FRAGMENTATION
12151         /* Determine if fragmentation is needed.  */
12152         if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
12153         {
12154 
12155             /* Fragmentation is needed, call the fragment routine if available. */
12156             if (ip_ptr -> nx_ip_fragment_processing)
12157             {
12158 
12159                 /* Call the IP fragment processing routine.  */
12160                 (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
12161             }
12162             else
12163             {
12164 
12165 #ifndef NX_DISABLE_IP_INFO
12166 
12167                 /* Increment the IP send packets dropped count.  */
12168                 ip_ptr -> nx_ip_send_packets_dropped++;
12169 #endif
12170 
12171                 /* Just release the packet.  */
12172                 _nx_packet_transmit_release(packet_ptr);
12173             }
12174 
12175             /* In either case, this packet send is complete, just return.  */
12176             return;
12177         }
12178 #endif
12179 
12180 #ifndef NX_DISABLE_IP_INFO
12181 
12182         /* Increment the IP packet sent count.  */
12183         ip_ptr -> nx_ip_total_packets_sent++;
12184 
12185         /* Increment the IP bytes sent count.  */
12186         ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
12187 
12188 #endif
12189 
12190         /* No mapping driver.  Just send the packet out!  */
12191         (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
12192     }
12193 }
12194 #endif /*NX_DISABLE_IPV4 */
12195 
12196 #ifdef FEATURE_NX_IPV6
12197 /**************************************************************************/
12198 /*                                                                        */
12199 /*  FUNCTION                                               RELEASE        */
12200 /*                                                                        */
12201 /*    _nxd_bsd_ipv6_packet_send                           PORTABLE C      */
12202 /*                                                           6.1          */
12203 /*  AUTHOR                                                                */
12204 /*                                                                        */
12205 /*    Yuxin Zhou, Microsoft Corporation                                   */
12206 /*                                                                        */
12207 /*  DESCRIPTION                                                           */
12208 /*                                                                        */
12209 /*    This function forwards the input packet directly to the appropriate */
12210 /*    link driver.  The caller needs to fill in the correct               */
12211 /*    source and destination addresses into the packet source and         */
12212 /*    destination address.  The caller also makes sure that the packet    */
12213 /*    interface address is valid (not in tentative state), and source     */
12214 /*    address is not unspecified e.g. NULL.                               */
12215 /*                                                                        */
12216 /*  INPUT                                                                 */
12217 /*                                                                        */
12218 /*    packet_ptr                            Pointer to packet to send     */
12219 /*    src_addr                              Pointer to source address     */
12220 /*    dest_addr                             Pointer to dest address       */
12221 /*                                                                        */
12222 /*  OUTPUT                                                                */
12223 /*                                                                        */
12224 /*    None                                                                */
12225 /*                                                                        */
12226 /*  CALLS                                                                 */
12227 /*                                                                        */
12228 /*    _nx_packet_transmit_release           Release transmit packet       */
12229 /*    _nx_nd_cache_add_entry                Add new entry to ND Cache     */
12230 /*    IPv6_Address_Type                     Find IPv6 address type        */
12231 /*    _nx_packet_copy                       Packet copy                   */
12232 /*    _nx_ip_packet_deferred_receive        Places received packets in    */
12233 /*                                             deferred packet queue      */
12234 /*    _nx_icmpv6_send_ns                    Send neighbor solicitation    */
12235 /*    _nxd_ipv6_search_onlink               Find onlink match             */
12236 /*    _nx_ipv6_fragment_processing          Fragment processing           */
12237 /*    (ip_link_driver)                      User supplied link driver     */
12238 /*                                                                        */
12239 /*  CALLED BY                                                             */
12240 /*                                                                        */
12241 /*    nx_bsd_send_internal                                                */
12242 /*                                                                        */
12243 /*  RELEASE HISTORY                                                       */
12244 /*                                                                        */
12245 /*    DATE              NAME                      DESCRIPTION             */
12246 /*                                                                        */
12247 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12248 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12249 /*                                            resulting in version 6.1    */
12250 /*                                                                        */
12251 /**************************************************************************/
_nxd_bsd_ipv6_packet_send(NX_PACKET * packet_ptr,ULONG * src_addr,ULONG * dest_addr)12252 static VOID _nxd_bsd_ipv6_packet_send(NX_PACKET *packet_ptr, ULONG *src_addr, ULONG *dest_addr)
12253 {
12254 
12255 UINT            status;
12256 ULONG           address_type;
12257 NX_IP_DRIVER    driver_request;
12258 NX_PACKET      *remove_packet;
12259 NX_PACKET      *packet_copy;
12260 UINT            same_address;
12261 NX_INTERFACE   *if_ptr;
12262 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
12263 NX_IPV6_HEADER *ip_header_ptr;
12264 #endif
12265 NX_IPV6_DESTINATION_ENTRY  *dest_entry_ptr;
12266 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
12267 UINT                        next_hop_path_mtu;
12268 NX_IPV6_DESTINATION_ENTRY  *next_hop_dest_entry_ptr;
12269 #endif
12270 NX_IP          *ip_ptr;
12271 
12272     ip_ptr = nx_bsd_default_ip;
12273 #ifndef NX_DISABLE_IP_INFO
12274 
12275     /* Increment the total send requests counter.  */
12276     ip_ptr -> nx_ip_total_packet_send_requests++;
12277 #endif
12278 
12279     if_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
12280 
12281 
12282     /* If the interface IP address is not valid (in DAD state), only ICMP is allowed */
12283     if(packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_state != NX_IPV6_ADDR_STATE_VALID)
12284     {
12285 
12286 #ifndef NX_DISABLE_IP_INFO
12287 
12288         /* Increment the IP invalid packet error.  */
12289         ip_ptr -> nx_ip_invalid_transmit_packets++;
12290 #endif
12291 
12292         /* Release the packet.  */
12293         _nx_packet_transmit_release(packet_ptr);
12294 
12295         /* Return... nothing more can be done!  */
12296         return;
12297     }
12298 
12299 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
12300     /* Build the IP header.  */
12301     ip_header_ptr = (NX_IPV6_HEADER*)packet_ptr -> nx_packet_prepend_ptr;
12302 #endif
12303 
12304     /* Check if the host is sending itself a packet. */
12305     same_address = (UINT)CHECK_IPV6_ADDRESSES_SAME(dest_addr, src_addr);
12306 
12307     /* If it is, consider this a loopback address. */
12308     if (same_address == 1)
12309     {
12310 
12311         address_type = IPV6_ADDRESS_LOOPBACK;
12312     }
12313     else
12314     {
12315 
12316         /* Otherwise check if this packet sending to a known loopback address. */
12317         address_type = IPv6_Address_Type(dest_addr);
12318     }
12319 
12320     /* Handle the internal loopback case. */
12321     if(address_type == IPV6_ADDRESS_LOOPBACK)
12322     {
12323 
12324         if(_nx_packet_copy(packet_ptr, &packet_copy, ip_ptr -> nx_ip_default_packet_pool, NX_NO_WAIT) == NX_SUCCESS)
12325         {
12326 #ifndef NX_DISABLE_IP_INFO
12327 
12328             /* Increment the IP packet sent count. */
12329             ip_ptr -> nx_ip_total_packets_sent++;
12330 
12331             /* Increment the IP bytes sent count. */
12332             ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV6_HEADER);
12333 #endif
12334 
12335             /* Send the packet to this IP's receive processing like it came in from the driver. */
12336             _nx_ip_packet_deferred_receive(ip_ptr, packet_copy);
12337         }
12338 #ifndef NX_DISABLE_IP_INFO
12339         else
12340         {
12341             /* Increment the IP send packets dropped count. */
12342             ip_ptr -> nx_ip_send_packets_dropped++;
12343 
12344             /* Increment the IP transmit resource error count. */
12345             ip_ptr -> nx_ip_transmit_resource_errors++;
12346         }
12347 #endif
12348         /* Release the transmit packet. */
12349         _nx_packet_transmit_release(packet_ptr);
12350         return;
12351 
12352     }
12353 
12354     /* Is this packet a multicast ? */
12355     if((dest_addr[0] & 0xFF000000) == 0xFF000000)
12356     {
12357 
12358 
12359         /* Set up the driver request. */
12360         driver_request.nx_ip_driver_ptr                  = ip_ptr;
12361         driver_request.nx_ip_driver_command              = NX_LINK_PACKET_SEND;
12362         driver_request.nx_ip_driver_packet               = packet_ptr;
12363         driver_request.nx_ip_driver_physical_address_msw = 0x00003333;
12364         driver_request.nx_ip_driver_physical_address_lsw = dest_addr[3];
12365         driver_request.nx_ip_driver_interface            = if_ptr;
12366 
12367 #ifndef NX_DISABLE_IP_INFO
12368 
12369         /* Increment the IP packet sent count.  */
12370         ip_ptr -> nx_ip_total_packets_sent++;
12371 
12372         /* Increment the IP bytes sent count.  */
12373         ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV6_HEADER);
12374 #endif
12375 
12376         /* Check if fragmentation is enabled. */
12377 #ifndef NX_DISABLE_FRAGMENTATION
12378 
12379         /* It is; is path MTU enabled? */
12380 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
12381 
12382         /* It is. We will check the path MTU for the packet destination to
12383            determine if we need to fragment the packet. */
12384 
12385         /* Get a pointer to the packet IP header. */
12386         ip_header_ptr = (NX_IPV6_HEADER *)packet_ptr -> nx_packet_prepend_ptr;
12387 
12388         /* Lookup the multicast destination in the destination table.  */
12389         status = _nx_icmpv6_dest_table_find(ip_ptr, ip_header_ptr -> nx_ip_header_destination_ip, &dest_entry_ptr, 0, 0);
12390 
12391         /* Did we find it in the table? */
12392         if ((status == NX_SUCCESS) && (dest_entry_ptr != NX_NULL))
12393         {
12394 
12395             /* Yes; Check the destination path MTU if fragmentation is needed.  */
12396             if ((dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu > 0) && (packet_ptr -> nx_packet_length >
12397                                                      dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu))
12398             {
12399 
12400                 /* Yes we must fragment the payload. */
12401                 _nx_ipv6_fragment_process(&driver_request, dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu);
12402 
12403                 /* This packet send is complete, just return.  */
12404                 return;
12405             }
12406 
12407             /* Packet should drop through and be checked against the IP mtu. */
12408         }
12409 
12410 #endif  /* NX_ENABLE_IPV6_PATH_MTU_DISCOVERY */
12411 
12412 
12413         /* Does the packet payload exceed our IP instance MTU?  */
12414         if (packet_ptr -> nx_packet_length > if_ptr -> nx_interface_ip_mtu_size)
12415         {
12416             /* Yes; ok to fragment the packet payload. */
12417             _nx_ipv6_fragment_process(&driver_request, if_ptr -> nx_interface_ip_mtu_size);
12418 
12419             /* This packet send is complete, just return.  */
12420             return;
12421         }
12422 
12423         /* Packet will go out unfragmented. */
12424 
12425 #endif  /* NX_DISABLE_FRAGMENTATION */
12426 
12427 
12428         /* Send the IP packet out on the network via the attached driver.  */
12429         (if_ptr -> nx_interface_link_driver_entry) (&driver_request);
12430 
12431         /* Return to caller.  */
12432         return;
12433     }
12434 
12435     /* Determine if physical mapping is needed by this link driver. */
12436     if( if_ptr && if_ptr -> nx_interface_address_mapping_needed )
12437     {
12438 
12439         /* Obtain MAC address */
12440         ND_CACHE_ENTRY *NDCacheEntry = NX_NULL;
12441         ULONG next_hop_address[4];
12442 
12443         SET_UNSPECIFIED_ADDRESS(next_hop_address);
12444 
12445         /* Lookup the packet destination in the destination table. */
12446         status = _nx_icmpv6_dest_table_find(ip_ptr, dest_addr, &dest_entry_ptr, 0, 0);
12447 
12448         /* Was a matching entry found? */
12449         if(status != NX_SUCCESS)
12450         {
12451 
12452             /* No; If the packet is either onlink or there is no default router,
12453                just copy the packet destination address to the 'next hop' address.  */
12454 
12455             if(_nxd_ipv6_search_onlink(ip_ptr, dest_addr))
12456             {
12457                 COPY_IPV6_ADDRESS(dest_addr, next_hop_address);
12458 
12459                 /* Add the next_hop in destination table. */
12460                 status = _nx_icmpv6_dest_table_add(ip_ptr, dest_addr, &dest_entry_ptr,
12461                                                    next_hop_address, if_ptr -> nx_interface_ip_mtu_size,
12462                                                    NX_WAIT_FOREVER, packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr);
12463 
12464                 /* Get the NDCacheEntry. */
12465                 if(status == NX_SUCCESS)
12466                     NDCacheEntry = dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry;
12467             }
12468 
12469             /* Check whether or not we have a default router. */
12470             else if(_nxd_ipv6_router_lookup(ip_ptr, if_ptr, next_hop_address, (VOID**)&NDCacheEntry) == NX_SUCCESS)
12471             {
12472                /* Add the next_hop in destination table. */
12473                 status = _nx_icmpv6_dest_table_add(ip_ptr, dest_addr, &dest_entry_ptr,
12474                                                    next_hop_address, if_ptr -> nx_interface_ip_mtu_size,
12475                                                    NX_WAIT_FOREVER, packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr);
12476 
12477                 /* If the default router did not has a reachable ND_CACHE_ENTRY. Get the NDCacheEntry. */
12478                 if(!NDCacheEntry)
12479                     NDCacheEntry = dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry;
12480             }
12481 
12482             /* Can not find next_hop or the destination table add failed. */
12483             if(status || ((next_hop_address[0] == 0) && (next_hop_address[1] == 0) && (next_hop_address[2] == 0) && (next_hop_address[3] == 0)))
12484             {
12485 
12486                 /* Release the packet. */
12487                 _nx_packet_release(packet_ptr);
12488 
12489                 /* Can't send it. */
12490                 return;
12491             }
12492 
12493         }
12494 
12495         /* Find a valid destination cache, set the nd cache and next hop address. */
12496         else
12497         {
12498 
12499             /* Check the NDCacheEntry is valid. */
12500             if(dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry -> nx_nd_cache_nd_status == ND_CACHE_STATE_INVALID)
12501             {
12502                 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))
12503                 {
12504                     /* Release the packet. */
12505                     _nx_packet_release(packet_ptr);
12506 
12507                     /* Can't send it. */
12508                     return;
12509                 }
12510 
12511             }
12512 
12513             /* Get the destination and next hop address. */
12514             NDCacheEntry = dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry;
12515             COPY_IPV6_ADDRESS(dest_entry_ptr -> nx_ipv6_destination_entry_next_hop, next_hop_address);
12516         }
12517 
12518         /* According RFC2461 ch 7.3.3, as long as the entry is valid and not in INCOMPLETE state,
12519            the IP layer should use the cached link layer address.  */
12520         if((NDCacheEntry -> nx_nd_cache_nd_status >= ND_CACHE_STATE_REACHABLE) &&
12521            (NDCacheEntry -> nx_nd_cache_nd_status <= ND_CACHE_STATE_PROBE))
12522         {
12523 
12524             UCHAR *mac_addr;
12525 
12526             mac_addr = NDCacheEntry -> nx_nd_cache_mac_addr;
12527 
12528             /* Assume we find the mac */
12529             driver_request.nx_ip_driver_ptr                  = ip_ptr;
12530             driver_request.nx_ip_driver_command              = NX_LINK_PACKET_SEND;
12531             driver_request.nx_ip_driver_packet               = packet_ptr;
12532             driver_request.nx_ip_driver_physical_address_msw = (ULONG)((mac_addr[0] << 8) | mac_addr[1]);
12533             driver_request.nx_ip_driver_physical_address_lsw =
12534                 (ULONG)((mac_addr[2] << 24) | (mac_addr[3] << 16) | (mac_addr[4] << 8) | mac_addr[5]);
12535             driver_request.nx_ip_driver_interface            = if_ptr;
12536 
12537 #ifndef NX_DISABLE_FRAGMENTATION
12538 
12539             /* If the packet size is bigger than MTU, NetX Duo is enabled to fragment
12540                the packet payload. */
12541 
12542             /* Check if path MTU Discovery is enabled first. */
12543 
12544 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
12545 
12546             /* It is.  To know if we need to fragment this packet we need the path MTU for the packet
12547                destination.  */
12548 
12549             /* If this destination has a non null next hop, we need to ascertain the next hop MTU.  */
12550 
12551             /* Get the path MTU for the actual destination. */
12552             next_hop_path_mtu = dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu;
12553 
12554 
12555             /* Find the next hop in the destination table. */
12556             status = _nx_icmpv6_dest_table_find(ip_ptr, next_hop_address, &next_hop_dest_entry_ptr, 0, 0);
12557 
12558             if (status == NX_SUCCESS)
12559             {
12560 
12561                 /* Now compare the destination path MTU with the next hop path MTU*/
12562                 if ((next_hop_dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu > 0) &&
12563                     (next_hop_path_mtu > next_hop_dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu))
12564                 {
12565 
12566                     /* Update the path mtu to reflect the next hop route. */
12567                     next_hop_path_mtu = next_hop_dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu;
12568                 }
12569             }
12570 
12571             /* Yes; Check the destination path MTU if fragmentation is needed.  */
12572             if ((next_hop_path_mtu > 0) &&
12573                 (packet_ptr -> nx_packet_length > next_hop_path_mtu))
12574             {
12575 
12576                 /* Yes we must fragment the payload. */
12577                 _nx_ipv6_fragment_process(&driver_request, next_hop_path_mtu);
12578 
12579                 /* This packet send is complete, just return.  */
12580                 return;
12581             }
12582 #endif  /* NX_ENABLE_IPV6_PATH_MTU_DISCOVERY */
12583 
12584             /* Send packet unfragmented. */
12585 
12586             /* If we didn't find anything in the destination table, let the packet drop through.  NetX Duo
12587                will check our IP instance MTU if fragmentation is needed before sending. */
12588 
12589 
12590             /* Does the packet payload exceed our IP instance MTU?  */
12591             if (packet_ptr -> nx_packet_length > if_ptr -> nx_interface_ip_mtu_size)
12592             {
12593                 /* Yes; ok to fragment the packet payload. */
12594                 _nx_ipv6_fragment_process(&driver_request, if_ptr -> nx_interface_ip_mtu_size);
12595 
12596                 /* This packet send is complete, just return.  */
12597                 return;
12598             }
12599 
12600             /* The packet requires no fragmentation. Proceed with sending the packet. */
12601 
12602 #endif /* NX_DISABLE_FRAGMENTATION */
12603 
12604 
12605 #ifndef NX_DISABLE_IP_INFO
12606 
12607             /* Increment the IP packet sent count.  */
12608             ip_ptr -> nx_ip_total_packets_sent++;
12609 
12610             /* Increment the IP bytes sent count.  */
12611             ip_ptr -> nx_ip_total_bytes_sent +=  packet_ptr -> nx_packet_length - sizeof(NX_IPV6_HEADER);
12612 #endif
12613 
12614             /* Send the IP packet out on the network via the attached driver.  */
12615             (if_ptr -> nx_interface_link_driver_entry) (&driver_request);
12616 
12617             /* If the entry is in STALE state, move it to DELAY state. */
12618             if(NDCacheEntry -> nx_nd_cache_nd_status == ND_CACHE_STATE_STALE)
12619             {
12620                 NDCacheEntry -> nx_nd_cache_nd_status = ND_CACHE_STATE_DELAY;
12621 
12622                 /* Start the Delay first probe timer */
12623                 NDCacheEntry -> nx_nd_cache_timer_tick = NX_DELAY_FIRST_PROBE_TIME;
12624 
12625             }
12626 
12627             /* Return to caller.  */
12628             return;
12629         }
12630 
12631         /* No MAC address was found in our cache table.  Start the Neighbor Discovery (ND)
12632            process to get it. */
12633 
12634         /* Ensure the current packet's queue next pointer to NULL */
12635         packet_ptr -> nx_packet_queue_next = NX_NULL;
12636 
12637         /* Determine if the queue is empty. */
12638         if(NDCacheEntry -> nx_nd_cache_packet_waiting_head == NX_NULL)
12639         {
12640             /* ICMPv6 is enabled */
12641             if(ip_ptr -> nx_ip_icmpv6_packet_process)
12642             {
12643 
12644                 /* Queue up this packet */
12645                 NDCacheEntry -> nx_nd_cache_packet_waiting_head = packet_ptr;
12646                 NDCacheEntry -> nx_nd_cache_packet_waiting_tail = packet_ptr;
12647                 NDCacheEntry -> nx_nd_cache_packet_waiting_queue_length = 1;
12648 
12649                 /* Set the outgoing address and interface to the cache entry.  */
12650                 NDCacheEntry -> nx_nd_cache_outgoing_address = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr;
12651                 NDCacheEntry -> nx_nd_cache_interface_ptr = if_ptr;
12652 
12653                 /* Is this a new entry? */
12654                 if(NDCacheEntry -> nx_nd_cache_nd_status == ND_CACHE_STATE_CREATED)
12655                 {
12656 
12657                     /* Start Neighbor discovery process by advancing to the incomplete state. */
12658                     NDCacheEntry -> nx_nd_cache_nd_status = ND_CACHE_STATE_INCOMPLETE;
12659                 }
12660 
12661                 _nx_icmpv6_send_ns(ip_ptr, next_hop_address,
12662                                    1, packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr, 0, NX_NULL);
12663 
12664                 NDCacheEntry -> nx_nd_cache_num_solicit = NX_MAX_MULTICAST_SOLICIT - 1;
12665                 NDCacheEntry -> nx_nd_cache_timer_tick = ip_ptr -> nx_ipv6_retrans_timer_ticks;
12666 
12667             }
12668             else
12669             {
12670 
12671                 _nx_packet_transmit_release(packet_ptr);
12672 #ifndef NX_DISABLE_IP_INFO
12673 
12674                 /* Increment the IP transmit resource error count.  */
12675                 ip_ptr -> nx_ip_transmit_resource_errors++;
12676 
12677                 /* Increment the IP send packets dropped count.  */
12678                 ip_ptr -> nx_ip_send_packets_dropped++;
12679 #endif
12680             }
12681             return;
12682         }
12683 
12684         /* The ND process already started.  Simply queue up this packet */
12685         NDCacheEntry -> nx_nd_cache_packet_waiting_tail -> nx_packet_queue_next = packet_ptr;
12686         NDCacheEntry -> nx_nd_cache_packet_waiting_tail = packet_ptr;
12687         NDCacheEntry -> nx_nd_cache_packet_waiting_queue_length++;
12688 
12689         /* Check if the number of packets enqueued exceeds the allowed number. */
12690         if(NDCacheEntry -> nx_nd_cache_packet_waiting_queue_length > NX_ND_MAX_QUEUE_DEPTH)
12691         {
12692 
12693             /* Yes, so delete the first packet. */
12694             remove_packet = NDCacheEntry -> nx_nd_cache_packet_waiting_head;
12695 
12696             NDCacheEntry -> nx_nd_cache_packet_waiting_head = remove_packet -> nx_packet_queue_next;
12697 
12698             /* Update the queued packet count for this cache entry. */
12699             NDCacheEntry -> nx_nd_cache_packet_waiting_queue_length--;
12700 
12701             _nx_packet_transmit_release(remove_packet);
12702 #ifndef NX_DISABLE_IP_INFO
12703             /* Increment the IP transmit resource error count.  */
12704             ip_ptr -> nx_ip_transmit_resource_errors++;
12705 
12706             /* Increment the IP send packets dropped count.  */
12707             ip_ptr -> nx_ip_send_packets_dropped++;
12708 #endif
12709         }
12710 
12711         return;
12712     }
12713 
12714     /* For now do nothing. Just release the packet */
12715     _nx_packet_release(packet_ptr);
12716 }
12717 
12718 #endif /* FEATURE_NX_IPV6 */
12719 
12720 #if defined(FEATURE_NX_IPV6) && defined(NX_ENABLE_IP_RAW_PACKET_FILTER)
12721 /**************************************************************************/
12722 /*                                                                        */
12723 /*  FUNCTION                                               RELEASE        */
12724 /*                                                                        */
12725 /*    _nxd_bsd_swap_ipv6_extension_headers                PORTABLE C      */
12726 /*                                                           6.1          */
12727 /*  AUTHOR                                                                */
12728 /*                                                                        */
12729 /*    Yuxin Zhou, Microsoft Corporation                                   */
12730 /*                                                                        */
12731 /*  DESCRIPTION                                                           */
12732 /*                                                                        */
12733 /*    This function performs endian swap operations on the IPv6           */
12734 /*    extension headers.                                                  */
12735 /*                                                                        */
12736 /*  INPUT                                                                 */
12737 /*                                                                        */
12738 /*    packet_ptr                            Pointer to packet             */
12739 /*    header_type                           Type of the first extension   */
12740 /*                                            header                      */
12741 /*                                                                        */
12742 /*  OUTPUT                                                                */
12743 /*                                                                        */
12744 /*    None                                                                */
12745 /*                                                                        */
12746 /*  CALLS                                                                 */
12747 /*                                                                        */
12748 /*    NX_CHANGE_USHORT_ENDIAN               Swap endian-ness on 16-bit    */
12749 /*                                            integer.                    */
12750 /*                                                                        */
12751 /*  CALLED BY                                                             */
12752 /*                                                                        */
12753 /*    NetX Duo BSD Layer Source Code                                      */
12754 /*                                                                        */
12755 /*  RELEASE HISTORY                                                       */
12756 /*                                                                        */
12757 /*    DATE              NAME                      DESCRIPTION             */
12758 /*                                                                        */
12759 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12760 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12761 /*                                            resulting in version 6.1    */
12762 /*                                                                        */
12763 /**************************************************************************/
_nxd_bsd_swap_ipv6_extension_headers(NX_PACKET * packet_ptr,UCHAR header_type)12764 static VOID  _nxd_bsd_swap_ipv6_extension_headers(NX_PACKET *packet_ptr, UCHAR header_type)
12765 {
12766 UCHAR                           *scan_ptr;
12767 ULONG                           remaining_bytes;
12768 ULONG                           header_length = 40;
12769 NX_IPV6_HEADER_OPTION           *option;
12770 
12771 
12772     remaining_bytes = (ULONG)packet_ptr -> nx_packet_prepend_ptr - (ULONG)packet_ptr -> nx_packet_ip_header;
12773 
12774     scan_ptr = packet_ptr -> nx_packet_ip_header;
12775 
12776     remaining_bytes -= header_length;
12777     scan_ptr += header_length;
12778 
12779     while(remaining_bytes)
12780     {
12781         option = (NX_IPV6_HEADER_OPTION*)scan_ptr;
12782         switch(header_type)
12783         {
12784         case NX_PROTOCOL_NEXT_HEADER_HOP_BY_HOP:
12785 
12786             break;
12787 
12788         case NX_PROTOCOL_NEXT_HEADER_DESTINATION:
12789 
12790             break;
12791 
12792         case NX_PROTOCOL_NEXT_HEADER_ROUTING:
12793             break;
12794 
12795 
12796         case NX_PROTOCOL_NEXT_HEADER_FRAGMENT:
12797             NX_CHANGE_USHORT_ENDIAN(((NX_IPV6_HEADER_FRAGMENT_OPTION *)scan_ptr) -> nx_ipv6_header_fragment_option_offset_flag);
12798             break;
12799 
12800         default:
12801 
12802             break;
12803         }
12804 
12805         header_type = option -> nx_ipv6_header_option_next_header;
12806 
12807         if(header_type == NX_PROTOCOL_NEXT_HEADER_AUTHENTICATION)
12808             header_length = (ULONG)((option -> nx_ipv6_header_option_ext_length << 2) + 2);
12809         else
12810             header_length = (ULONG)((option -> nx_ipv6_header_option_ext_length + 1) << 3);
12811 
12812 
12813         remaining_bytes -= header_length;
12814         scan_ptr += header_length;
12815     }
12816 }
12817 #endif  /* defined(FEATURE_NX_IPV6) && defined(NX_ENABLE_IP_RAW_PACKET_FILTER) */
12818 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
12819 
12820 
12821 /**************************************************************************/
12822 /*                                                                        */
12823 /*  FUNCTION                                               RELEASE        */
12824 /*                                                                        */
12825 /*    nx_bsd_pppoe_internal_sendto                        PORTABLE C      */
12826 /*                                                           6.3.0        */
12827 /*  AUTHOR                                                                */
12828 /*                                                                        */
12829 /*    Yuxin Zhou, Microsoft Corporation                                   */
12830 /*                                                                        */
12831 /*  DESCRIPTION                                                           */
12832 /*                                                                        */
12833 /*    This function sends raw PPPOE packet to driver directly.            */
12834 /*                                                                        */
12835 /*  INPUT                                                                 */
12836 /*                                                                        */
12837 /*    bsd_socket_ptr                        Pointer to bsd socket         */
12838 /*    msg                                   Message to send               */
12839 /*    msgLength                             Length of message             */
12840 /*    flags                                 Flags                         */
12841 /*    destAddr                              Pointer to destination address*/
12842 /*    destAddrLen                           Length of destination address */
12843 /*                                                                        */
12844 /*  OUTPUT                                                                */
12845 /*                                                                        */
12846 /*    msgLength                             On success                    */
12847 /*    NX_SOC_ERROR (-1)                     On failure                    */
12848 /*                                                                        */
12849 /*  CALLS                                                                 */
12850 /*                                                                        */
12851 /*    nx_packet_allocate                    Allocate a packet             */
12852 /*    nx_packet_data_append                 Append data to the packet     */
12853 /*    nx_packet_release                     Release the packet on error   */
12854 /*    tx_mutex_get                          Obtain exclusive access to    */
12855 /*    tx_mutex_put                          Release exclusive access      */
12856 /*                                                                        */
12857 /*  CALLED BY                                                             */
12858 /*                                                                        */
12859 /*    Application Code                                                    */
12860 /*                                                                        */
12861 /*  RELEASE HISTORY                                                       */
12862 /*                                                                        */
12863 /*    DATE              NAME                      DESCRIPTION             */
12864 /*                                                                        */
12865 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
12866 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
12867 /*                                            resulting in version 6.1    */
12868 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
12869 /*                                            used new API/structs naming,*/
12870 /*                                            resulting in version 6.3.0  */
12871 /*                                                                        */
12872 /**************************************************************************/
nx_bsd_pppoe_internal_sendto(NX_BSD_SOCKET * bsd_socket_ptr,CHAR * msg,INT msgLength,INT flags,struct nx_bsd_sockaddr * destAddr,INT destAddrLen)12873 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)
12874 {
12875 UINT                if_index;
12876 struct nx_bsd_sockaddr_ll
12877                     *destAddr_ll;
12878 #if 0
12879 ULONG               src_mac_msw;
12880 ULONG               src_mac_lsw;
12881 #endif
12882 NX_IP_DRIVER        driver_request;
12883 UINT                status;
12884 NX_PACKET          *packet_ptr = NX_NULL;
12885 
12886     NX_PARAMETER_NOT_USED(bsd_socket_ptr);
12887     NX_PARAMETER_NOT_USED(flags);
12888 
12889     /* Validate the parameters. */
12890     if(destAddr == NX_NULL)
12891     {
12892         /* Set the socket error if extended socket options enabled. */
12893         nx_bsd_set_errno(EINVAL);
12894 
12895         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12896         return(NX_SOC_ERROR);
12897     }
12898 
12899     if(destAddr -> sa_family != AF_PACKET)
12900     {
12901         /* Set the socket error if extended socket options enabled. */
12902         nx_bsd_set_errno(EINVAL);
12903 
12904         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12905         return(NX_SOC_ERROR);
12906     }
12907 
12908     if(destAddrLen != sizeof(struct nx_bsd_sockaddr_ll))
12909     {
12910         /* Set the socket error if extended socket options enabled. */
12911         nx_bsd_set_errno(EINVAL);
12912 
12913         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12914         return(NX_SOC_ERROR);
12915     }
12916 
12917     destAddr_ll = (struct nx_bsd_sockaddr_ll*)destAddr;
12918 
12919     if((destAddr_ll -> sll_protocol != ETHERTYPE_PPPOE_SESS) && (destAddr_ll -> sll_protocol != ETHERTYPE_PPPOE_DISC))
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     /* Validate the interface ID */
12929     if_index = (UINT)(destAddr_ll -> sll_ifindex);
12930     if(if_index >= NX_MAX_IP_INTERFACES)
12931     {
12932         /* Set the socket error if extended socket options enabled. */
12933         nx_bsd_set_errno(EINVAL);
12934 
12935         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12936         return(NX_SOC_ERROR);
12937     }
12938 
12939     if(nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_valid == 0)
12940     {
12941         /* Set the socket error if extended socket options enabled. */
12942         nx_bsd_set_errno(EINVAL);
12943 
12944         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12945         return(NX_SOC_ERROR);
12946     }
12947 
12948 #if 0
12949     /* Pickup the source MAC address */
12950     src_mac_msw = nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_physical_address_msw;
12951     src_mac_lsw = nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_physical_address_lsw;
12952 #endif
12953 
12954 
12955 
12956     /* Validate the packet length */
12957     if(msgLength > (INT)(nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_ip_mtu_size + 14))
12958     {
12959         /* Set the socket error if extended socket options enabled. */
12960         nx_bsd_set_errno(EINVAL);
12961 
12962         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12963         return(NX_SOC_ERROR);
12964     }
12965 
12966     /* FIXME:  If the socket is non-blocking, Timeout value should be set to 0 */
12967     status = nx_packet_allocate(nx_bsd_default_packet_pool, &packet_ptr, NX_PHYSICAL_HEADER, NX_NO_WAIT);
12968 
12969     /* Check for errors.   */
12970     if (status != NX_SUCCESS)
12971     {
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 
12982 
12983     /* Now copy the data into the NetX packet.  */
12984     status =  nx_packet_data_append(packet_ptr, (VOID *) msg, (ULONG)msgLength, nx_bsd_default_packet_pool, NX_NO_WAIT);
12985 
12986     /* Was the data copy successful?  */
12987     if (status != NX_SUCCESS)
12988     {
12989 
12990         nx_packet_release(packet_ptr);
12991 
12992         /* Set the socket error.  */
12993         nx_bsd_set_errno(ENOBUFS);
12994 
12995         /* Return an error status.*/
12996         NX_BSD_ERROR(status, __LINE__);
12997         return(NX_SOC_ERROR);
12998     }
12999 
13000     /* Now ready to transmit this packet. */
13001     driver_request.nx_ip_driver_ptr =                   nx_bsd_default_ip;
13002     if(destAddr_ll -> sll_protocol == ETHERTYPE_PPPOE_SESS)
13003         driver_request.nx_ip_driver_command =           NX_LINK_PACKET_PPPOE_SESS_SEND;
13004     else
13005         driver_request.nx_ip_driver_command =           NX_LINK_PACKET_PPPOE_DISC_SEND;
13006     driver_request.nx_ip_driver_packet =                packet_ptr;
13007     driver_request.nx_ip_driver_interface =             &nx_bsd_default_ip -> nx_ip_interface[if_index];
13008 
13009     /* Obtain the BSD lock. */
13010     status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
13011 
13012     /* Check the status.  */
13013     if (status != NX_SUCCESS)
13014     {
13015 
13016         nx_packet_release(packet_ptr);
13017 
13018         /* Set the socket error if extended socket options enabled. */
13019         nx_bsd_set_errno(EACCES);
13020 
13021         /* Return an error. */
13022         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
13023         return(NX_SOC_ERROR);
13024     }
13025 
13026     (driver_request.nx_ip_driver_interface -> nx_interface_link_driver_entry)(&driver_request);
13027 
13028     /* Release the mutex. */
13029     tx_mutex_put(nx_bsd_protection_ptr);
13030 
13031     return(msgLength);
13032 }
13033 
13034 
13035 /**************************************************************************/
13036 /*                                                                        */
13037 /*  FUNCTION                                               RELEASE        */
13038 /*                                                                        */
13039 /*    _nx_bsd_pppoe_packet_received                       PORTABLE C      */
13040 /*                                                           6.1          */
13041 /*  AUTHOR                                                                */
13042 /*                                                                        */
13043 /*    Yuxin Zhou, Microsoft Corporation                                   */
13044 /*                                                                        */
13045 /*  DESCRIPTION                                                           */
13046 /*                                                                        */
13047 /*    This function receives raw PPPOE packet from driver directly.       */
13048 /*                                                                        */
13049 /*  INPUT                                                                 */
13050 /*                                                                        */
13051 /*    packet_ptr                            Pointer to received packet    */
13052 /*    frame_type                            Type of frame                 */
13053 /*    interface_id                          Interface ID                  */
13054 /*                                                                        */
13055 /*  OUTPUT                                                                */
13056 /*                                                                        */
13057 /*    NX_SUCCESS                                                          */
13058 /*                                                                        */
13059 /*  CALLS                                                                 */
13060 /*                                                                        */
13061 /*    nx_bsd_select_wakeup                  Wake up any asychronous       */
13062 /*                                            receive call                */
13063 /*    nx_packet_release                     Release the packet on error   */
13064 /*                                                                        */
13065 /*  CALLED BY                                                             */
13066 /*                                                                        */
13067 /*    Application Code                                                    */
13068 /*                                                                        */
13069 /*  RELEASE HISTORY                                                       */
13070 /*                                                                        */
13071 /*    DATE              NAME                      DESCRIPTION             */
13072 /*                                                                        */
13073 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13074 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13075 /*                                            resulting in version 6.1    */
13076 /*                                                                        */
13077 /**************************************************************************/
_nx_bsd_pppoe_packet_received(NX_PACKET * packet_ptr,UINT frame_type,UINT interface_id)13078 UINT _nx_bsd_pppoe_packet_received(NX_PACKET *packet_ptr, UINT frame_type, UINT interface_id)
13079 {
13080 
13081 UINT i;
13082 UINT sockid = NX_BSD_MAX_SOCKETS;
13083 UINT create_id = 0xFFFFFFFF;
13084 NX_BSD_SOCKET *bsd_ptr;
13085 
13086     NX_PARAMETER_NOT_USED(interface_id);
13087 
13088     /* Find the socket with the lowest create-ID.  Put the packet into the socket's recevie queue. */
13089     for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
13090     {
13091         if((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE) &&
13092           /*
13093           (nx_bsd_socket_array[i].nx_bsd_raw_socket_enabled == NX_TRUE) &&
13094           */
13095                 (nx_bsd_socket_array[i].nx_bsd_socket_family == AF_PACKET) &&
13096                 (nx_bsd_socket_array[i].nx_bsd_socket_protocol == frame_type))
13097         {
13098             if(nx_bsd_socket_array[i].nx_bsd_socket_create_id < create_id)
13099             {
13100                 sockid = i;
13101                 create_id = nx_bsd_socket_array[i].nx_bsd_socket_create_id;
13102             }
13103         }
13104     }
13105     if(sockid == NX_BSD_MAX_SOCKETS)
13106     {
13107         /* No BSD sockets are avaialble for this frame type. */
13108         nx_packet_release(packet_ptr);
13109         return(NX_SUCCESS);
13110     }
13111     /* Now we need to put the packet into the socket. */
13112     bsd_ptr = &nx_bsd_socket_array[sockid];
13113 
13114     /* Drop the packet if the receive queue exceeds max depth. */
13115     if(bsd_ptr -> nx_bsd_socket_received_packet_count >=
13116             bsd_ptr -> nx_bsd_socket_received_packet_count_max)
13117     {
13118         nx_packet_release(packet_ptr);
13119         return(NX_SUCCESS);
13120     }
13121 
13122     if(bsd_ptr -> nx_bsd_socket_received_packet)
13123     {
13124         bsd_ptr -> nx_bsd_socket_received_packet_tail -> nx_packet_queue_next = packet_ptr;
13125     }
13126     else
13127     {
13128         bsd_ptr -> nx_bsd_socket_received_packet = packet_ptr;
13129         bsd_ptr -> nx_bsd_socket_received_packet_offset = 0;
13130     }
13131 
13132     bsd_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
13133     bsd_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
13134     bsd_ptr -> nx_bsd_socket_received_packet_count ++;
13135 
13136     nx_bsd_select_wakeup(sockid, FDSET_READ);
13137 
13138     return 0;
13139 }
13140 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
13141 
13142 #ifdef NX_BSD_RAW_SUPPORT
13143 
13144 /**************************************************************************/
13145 /*                                                                        */
13146 /*  FUNCTION                                               RELEASE        */
13147 /*                                                                        */
13148 /*    _nx_bsd_hardware_internal_sendto                    PORTABLE C      */
13149 /*                                                           6.4.0        */
13150 /*  AUTHOR                                                                */
13151 /*                                                                        */
13152 /*    Yuxin Zhou, Microsoft Corporation                                   */
13153 /*                                                                        */
13154 /*  DESCRIPTION                                                           */
13155 /*                                                                        */
13156 /*    This function sends raw packet to driver directly.                  */
13157 /*                                                                        */
13158 /*  INPUT                                                                 */
13159 /*                                                                        */
13160 /*    bsd_socket_ptr                        Pointer to bsd socket         */
13161 /*    msg                                   Message to send               */
13162 /*    msgLength                             Length of message             */
13163 /*    flags                                 Flags                         */
13164 /*    destAddr                              Pointer to destination address*/
13165 /*    destAddrLen                           Length of destination address */
13166 /*                                                                        */
13167 /*  OUTPUT                                                                */
13168 /*                                                                        */
13169 /*    msgLength                             On success                    */
13170 /*    NX_SOC_ERROR (-1)                     On failure                    */
13171 /*                                                                        */
13172 /*  CALLS                                                                 */
13173 /*                                                                        */
13174 /*    nx_packet_allocate                    Allocate a packet             */
13175 /*    nx_packet_data_append                 Append data to the packet     */
13176 /*    nx_packet_release                     Release the packet on error   */
13177 /*    tx_mutex_get                          Obtain exclusive access to    */
13178 /*    tx_mutex_put                          Release exclusive access      */
13179 /*                                                                        */
13180 /*  CALLED BY                                                             */
13181 /*                                                                        */
13182 /*    Application Code                                                    */
13183 /*                                                                        */
13184 /*  RELEASE HISTORY                                                       */
13185 /*                                                                        */
13186 /*    DATE              NAME                      DESCRIPTION             */
13187 /*                                                                        */
13188 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13189 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13190 /*                                            resulting in version 6.1    */
13191 /*  12-31-2023     Yanwu Cai                Modified comment(s),          */
13192 /*                                            added nx_link layer,        */
13193 /*                                            resulting in version 6.4.0  */
13194 /*                                                                        */
13195 /**************************************************************************/
_nx_bsd_hardware_internal_sendto(NX_BSD_SOCKET * bsd_socket_ptr,CHAR * msg,INT msgLength,INT flags,struct nx_bsd_sockaddr * destAddr,INT destAddrLen)13196 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)
13197 {
13198 UINT                if_index;
13199 struct nx_bsd_sockaddr_ll
13200                    *destAddr_ll;
13201 UINT                status;
13202 NX_PACKET          *packet_ptr = NX_NULL;
13203 
13204     NX_PARAMETER_NOT_USED(bsd_socket_ptr);
13205     NX_PARAMETER_NOT_USED(flags);
13206 
13207     /* Validate the parameters. */
13208     if(destAddr == NX_NULL)
13209     {
13210         /* Set the socket error if extended socket options enabled. */
13211         nx_bsd_set_errno(EINVAL);
13212 
13213         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
13214         return(NX_SOC_ERROR);
13215     }
13216 
13217     if(destAddr -> sa_family != AF_PACKET)
13218     {
13219         /* Set the socket error if extended socket options enabled. */
13220         nx_bsd_set_errno(EINVAL);
13221 
13222         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
13223         return(NX_SOC_ERROR);
13224     }
13225 
13226     if(destAddrLen != sizeof(struct nx_bsd_sockaddr_ll))
13227     {
13228         /* Set the socket error if extended socket options enabled. */
13229         nx_bsd_set_errno(EINVAL);
13230 
13231         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
13232         return(NX_SOC_ERROR);
13233     }
13234 
13235     destAddr_ll = (struct nx_bsd_sockaddr_ll*)destAddr;
13236 
13237     /* Validate the interface ID */
13238     if_index = (UINT)(destAddr_ll -> sll_ifindex);
13239     if(if_index >= NX_MAX_IP_INTERFACES)
13240     {
13241         /* Set the socket error if extended socket options enabled. */
13242         nx_bsd_set_errno(EINVAL);
13243 
13244         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
13245         return(NX_SOC_ERROR);
13246     }
13247 
13248     if(nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_valid == 0)
13249     {
13250         /* Set the socket error if extended socket options enabled. */
13251         nx_bsd_set_errno(EINVAL);
13252 
13253         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
13254         return(NX_SOC_ERROR);
13255     }
13256 
13257     /* Validate the packet length */
13258     if(msgLength > (INT)(nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_ip_mtu_size + 18))
13259     {
13260         /* Set the socket error if extended socket options enabled. */
13261         nx_bsd_set_errno(EINVAL);
13262 
13263         NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
13264         return(NX_SOC_ERROR);
13265     }
13266 
13267     status = nx_packet_allocate(nx_bsd_default_packet_pool, &packet_ptr, NX_PHYSICAL_HEADER, NX_NO_WAIT);
13268 
13269     /* Check for errors.   */
13270     if (status != NX_SUCCESS)
13271     {
13272 
13273         /* Set the socket error.  */
13274         nx_bsd_set_errno(ENOBUFS);
13275 
13276         /* Return an error status.*/
13277         NX_BSD_ERROR(status, __LINE__);
13278         return(NX_SOC_ERROR);
13279     }
13280 
13281     /* Set IP interface. */
13282     packet_ptr -> nx_packet_ip_interface = &nx_bsd_default_ip -> nx_ip_interface[if_index];
13283 
13284     /* Now copy the data into the NetX packet.  */
13285     status =  nx_packet_data_append(packet_ptr, (VOID *) msg, (ULONG)msgLength, nx_bsd_default_packet_pool, NX_NO_WAIT);
13286 
13287     /* Was the data copy successful?  */
13288     if (status != NX_SUCCESS)
13289     {
13290 
13291         nx_packet_release(packet_ptr);
13292 
13293         /* Set the socket error.  */
13294         nx_bsd_set_errno(ENOBUFS);
13295 
13296         /* Return an error status.*/
13297         NX_BSD_ERROR(status, __LINE__);
13298         return(NX_SOC_ERROR);
13299     }
13300 
13301 #if defined(__PRODUCT_NETXDUO__) && defined(NX_ENABLE_INTERFACE_CAPABILITY)
13302     packet_ptr -> nx_packet_interface_capability_flag = nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_capability_flag;
13303 #endif /* defined(__PRODUCT_NETXDUO__) && defined(NX_ENABLE_INTERFACE_CAPABILITY) */
13304 
13305     /* Obtain the BSD lock. */
13306     status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
13307 
13308     /* Check the status.  */
13309     if (status != NX_SUCCESS)
13310     {
13311 
13312         nx_packet_release(packet_ptr);
13313 
13314         /* Set the socket error if extended socket options enabled. */
13315         nx_bsd_set_errno(EACCES);
13316 
13317         /* Return an error. */
13318         NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
13319         return(NX_SOC_ERROR);
13320     }
13321 
13322 #ifdef NX_ENABLE_VLAN
13323     nx_link_raw_packet_send(nx_bsd_default_ip, if_index, packet_ptr);
13324 #else
13325     _nx_driver_hardware_packet_send(packet_ptr);
13326 #endif /* NX_ENABLE_VLAN */
13327 
13328     /* Release the mutex. */
13329     tx_mutex_put(nx_bsd_protection_ptr);
13330 
13331     return(msgLength);
13332 }
13333 
13334 
13335 /**************************************************************************/
13336 /*                                                                        */
13337 /*  FUNCTION                                               RELEASE        */
13338 /*                                                                        */
13339 /*    _nx_bsd_hardware_packet_received                    PORTABLE C      */
13340 /*                                                           6.1          */
13341 /*  AUTHOR                                                                */
13342 /*                                                                        */
13343 /*    Yuxin Zhou, Microsoft Corporation                                   */
13344 /*                                                                        */
13345 /*  DESCRIPTION                                                           */
13346 /*                                                                        */
13347 /*    This function receives raw packet from driver directly.             */
13348 /*                                                                        */
13349 /*  INPUT                                                                 */
13350 /*                                                                        */
13351 /*    packet_ptr                            Pointer to received packet    */
13352 /*    consumed                              Return packet consumed or not */
13353 /*                                                                        */
13354 /*  OUTPUT                                                                */
13355 /*                                                                        */
13356 /*    None                                                                */
13357 /*                                                                        */
13358 /*  CALLS                                                                 */
13359 /*                                                                        */
13360 /*    nx_bsd_select_wakeup                  Wake up any asychronous       */
13361 /*                                            receive call                */
13362 /*                                                                        */
13363 /*  CALLED BY                                                             */
13364 /*                                                                        */
13365 /*    Application Code                                                    */
13366 /*                                                                        */
13367 /*  RELEASE HISTORY                                                       */
13368 /*                                                                        */
13369 /*    DATE              NAME                      DESCRIPTION             */
13370 /*                                                                        */
13371 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13372 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13373 /*                                            resulting in version 6.1    */
13374 /*                                                                        */
13375 /**************************************************************************/
_nx_bsd_hardware_packet_received(NX_PACKET * packet_ptr,UCHAR * consumed)13376 static VOID  _nx_bsd_hardware_packet_received(NX_PACKET *packet_ptr, UCHAR *consumed)
13377 {
13378 
13379 UINT i;
13380 UINT sockid = NX_BSD_MAX_SOCKETS;
13381 NX_BSD_SOCKET *bsd_ptr;
13382 
13383     /* Initialize the consumed to be false. */
13384     *consumed = NX_FALSE;
13385 
13386     /* Find the socket with the matching interface.  Put the packet into the socket's recevie queue. */
13387     for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
13388     {
13389         if((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE) &&
13390                 (nx_bsd_socket_array[i].nx_bsd_socket_family == AF_PACKET) &&
13391                 ((nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY) ||
13392                  (nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface == (ULONG)(packet_ptr -> nx_packet_ip_interface))))
13393         {
13394             sockid = i;
13395         }
13396     }
13397     if(sockid == NX_BSD_MAX_SOCKETS)
13398     {
13399         /* No BSD sockets are avaialble for this frame type. */
13400         return;
13401     }
13402     /* Now we need to put the packet into the socket. */
13403     bsd_ptr = &nx_bsd_socket_array[sockid];
13404 
13405     /* Drop the packet if the receive queue exceeds max depth. */
13406     if(bsd_ptr -> nx_bsd_socket_received_packet_count >=
13407             bsd_ptr -> nx_bsd_socket_received_packet_count_max)
13408     {
13409         return;
13410     }
13411 
13412 #ifndef NX_DISABLE_BSD_RAW_PACKET_DUPLICATE
13413     /* Duplicate the packet. */
13414     if (nx_packet_copy(packet_ptr, &packet_ptr, nx_bsd_default_packet_pool, NX_NO_WAIT) != NX_SUCCESS)
13415     {
13416         return;
13417     }
13418 #else
13419     /* Consume the packet. IP layer will not see it. */
13420     *consumed = NX_TRUE;
13421 #endif /* NX_DISABLE_BSD_RAW_PACKET_DUPLICATE */
13422 
13423     if(bsd_ptr -> nx_bsd_socket_received_packet)
13424     {
13425         bsd_ptr -> nx_bsd_socket_received_packet_tail -> nx_packet_queue_next = packet_ptr;
13426     }
13427     else
13428     {
13429         bsd_ptr -> nx_bsd_socket_received_packet = packet_ptr;
13430         bsd_ptr -> nx_bsd_socket_received_packet_offset = 0;
13431     }
13432 
13433     bsd_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
13434     bsd_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
13435     bsd_ptr -> nx_bsd_socket_received_packet_count ++;
13436 
13437     nx_bsd_select_wakeup(sockid, FDSET_READ);
13438 
13439     return;
13440 }
13441 
13442 #ifdef NX_ENABLE_VLAN
13443 /**************************************************************************/
13444 /*                                                                        */
13445 /*  FUNCTION                                               RELEASE        */
13446 /*                                                                        */
13447 /*    _nx_bsd_ethernet_receive_notify                     PORTABLE C      */
13448 /*                                                           6.4.0        */
13449 /*  AUTHOR                                                                */
13450 /*                                                                        */
13451 /*    Yanwu Cai, Microsoft Corporation                                    */
13452 /*                                                                        */
13453 /*  DESCRIPTION                                                           */
13454 /*                                                                        */
13455 /*    This function receives raw packet from NetX Link layer.             */
13456 /*                                                                        */
13457 /*  INPUT                                                                 */
13458 /*                                                                        */
13459 /*    ip_ptr                                Pointer to IP struct          */
13460 /*    interface_index                       Interface index               */
13461 /*    packet_ptr                            Pointer to received packet    */
13462 /*    physical_address_msw                  Pyhsical address              */
13463 /*    physical_address_lsw                  Pyhsical address              */
13464 /*    packet_type                           Type of received packet       */
13465 /*    header_size                           Header size                   */
13466 /*    context                               Pointer to context            */
13467 /*    time_ptr                              Pointer to NX_LINK_TIME_STRUCT*/
13468 /*                                                                        */
13469 /*  OUTPUT                                                                */
13470 /*                                                                        */
13471 /*    NX_SUCCESS                            The packet is consumed        */
13472 /*    NX_SOC_ERROR                          Error occured and the packet  */
13473 /*                                            is not consumed             */
13474 /*                                                                        */
13475 /*  CALLS                                                                 */
13476 /*                                                                        */
13477 /*    nx_bsd_select_wakeup                  Wake up any asychronous       */
13478 /*                                            receive call                */
13479 /*                                                                        */
13480 /*  CALLED BY                                                             */
13481 /*                                                                        */
13482 /*    Application Code                                                    */
13483 /*                                                                        */
13484 /*  RELEASE HISTORY                                                       */
13485 /*                                                                        */
13486 /*    DATE              NAME                      DESCRIPTION             */
13487 /*                                                                        */
13488 /*  12-31-2023     Yanwu Cai                Initial Version 6.4.0         */
13489 /*                                                                        */
13490 /**************************************************************************/
_nx_bsd_ethernet_receive_notify(NX_IP * ip_ptr,UINT interface_index,NX_PACKET * packet_ptr,ULONG physical_address_msw,ULONG physical_address_lsw,UINT packet_type,UINT header_size,VOID * context,struct NX_LINK_TIME_STRUCT * time_ptr)13491 static UINT _nx_bsd_ethernet_receive_notify(NX_IP *ip_ptr, UINT interface_index, NX_PACKET *packet_ptr,
13492                                             ULONG physical_address_msw, ULONG physical_address_lsw,
13493                                             UINT packet_type, UINT header_size, VOID *context,
13494                                             struct NX_LINK_TIME_STRUCT *time_ptr)
13495 {
13496 UINT i;
13497 UINT sockid = NX_BSD_MAX_SOCKETS;
13498 NX_BSD_SOCKET *bsd_ptr;
13499 
13500 
13501     /* Find the socket with the matching interface.  Put the packet into the socket's recevie queue. */
13502     for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
13503     {
13504         if((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE) &&
13505                 (nx_bsd_socket_array[i].nx_bsd_socket_family == AF_PACKET) &&
13506                 ((nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY) ||
13507                  (nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface == (ULONG)(packet_ptr -> nx_packet_ip_interface))))
13508         {
13509             sockid = i;
13510         }
13511     }
13512     if(sockid == NX_BSD_MAX_SOCKETS)
13513     {
13514         /* No BSD sockets are avaialble for this frame type. */
13515         return(NX_SOC_ERROR);
13516     }
13517     /* Now we need to put the packet into the socket. */
13518     bsd_ptr = &nx_bsd_socket_array[sockid];
13519 
13520     /* Drop the packet if the receive queue exceeds max depth. */
13521     if(bsd_ptr -> nx_bsd_socket_received_packet_count >=
13522             bsd_ptr -> nx_bsd_socket_received_packet_count_max)
13523     {
13524         return(NX_SOC_ERROR);
13525     }
13526 
13527 #ifndef NX_DISABLE_BSD_RAW_PACKET_DUPLICATE
13528     /* Duplicate the packet. */
13529     if (nx_packet_copy(packet_ptr, &packet_ptr, nx_bsd_default_packet_pool, NX_NO_WAIT) != NX_SUCCESS)
13530     {
13531         return(NX_SOC_ERROR);
13532     }
13533 
13534 #endif /* NX_DISABLE_BSD_RAW_PACKET_DUPLICATE */
13535 
13536 #ifdef NX_ENABLE_VLAN
13537     if (header_size == NX_LINK_ETHERNET_HEADER_SIZE + NX_LINK_VLAN_HEADER_SIZE)
13538     {
13539         memmove(packet_ptr -> nx_packet_prepend_ptr + NX_LINK_VLAN_HEADER_SIZE,
13540                 packet_ptr -> nx_packet_prepend_ptr,
13541                 NX_LINK_ETHERNET_HEADER_SIZE - 2); /* use case of memmove is verified. */
13542         packet_ptr -> nx_packet_length =  packet_ptr -> nx_packet_length - NX_LINK_VLAN_HEADER_SIZE;
13543         packet_ptr -> nx_packet_prepend_ptr += NX_LINK_VLAN_HEADER_SIZE;
13544     }
13545 #endif /* NX_ENABLE_VLAN */
13546 
13547     if(bsd_ptr -> nx_bsd_socket_received_packet)
13548     {
13549         bsd_ptr -> nx_bsd_socket_received_packet_tail -> nx_packet_queue_next = packet_ptr;
13550     }
13551     else
13552     {
13553         bsd_ptr -> nx_bsd_socket_received_packet = packet_ptr;
13554         bsd_ptr -> nx_bsd_socket_received_packet_offset = 0;
13555     }
13556 
13557     bsd_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
13558     bsd_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
13559     bsd_ptr -> nx_bsd_socket_received_packet_count ++;
13560 
13561     nx_bsd_select_wakeup(sockid, FDSET_READ);
13562 
13563     return(NX_SUCCESS);
13564 
13565 }
13566 #endif
13567 #endif /* NX_BSD_RAW_SUPPORT */
13568 
13569 
13570 
13571 /**************************************************************************/
13572 /*                                                                        */
13573 /*  FUNCTION                                               RELEASE        */
13574 /*                                                                        */
13575 /*    inet_pton                                           PORTABLE C      */
13576 /*                                                           6.3.0        */
13577 /*  AUTHOR                                                                */
13578 /*                                                                        */
13579 /*    Yuxin Zhou, Microsoft Corporation                                   */
13580 /*                                                                        */
13581 /*  DESCRIPTION                                                           */
13582 /*                                                                        */
13583 /*    This function converts an IP address from  presentation to numeric. */
13584 /*                                                                        */
13585 /*  INPUT                                                                 */
13586 /*                                                                        */
13587 /*    af                                    Either AF_INET or AF_INET6    */
13588 /*    src                                   A pointer pointing to the     */
13589 /*                                            presentation of IP address  */
13590 /*    dst                                   A pointer pointing to the     */
13591 /*                                            destination memory          */
13592 /*                                                                        */
13593 /*  OUTPUT                                                                */
13594 /*                                                                        */
13595 /*    status                                1 OK                          */
13596 /*                                          0 invalid presentation        */
13597 /*                                          -1 error                      */
13598 /*                                                                        */
13599 /*  CALLS                                                                 */
13600 /*                                                                        */
13601 /*    inet_aton                             Convert IPv4 address from     */
13602 /*                                          presentation to numeric       */
13603 /*                                                                        */
13604 /*  CALLED BY                                                             */
13605 /*                                                                        */
13606 /*    Application Code                                                    */
13607 /*                                                                        */
13608 /*  RELEASE HISTORY                                                       */
13609 /*                                                                        */
13610 /*    DATE              NAME                      DESCRIPTION             */
13611 /*                                                                        */
13612 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13613 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13614 /*                                            resulting in version 6.1    */
13615 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
13616 /*                                            used new API/structs naming,*/
13617 /*                                            resulting in version 6.3.0  */
13618 /*                                                                        */
13619 /**************************************************************************/
nx_bsd_inet_pton(INT af,const CHAR * src,VOID * dst)13620 INT  nx_bsd_inet_pton(INT af, const CHAR *src, VOID *dst)
13621 {
13622 CHAR    ch;
13623 USHORT  value;
13624 /* A number used to convert a character in '0123456789abcdefABCDEF'  to a number. */
13625 UINT    minuend;
13626 /* A counter used to recoder the number of digits between 2 colons. */
13627 UINT    digit_counter;
13628 
13629 UCHAR   *colon_location;
13630 /* A pointer used to traverse the destination memory. */
13631 UCHAR   *dst_cur_ptr;
13632 /* A pointer to the end of the destination memory. */
13633 UCHAR   *dst_end_ptr;
13634 ULONG   *dst_long_ptr;
13635 
13636 const CHAR    *ipv4_addr_start = src;
13637 UINT    n, i;
13638 
13639 struct  nx_bsd_in_addr ipv4_addr;
13640 
13641     if(af == AF_INET)
13642     {
13643         /* Convert IPv4 address from presentation to numeric. */
13644         if(nx_bsd_inet_aton(src, &ipv4_addr))
13645         {
13646             /* Copy the IPv4 address to the destination. */
13647             *((ULONG *)dst) = ipv4_addr.s_addr;
13648             return 1;
13649         }
13650         return 0;
13651     }
13652     else if(af == AF_INET6)
13653     {
13654         /* If : is at the beginning, the next value must be : .*/
13655         if(*src == ':')
13656             if(*src++ != ':')
13657                 return 0;
13658 
13659         /* Initialization. */
13660         value          = 0;
13661         digit_counter  = 0;
13662         colon_location = NX_NULL;
13663         dst_cur_ptr    = dst;
13664         /* Calculate the end of the destination memory. */
13665         dst_end_ptr    = (UCHAR*)dst + 15;
13666         /* Clear the destination memory. */
13667         memset(dst_cur_ptr, 0, 16);
13668 
13669         while(*src != 0)
13670         {
13671             /* Get the current character. */
13672             ch = *src++;
13673 
13674             /* Judge which minuend to use.
13675              * '0' - 48 == 0
13676              * 'a' - 87 == 10
13677              * 'A' - 55 == 10
13678              */
13679             minuend = 0;
13680             if(ch >= '0' && ch <= '9')
13681                 minuend = 48;
13682             else if(ch >= 'a' && ch <= 'f')
13683                 minuend = 87;
13684             else if(ch >= 'A' && ch <= 'F')
13685                 minuend = 55;
13686 
13687             /* if minuend is not 0, then ch is character in "0123456789abcdefABCDEF" */
13688             if(minuend)
13689             {
13690                 /* Convert the character to number. */
13691                 value = (USHORT)(value << 4);
13692                 value = (USHORT)(value | ((UINT)ch - minuend));
13693 
13694                 /* The max number of digits between 2 colons is 4. */
13695                 if(++digit_counter > 4)
13696                     return 0;
13697 
13698                 continue;
13699             }
13700 
13701             if(ch == ':')
13702             {
13703                 ipv4_addr_start = src;
13704 
13705                 /* Is there a digit before the colon? */
13706                 if(!digit_counter)
13707                 {
13708                     /* There is no digit before the colon. */
13709 
13710                     /* If there are 2 "::", Invalid Presentation Format.
13711                      * IF there is a ":::", Invalid Presention Format. */
13712                     if(colon_location)
13713                         return 0;
13714 
13715                     /* Record the colon location. */
13716                     colon_location = dst_cur_ptr;
13717                     continue;
13718                 }
13719                 else if(*src == '\0')
13720                 {
13721                     /* The colon is at the end of src, Invalid Presention Format. */
13722                     return 0;
13723                 }
13724 
13725                 if(dst_cur_ptr + 1 > dst_end_ptr)
13726                 {
13727                     /* Invalid Presentation Format. */
13728                     return 0;
13729                 }
13730 
13731                 /* Store the value to the dst memory. */
13732                 *(dst_cur_ptr++) = (UCHAR) (value >> 8) & 0xff;
13733                 *(dst_cur_ptr++) = (UCHAR) (value) & 0xff;
13734 
13735                 /* Reset the value and digit counter. */
13736                 digit_counter = 0;
13737                 value = 0;
13738 
13739                 continue;
13740 
13741             }
13742             else if(ch == '.')
13743             {
13744                 /* Process the dotted-decimal string in IPv4-mapped IPv6 address and IPv4-compatible IPv6 address. */
13745 
13746                 if(dst_cur_ptr + 3 > dst_end_ptr)
13747                 {
13748                     /* Invalid Presentation Format. */
13749                     return 0;
13750                 }
13751 
13752                 /* Convert the ipv4 address from presentation to numeric. */
13753                 if(nx_bsd_inet_aton(ipv4_addr_start, &ipv4_addr))
13754                 {
13755 
13756                     /* Make sure the result is in network byte order. */
13757                     ipv4_addr.s_addr = ntohl(ipv4_addr.s_addr);
13758                     NX_CHANGE_ULONG_ENDIAN(ipv4_addr.s_addr);
13759 
13760                     /* Store the value to the dst memory. */
13761                     *(ULONG *)dst_cur_ptr = ipv4_addr.s_addr;
13762 
13763                     dst_cur_ptr += 4;
13764                     digit_counter = 0;
13765 
13766                     break;
13767                 }
13768                 else
13769                     return 0;
13770 
13771 
13772             }
13773             else
13774             {
13775                 return 0;
13776             }
13777         }
13778 
13779         if(digit_counter)
13780         {
13781 
13782             /* Invalid Presentation Format. */
13783             if(dst_cur_ptr + 1 > dst_end_ptr)
13784                 return 0;
13785 
13786             /* Store the value to the dst memory. */
13787             *(dst_cur_ptr++) = (UCHAR) (value >> 8) & 0xff;
13788             *(dst_cur_ptr++) = (UCHAR) (value)      & 0xff;
13789 
13790         }
13791 
13792         if(colon_location)
13793         {
13794             /* There is a :: in the IPv6 address presentation. */
13795 
13796             /* Calculate how many octets should be moved to the end of the dst memory. */
13797             n = (UINT)(dst_cur_ptr  - colon_location);
13798 
13799             if(dst_cur_ptr == dst_end_ptr)
13800                 return 0;
13801 
13802             /* Move the data to the end of dst memory.
13803              *  -----------         -----------
13804              * |aabb0000000| ----> |aa0000000bb|
13805              *  -----------         -----------
13806              */
13807             for(i = 1; i <=n; i++)
13808             {
13809                 *(dst_end_ptr--) = colon_location[n - i];
13810                 colon_location[n-i]  = 0;
13811             }
13812 
13813             dst_cur_ptr = dst_end_ptr + 1;
13814         }
13815 
13816         if(dst_cur_ptr != (dst_end_ptr + 1))
13817             return 0;
13818 
13819         dst_long_ptr = (ULONG *)dst;
13820 
13821         /* First convert it to host byte order. */
13822         NX_CHANGE_ULONG_ENDIAN(dst_long_ptr[0]);
13823         NX_CHANGE_ULONG_ENDIAN(dst_long_ptr[1]);
13824         NX_CHANGE_ULONG_ENDIAN(dst_long_ptr[2]);
13825         NX_CHANGE_ULONG_ENDIAN(dst_long_ptr[3]);
13826 
13827         /* Convert it to network byte order by BSD macros. */
13828         dst_long_ptr[0] = htonl(dst_long_ptr[0]);
13829         dst_long_ptr[1] = htonl(dst_long_ptr[1]);
13830         dst_long_ptr[2] = htonl(dst_long_ptr[2]);
13831         dst_long_ptr[3] = htonl(dst_long_ptr[3]);
13832         return 1;
13833     }
13834     else
13835     {
13836         /* Error. */
13837         return -1;
13838     }
13839 }
13840 
13841 /**************************************************************************/
13842 /*                                                                        */
13843 /*  FUNCTION                                               RELEASE        */
13844 /*                                                                        */
13845 /*    inet_ntop                                           PORTABLE C      */
13846 /*                                                           6.3.0        */
13847 /*  AUTHOR                                                                */
13848 /*                                                                        */
13849 /*    Yuxin Zhou, Microsoft Corporation                                   */
13850 /*                                                                        */
13851 /*  DESCRIPTION                                                           */
13852 /*                                                                        */
13853 /*    This function converts an IP address from  numeric to presentation. */
13854 /*                                                                        */
13855 /*  INPUT                                                                 */
13856 /*                                                                        */
13857 /*    af                                    Either AF_INET or AF_INET6    */
13858 /*    src                                   A void pointer pointing to    */
13859 /*                                           network byte order IP address*/
13860 /*    dst                                   A char pointer pointing to    */
13861 /*                                           the destination buffer       */
13862 /*    size                                  The size of the destination   */
13863 /*                                           buffer                       */
13864 /*                                                                        */
13865 /*  OUTPUT                                                                */
13866 /*                                                                        */
13867 /*    dst                                   The destination buffer        */
13868 /*                                                                        */
13869 /*  CALLS                                                                 */
13870 /*                                                                        */
13871 /*    inet_ntoa_internal                    Convert IPv4 address from     */
13872 /*                                          numeric to presentation       */
13873 /*                                                                        */
13874 /*  CALLED BY                                                             */
13875 /*                                                                        */
13876 /*    Application Code                                                    */
13877 /*                                                                        */
13878 /*  RELEASE HISTORY                                                       */
13879 /*                                                                        */
13880 /*    DATE              NAME                      DESCRIPTION             */
13881 /*                                                                        */
13882 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
13883 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
13884 /*                                            resulting in version 6.1    */
13885 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
13886 /*                                            used new API/structs naming,*/
13887 /*                                            resulting in version 6.3.0  */
13888 /*                                                                        */
13889 /**************************************************************************/
nx_bsd_inet_ntop(INT af,const VOID * src,CHAR * dst,nx_bsd_socklen_t size)13890 const CHAR *nx_bsd_inet_ntop(INT af, const VOID *src, CHAR *dst, nx_bsd_socklen_t size)
13891 {
13892 
13893 INT    shorthand_index;
13894 INT    shorthand_len;
13895 INT    current_index;
13896 INT    current_len;
13897 
13898 INT    i;
13899 INT    index;
13900 UINT   rt_size;
13901 
13902 
13903     if(af == AF_INET)
13904     {
13905         /* Convert IPv4 address from numeric to presentation. */
13906         if(inet_ntoa_internal(src, dst, size))
13907             return dst;
13908         else
13909             return NX_NULL;
13910     }
13911     else if(af == AF_INET6)
13912     {
13913     USHORT temp[8];
13914         temp[0] = (USHORT)(ntohl(*((ULONG *)src)) >> 16);
13915         temp[1] = (USHORT)(ntohl(*((ULONG *)src)) & 0xFFFF);
13916         temp[2] = (USHORT)(ntohl(*(((ULONG *)src) + 1)) >> 16);
13917         temp[3] = (USHORT)(ntohl(*(((ULONG *)src) + 1)) & 0xFFFF);
13918         temp[4] = (USHORT)(ntohl(*(((ULONG *)src) + 2)) >> 16);
13919         temp[5] = (USHORT)(ntohl(*(((ULONG *)src) + 2)) & 0xFFFF);
13920         temp[6] = (USHORT)(ntohl(*(((ULONG *)src) + 3)) >> 16);
13921         temp[7] = (USHORT)(ntohl(*(((ULONG *)src) + 3)) & 0xFFFF);
13922 
13923         /* Initialization. */
13924         shorthand_index = -1;
13925         shorthand_len = 0;
13926         current_index = -1;
13927         current_len = 0;
13928 
13929         /* Find the longest 0x00 in src for ::
13930          * 16 * 8 == 128  */
13931         for(i = 0; i < 8; i++)
13932         {
13933             if(temp[i] == 0)
13934             {
13935                 if(current_index == -1)
13936                 {
13937                     /* Record the index of 0x00, Initialize the length to 1. */
13938                     current_index = i;
13939                     current_len = 1;
13940                 }
13941                 else
13942                 {
13943                     current_len++;
13944                 }
13945             }
13946             else
13947             {
13948                 /* Not 0x00 . */
13949 
13950                 if(current_index != -1)
13951                 {
13952                     /* Not equal -1, means there is record of 0x00s . */
13953 
13954                     if(shorthand_index == -1 || current_len > shorthand_len)
13955                     {
13956                         /* Record the longest 0x00s. */
13957                         shorthand_index = current_index;
13958                         shorthand_len = current_len;
13959                     }
13960 
13961                     /* Reset the index. */
13962                     current_index = -1;
13963                 }
13964 
13965             }
13966         }
13967 
13968 
13969         if(current_len > shorthand_len)
13970         {
13971             /* Record the longest 0x00s. */
13972             shorthand_index = current_index;
13973             shorthand_len = current_len;
13974         }
13975 
13976         /* If length is less than 2, no need for shorthand. */
13977         if(shorthand_len < 2)
13978         {
13979             shorthand_index = -1;
13980         }
13981 
13982         index = 0;
13983         /* Format the result. */
13984         for(i = 0; i < 8; i++)
13985         {
13986             /* Is i in the range of :: */
13987             if((shorthand_index != -1) &&
13988                (i >= shorthand_index) &&
13989                (i < (shorthand_index + shorthand_len)))
13990             {
13991                 if(i == shorthand_index)
13992                 {
13993                     /* Check if there is enough memory to store a character. */
13994                     if((size - (ULONG)index) < 1)
13995                         return NX_NULL;
13996 
13997                     dst[index++] = ':';
13998                 }
13999                 continue;
14000             }
14001 
14002            if(i != 0)
14003            {
14004                 /* Check if there is enough memory to store a character. */
14005                 if((size - (ULONG)index) < 1)
14006                     return NX_NULL;
14007 
14008                 dst[index++] = ':';
14009            }
14010 
14011            /* Does this address contain IPv4 address. */
14012            if(i == 6 && shorthand_index == 0 &&
14013               (shorthand_len == 6 ||                       /* IPv4-mapped IPv6 address     ----->  ::1.2.3.4 */
14014               (shorthand_len == 5 && temp[5] == 0xffff)))  /* IPv4-compatible IPv6 address ----->  ::ffff:1.2.3.4 */
14015            {
14016                /* Convert ipv4 address to string.  12 == 16 - 4*/
14017                rt_size = (UINT)inet_ntoa_internal((UCHAR*)src + 12, &dst[index], size - (ULONG)index);
14018 
14019                /* Check the return size, 0 means error. */
14020                if(rt_size)
14021                    index += (INT)rt_size;
14022                else
14023                    return NX_NULL;
14024            }
14025 
14026            /* Convert hex number to string */
14027            rt_size = bsd_number_convert(temp[i], &dst[index], size - (ULONG)index, 16);
14028            if(!rt_size)
14029                return NX_NULL;
14030 
14031            /* Increment the index. */
14032            index += (INT)rt_size;
14033 
14034         }
14035 
14036         /* Is there a trailing : */
14037         if((shorthand_index != -1) && (shorthand_index + shorthand_len == 8))
14038         {
14039             /* Check if there is enough memory to store a character. */
14040             if((size - (ULONG)index) < 1)
14041                 return NX_NULL;
14042 
14043             dst[index++] = ':';
14044 
14045         }
14046 
14047         /* Check if there is enough memory to store a character. */
14048         if((size - (ULONG)index) < 1)
14049             return NX_NULL;
14050 
14051         dst[index] = '\0';
14052 
14053         return dst;
14054     }
14055     else
14056     {
14057         return NX_NULL;
14058     }
14059 }
14060 
14061 /**************************************************************************/
14062 /*                                                                        */
14063 /*  FUNCTION                                               RELEASE        */
14064 /*                                                                        */
14065 /*    inet_ntoa_internal                                  PORTABLE C      */
14066 /*                                                           6.1          */
14067 /*  AUTHOR                                                                */
14068 /*                                                                        */
14069 /*    Yuxin Zhou, Microsoft Corporation                                   */
14070 /*                                                                        */
14071 /*  DESCRIPTION                                                           */
14072 /*                                                                        */
14073 /*    This function converts an IPv4 address to a string and returns the  */
14074 /*    size of the string.                                                 */
14075 /*                                                                        */
14076 /*  INPUT                                                                 */
14077 /*                                                                        */
14078 /*    src                                   A void pointer pointing to    */
14079 /*                                            IPv4 address                */
14080 /*    dst                                   A char pointer pointing to    */
14081 /*                                            the destination buffer      */
14082 /*    dst_size                              The size of the destination   */
14083 /*                                            buffer                      */
14084 /*                                                                        */
14085 /*  OUTPUT                                                                */
14086 /*                                                                        */
14087 /*    index                                 The size of the IPv4 address  */
14088 /*                                            string                      */
14089 /*                                                                        */
14090 /*  CALLS                                                                 */
14091 /*                                                                        */
14092 /*    memset                                Set the memory to 0           */
14093 /*    bsd_number_convert                    Convert a number to string    */
14094 /*                                                                        */
14095 /*  CALLED BY                                                             */
14096 /*                                                                        */
14097 /*    NetX Duo BSD Layer Source Code                                      */
14098 /*                                                                        */
14099 /*  RELEASE HISTORY                                                       */
14100 /*                                                                        */
14101 /*    DATE              NAME                      DESCRIPTION             */
14102 /*                                                                        */
14103 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14104 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
14105 /*                                            resulting in version 6.1    */
14106 /*                                                                        */
14107 /**************************************************************************/
14108 
inet_ntoa_internal(const VOID * src,CHAR * dst,ULONG dst_size)14109 static INT inet_ntoa_internal(const VOID *src, CHAR *dst, ULONG dst_size)
14110 {
14111 ULONG temp;
14112 UINT size;
14113 UINT index = 0;
14114 
14115 
14116     /* Set a local pointer to move up the buffer. */
14117     temp = ntohl(*((ULONG *)src));
14118 
14119     memset(dst, 0, dst_size);
14120 
14121     /* Convert the first number to a string. */
14122     size = bsd_number_convert((temp >> 24), &dst[0], dst_size - index, 10);
14123 
14124     if(!size)
14125         return 0;
14126 
14127     /* Move up the index and buffer pointer. */
14128     index += size;
14129 
14130     /* Check the rest of the dst buffer. */
14131     if((dst_size - index) < 1)
14132         return 0;
14133 
14134     /* Add the decimal. */
14135     dst[index++] = '.';
14136 
14137     /* And repeat three more times...*/
14138     size = bsd_number_convert((temp >> 16) & 0xff, &dst[index], dst_size - index, 10);
14139 
14140     if(!size)
14141         return 0;
14142 
14143     index += size;
14144 
14145     if((dst_size - index) < 1)
14146         return 0;
14147 
14148     dst[index++] = '.';
14149 
14150     size = bsd_number_convert((temp >> 8) & 0xff, &dst[index], dst_size - index, 10);
14151 
14152     if(!size)
14153         return 0;
14154 
14155     index += size;
14156 
14157     if((dst_size - index) < 1)
14158         return 0;
14159 
14160     dst[index++] = '.';
14161 
14162     size = bsd_number_convert(temp & 0xff, &dst[index], dst_size - index, 10);
14163 
14164     if(!size)
14165         return 0;
14166 
14167     index += size;
14168 
14169     if((dst_size - index) < 1)
14170         return 0;
14171 
14172     dst[index++] = '\0';
14173 
14174     /* Return the size of the dst string. */
14175     return((INT)(index));
14176 }
14177 
14178 
14179 /**************************************************************************/
14180 /*                                                                        */
14181 /*  FUNCTION                                               RELEASE        */
14182 /*                                                                        */
14183 /*    getaddrinfo                                         PORTABLE C      */
14184 /*                                                           6.3.0        */
14185 /*  AUTHOR                                                                */
14186 /*                                                                        */
14187 /*    Yuxin Zhou, Microsoft Corporation                                   */
14188 /*                                                                        */
14189 /*  DESCRIPTION                                                           */
14190 /*                                                                        */
14191 /*    This function returns one or more addrinfo structures according to  */
14192 /*    the specified node and service.                                     */
14193 /*                                                                        */
14194 /*  INPUT                                                                 */
14195 /*                                                                        */
14196 /*   node                                   Node is either a hostname or  */
14197 /*                                           an address string(dotted-    */
14198 /*                                           decimal for IPv4 or a hex    */
14199 /*                                           string for IPv6).            */
14200 /*   service                                Service is either a service   */
14201 /*                                           name or a decimal port number*/
14202 /*                                           string.                      */
14203 /*   hints                                  Hints is either a null pointer*/
14204 /*                                           or a pointer to an addrinfo  */
14205 /*                                           structure that the caller    */
14206 /*                                           fills in with hints about the*/
14207 /*                                           types of information the     */
14208 /*                                           caller wants returned.       */
14209 /*   res                                    Pointer to the returned       */
14210 /*                                           addrinfo list.               */
14211 /*                                                                        */
14212 /*  OUTPUT                                                                */
14213 /*                                                                        */
14214 /*    status                                0 if OK, nonzero on errors    */
14215 /*                                                                        */
14216 /*  CALLS                                                                 */
14217 /*                                                                        */
14218 /*    bsd_string_to_number                  Convert a string to a number  */
14219 /*    htons                                 Host byte order to network    */
14220 /*                                          byte order                    */
14221 /*    memcmp                                Memory compare                */
14222 /*    inet_pton                             Convert IP address from       */
14223 /*                                          presentation to numeric       */
14224 /*    tx_block_allocate                     Allocate memory for address or*/
14225 /*                                          addrinfo                      */
14226 /*    memset                                Set the memory to 0           */
14227 /*    freeaddrinfo                          Release addrinfo memory       */
14228 /*    nx_dns_ipv4_address_by_name_get       Get ipv4 addr by name via dns */
14229 /*    nxd_dns_ipv6_address_by_name_get      Get ipv6 addr by name via dns */
14230 /*                                                                        */
14231 /*  CALLED BY                                                             */
14232 /*                                                                        */
14233 /*    Application Code                                                    */
14234 /*                                                                        */
14235 /*  RELEASE HISTORY                                                       */
14236 /*                                                                        */
14237 /*    DATE              NAME                      DESCRIPTION             */
14238 /*                                                                        */
14239 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14240 /*  09-30-2020     Yuxin Zhou               Modified comment(s), improved */
14241 /*                                            buffer length verification, */
14242 /*                                            verified memcpy use cases,  */
14243 /*                                            fixed compiler errors,      */
14244 /*                                            resulting in version 6.1    */
14245 /*  07-29-2022     Yuxin Zhou               Modified comment(s), and      */
14246 /*                                            fixed compiler warnings,    */
14247 /*                                            resulting in version 6.1.12 */
14248 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
14249 /*                                            used new API/structs naming,*/
14250 /*                                            resulting in version 6.3.0  */
14251 /*                                                                        */
14252 /**************************************************************************/
nx_bsd_getaddrinfo(const CHAR * node,const CHAR * service,const struct nx_bsd_addrinfo * hints,struct nx_bsd_addrinfo ** res)14253 INT  nx_bsd_getaddrinfo(const CHAR *node, const CHAR *service, const struct nx_bsd_addrinfo *hints, struct nx_bsd_addrinfo **res)
14254 {
14255 
14256 UINT            status;
14257 #ifdef NX_BSD_ENABLE_DNS
14258 UINT            status2;
14259 #endif
14260 UINT            pton_flag;
14261 UINT            port;
14262 UINT            i, j;
14263 INT             addr_family;
14264 UINT            ipv4_addr_count = 0;
14265 UINT            ipv6_addr_count = 0;
14266 UINT            match_service_count;
14267 UINT            match_service_socktype[3];
14268 UINT            match_service_protocol[3];
14269 struct nx_bsd_addrinfo
14270                *addrinfo_cur_ptr  = NX_NULL;
14271 struct nx_bsd_addrinfo
14272                *addrinfo_head_ptr = NX_NULL;
14273 struct nx_bsd_addrinfo
14274                *addrinfo_tail_ptr = NX_NULL;
14275 struct nx_bsd_sockaddr
14276                *sockaddr_ptr      = NX_NULL;
14277 UCHAR           *cname_buffer      = NX_NULL;
14278 
14279 /* When hints is a null pointer, use the default value below. */
14280 static struct nx_bsd_addrinfo default_hints = {0, AF_UNSPEC, 0, 0, 0, NX_NULL, NX_NULL, NX_NULL};
14281 
14282 
14283 
14284     /* if node and service are null return an error, invalid input. */
14285     if((node == NX_NULL) && (service == NX_NULL))
14286         return EAI_NONAME;
14287 
14288     if(hints)
14289     {
14290 
14291         /* Check if the address family is valid. */
14292         if((hints -> ai_family != AF_INET)  &&
14293            (hints -> ai_family != AF_INET6) &&
14294            (hints -> ai_family != AF_UNSPEC))
14295             return EAI_FAMILY;
14296 
14297         /* Check if the socket type is valid. */
14298         if((hints -> ai_socktype != SOCK_DGRAM)  &&
14299            (hints -> ai_socktype != SOCK_STREAM) &&
14300            (hints -> ai_socktype != 0))
14301             return EAI_SOCKTYPE;
14302 
14303         /* If socktype and protocol are both specified, check if they are meaningful. */
14304         if((hints -> ai_socktype != 0) && (hints -> ai_protocol != 0))
14305         {
14306             if(((hints -> ai_socktype == SOCK_STREAM) && (hints -> ai_protocol != IPPROTO_TCP)) ||
14307                ((hints -> ai_socktype == SOCK_DGRAM) && (hints -> ai_protocol != IPPROTO_UDP)) ||
14308                ((hints -> ai_socktype == SOCK_RAW) && (hints -> ai_protocol != IPPROTO_RAW)))
14309                 return EAI_SOCKTYPE;
14310         }
14311 
14312     }
14313     else
14314     {
14315         hints = &default_hints;
14316     }
14317 
14318     /* Sock type specified? */
14319     if(hints -> ai_socktype == 0)
14320     {
14321 
14322         /* No; is protocol specified? */
14323         if(hints -> ai_protocol == 0)
14324         {
14325 
14326             /* No, protocol is not specified. */
14327 
14328             /* Set default socktype and protocol. */
14329             match_service_count = 3;
14330             match_service_socktype[0] = SOCK_STREAM;
14331             match_service_protocol[0] = IPPROTO_TCP;
14332             match_service_socktype[1] = SOCK_DGRAM;
14333             match_service_protocol[1] = IPPROTO_UDP;
14334             match_service_socktype[2] = SOCK_RAW;
14335             match_service_protocol[2] = 0;
14336         }
14337         else
14338         {
14339 
14340             /* protocol is specified. */
14341             match_service_count = 1;
14342             match_service_protocol[0] = (UINT)(hints -> ai_protocol);
14343 
14344             /* Set default socktype according to protocol. */
14345             if(hints -> ai_protocol == IPPROTO_TCP)
14346                 match_service_socktype[0] = SOCK_STREAM;
14347             else if(hints -> ai_protocol == IPPROTO_UDP)
14348                 match_service_socktype[0] = SOCK_DGRAM;
14349         }
14350     }
14351     else
14352     {
14353 
14354         /* Socktype is specified. */
14355         match_service_count = 1;
14356         match_service_socktype[0] = (UINT)(hints -> ai_socktype);
14357 
14358         if(hints -> ai_protocol == 0)
14359         {
14360 
14361             /* Protocol is not specified. */
14362 
14363             /* Set default protocol according to socktype. */
14364             if(hints -> ai_socktype == SOCK_STREAM)
14365                 match_service_protocol[0] = IPPROTO_TCP;
14366             else if(hints -> ai_socktype == SOCK_DGRAM)
14367                 match_service_protocol[0] = IPPROTO_UDP;
14368             else if(hints -> ai_socktype == SOCK_RAW)
14369                 match_service_protocol[0] = 0;
14370         }
14371         else
14372         {
14373 
14374             /* Protocol is specififed. */
14375             match_service_protocol[0] = (UINT)(hints -> ai_protocol);
14376         }
14377     }
14378 
14379     if(service)
14380     {
14381 
14382         /* Service is not null. */
14383         if(bsd_string_to_number(service, &port) != NX_SOC_ERROR)
14384         {
14385 
14386             /* Service is a decimal port number string, and has been converted to a numeric port successfully. */
14387 
14388             /* Convert port from host byte order to network byte order. */
14389             port = htons((USHORT)port);
14390         }
14391         else
14392         {
14393 
14394             /* Service is an address name, not a decimal port number string. */
14395 
14396             /* Check if numeric service flag is set. If so this is an invalid string. */
14397             if(hints -> ai_flags & AI_NUMERICSERV)
14398                 return EAI_NONAME;
14399 
14400             match_service_count = 0;
14401 
14402             /* Look for a match of name, protocol and socket type for a match in the service list. */
14403             for(i = 0; i < _nx_bsd_serv_list_len; i++)
14404             {
14405 
14406                 /* Check if there is a match. */
14407                 if(!memcmp(_nx_bsd_serv_list_ptr[i].service_name, service, _nx_bsd_string_length((CHAR *)service)) &&
14408                         ((_nx_bsd_serv_list_ptr[i].service_socktype == hints -> ai_socktype) ||(hints -> ai_socktype == 0)) &&
14409                         ((_nx_bsd_serv_list_ptr[i].service_protocol == hints -> ai_protocol) ||(hints -> ai_protocol == 0)))
14410                 {
14411                     match_service_socktype[match_service_count] = (UINT)(_nx_bsd_serv_list_ptr[i].service_socktype);
14412                     match_service_protocol[match_service_count++] = (UINT)(_nx_bsd_serv_list_ptr[i].service_protocol);
14413 
14414                     /* Convert host byte order to network byte order. */
14415                     port = htons(_nx_bsd_serv_list_ptr[i].service_port);
14416                 }
14417             }
14418 
14419             /* Service is not available. */
14420             if(match_service_count == 0)
14421                 return EAI_SERVICE;
14422         }
14423     }
14424     else
14425     {
14426 
14427         /* Convert host byte order to network byte order. */
14428         port = htons(0);
14429     }
14430 
14431     if(node)
14432     {
14433 
14434         /* Node is not null. */
14435 
14436         /* Determine the address family. */
14437         addr_family = AF_INET;
14438 
14439         for(i = 0; i < _nx_bsd_string_length((CHAR *)node); i++)
14440         {
14441             if(node[i] == ':')
14442             {
14443                 /* There is a colon, so it is an IPv6 address. */
14444                 addr_family = AF_INET6;
14445                 break;
14446             }
14447         }
14448 
14449         /* Initialize to 0, default to pton failing. */
14450         pton_flag = 0;
14451 
14452         if(addr_family == AF_INET)
14453         {
14454 
14455             /* Convert node from a string presentation to a numeric address. */
14456             if(nx_bsd_inet_pton(addr_family, node, &(nx_bsd_ipv4_addr_buffer[0])) == 1)
14457             {
14458                 /* pton has successful completion. */
14459                 pton_flag = 1;
14460 
14461                 /* Check if the address and the specified family match. */
14462                 if((hints -> ai_family != AF_INET) && (hints -> ai_family != AF_UNSPEC))
14463                     return EAI_ADDRFAMILY;
14464 
14465                 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv4_addr_buffer[0]);
14466                 ipv4_addr_count = 1;
14467             }
14468         }
14469         else
14470         {
14471 
14472             /* Convert node from a string presentation to a numeric address. */
14473             if(nx_bsd_inet_pton(addr_family, node, &(nx_bsd_ipv6_addr_buffer[0])) == 1)
14474             {
14475                 /* pton completed successfully. */
14476                 pton_flag = 1;
14477 
14478                 /* Check is the address and the specified family matches. */
14479                 if((hints -> ai_family != AF_INET6) && (hints -> ai_family != AF_UNSPEC))
14480                     return EAI_ADDRFAMILY;
14481 
14482                 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv6_addr_buffer[0]);
14483                 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv6_addr_buffer[1]);
14484                 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv6_addr_buffer[2]);
14485                 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv6_addr_buffer[3]);
14486                 ipv6_addr_count = 1;
14487             }
14488         }
14489 
14490         if(pton_flag == 1)
14491         {
14492 
14493             /* pton completed successfull. Host (node) is an address string. */
14494 
14495 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
14496             /* DNS supports extended services including Canonical name queries. */
14497             if((hints -> ai_flags & AI_CANONNAME) && !(hints -> ai_flags & AI_NUMERICHOST))
14498             {
14499 
14500                 /* Allocate a block for canonical name. */
14501                 status = tx_block_allocate(&nx_bsd_cname_block_pool, (VOID *) &cname_buffer, NX_BSD_TIMEOUT);
14502 
14503                 /* Check for error status.  */
14504                 if (status != TX_SUCCESS)
14505                 {
14506                     /* Set the error. */
14507                     nx_bsd_set_errno(ENOMEM);
14508 
14509                     /* Error getting NetX socket memory.  */
14510                     NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
14511 
14512                     /* Return memory allocation error. */
14513                     return(EAI_MEMORY);
14514                 }
14515 
14516                 /* Verify buffer size. */
14517                 if (_nx_bsd_string_length((CHAR *)node) > NX_DNS_NAME_MAX)
14518                     return(EAI_OVERFLOW);
14519 
14520                 memcpy(cname_buffer, node, _nx_bsd_string_length((CHAR *)node)); /* Use case of memcpy is verified. */
14521 
14522             }
14523 #endif /* NX_BSD_ENABLE_DNS && NX_DNS_ENABLE_EXTENDED_RR_TYPES */
14524 
14525         }
14526         else
14527         {
14528 
14529             /* Presentation to numeric format fails, node may be a hostname, not a numeric IP address. */
14530 
14531             /* Check if numeric host flag is set. */
14532             if(hints -> ai_flags & AI_NUMERICHOST)
14533                 return EAI_NONAME;
14534 
14535 #ifdef NX_BSD_ENABLE_DNS
14536             if(hints -> ai_family == AF_INET)
14537             {
14538 
14539                 /* Get IPv4 address by hostname. */
14540                 status = nx_dns_ipv4_address_by_name_get(_nx_dns_instance_ptr, (UCHAR *)node, &nx_bsd_ipv4_addr_buffer[0],
14541                                                          NX_BSD_IPV4_ADDR_PER_HOST * 4, &ipv4_addr_count, NX_BSD_TIMEOUT);
14542 
14543                 if(status != NX_SUCCESS)
14544                 {
14545 
14546                     /* Just return EAI_FAIL, because we can't discriminate between DNS FAIL and the situation where the specified
14547                        network host exists but does not have any network addresses defined. It would be better to return EAI_FAIL
14548                        for DNS FAIL, and EAI_NODATA for the latter situation. */
14549                     return EAI_FAIL;
14550                 }
14551             }
14552             else if(hints -> ai_family == AF_INET6)
14553             {
14554 
14555                 /* Get IPv6 address by hostname. */
14556                 status = nxd_dns_ipv6_address_by_name_get(_nx_dns_instance_ptr, (UCHAR *)node, &nx_bsd_ipv6_addr_buffer[0],
14557                                                           NX_BSD_IPV6_ADDR_PER_HOST * 16, &ipv6_addr_count, NX_BSD_TIMEOUT);
14558 
14559                 if(status != NX_SUCCESS)
14560                 {
14561                     /* Just return EAI_FAIL, because we can't discriminate between DNS FAIL and the situation where the specified
14562                        network host exists but does not have any network addresses defined. It would be better to return EAI_FAIL
14563                        for DNS FAIL, and EAI_NODATA for the latter situation. */
14564                     return EAI_FAIL;
14565                 }
14566             }
14567             else
14568             {
14569 
14570                 /* Address family is not specified. Query for both IPv4 and IPv6 address. */
14571 
14572                 /* Get IPv4 address by hostname. */
14573                 status = nx_dns_ipv4_address_by_name_get(_nx_dns_instance_ptr, (UCHAR *)node, &nx_bsd_ipv4_addr_buffer[0],
14574                                                          NX_BSD_IPV4_ADDR_PER_HOST * 4, &ipv4_addr_count, NX_BSD_TIMEOUT);
14575 
14576                 /* Get IPv6 address by hostname. */
14577                 status2 = nxd_dns_ipv6_address_by_name_get(_nx_dns_instance_ptr, (UCHAR *)node, &nx_bsd_ipv6_addr_buffer[0],
14578                                                            NX_BSD_IPV6_ADDR_PER_HOST * 16, &ipv6_addr_count, NX_BSD_TIMEOUT);
14579 
14580                 if((status != NX_SUCCESS) && status2 != NX_SUCCESS)
14581                 {
14582                     /* Just return EAI_FAIL, because we can't discriminate between DNS FAIL and the situation that the specified
14583                        network host exists, but does not have any network addresses defined. It would be better to return EAI_FAIL
14584                        for DNS FAIL, and EAI_NODATA for the latter situation. */
14585                     return EAI_FAIL;
14586                 }
14587             }
14588 
14589             if(hints -> ai_flags & AI_CANONNAME)
14590             {
14591 
14592 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14593                 /* Allocate a block for canonical name. */
14594                 status = tx_block_allocate(&nx_bsd_cname_block_pool, (VOID *) &cname_buffer, NX_BSD_TIMEOUT);
14595 
14596                 /* Check for error status.  */
14597                 if (status != TX_SUCCESS)
14598                 {
14599                     /* Set the error. */
14600                     set_errno(ENOMEM);
14601 
14602                     /* Error getting NetX socket memory.  */
14603                     NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
14604 
14605                     /* Return memory allocation error. */
14606                     return(EAI_MEMORY);
14607                 }
14608 
14609                 status = nx_dns_cname_get(_nx_dns_instance_ptr, (UCHAR *)node, cname_buffer,
14610                                           nx_bsd_cname_block_pool.tx_block_pool_block_size, NX_BSD_TIMEOUT);
14611                 if(status != NX_SUCCESS)
14612                 {
14613 
14614                     /* Verify buffer size. */
14615                     if (_nx_bsd_string_length((CHAR *)node) > NX_DNS_NAME_MAX)
14616                         return(EAI_OVERFLOW);
14617 
14618                     memcpy(cname_buffer, node, _nx_bsd_string_length((CHAR *)node)); /* Use case of memcpy is verified. */
14619                 }
14620 
14621 #else
14622                 cname_buffer = (UCHAR *)node;
14623 #endif
14624             }
14625 #else
14626             return EAI_FAIL;
14627 #endif
14628 
14629         }
14630     }
14631     else
14632     {
14633 
14634         /* Node is null. */
14635         if(hints -> ai_flags & AI_PASSIVE)
14636         {
14637             /* The caller wiil use the socket for a passive open. */
14638 
14639             nx_bsd_ipv4_addr_buffer[0] = INADDR_ANY;
14640 
14641             nx_bsd_ipv6_addr_buffer[0] = 0;
14642             nx_bsd_ipv6_addr_buffer[1] = 0;
14643             nx_bsd_ipv6_addr_buffer[2] = 0;
14644             nx_bsd_ipv6_addr_buffer[3] = 0;
14645         }
14646         else
14647         {
14648 
14649             /* Localhost address. */
14650             nx_bsd_ipv4_addr_buffer[0] = 0x7F000001;
14651 
14652             nx_bsd_ipv6_addr_buffer[0] = 0;
14653             nx_bsd_ipv6_addr_buffer[1] = 0;
14654             nx_bsd_ipv6_addr_buffer[2] = 0;
14655             nx_bsd_ipv6_addr_buffer[3] = 1;
14656         }
14657 
14658         if (hints -> ai_family != AF_INET6)
14659         {
14660             ipv4_addr_count = 1;
14661         }
14662         ipv6_addr_count = 1;
14663     }
14664 
14665 
14666     for(i = 0; i < ipv4_addr_count + ipv6_addr_count; i++)
14667     {
14668 
14669         /* Allocate a block for ipv4 address. */
14670         status = tx_block_allocate(&nx_bsd_addrinfo_block_pool, (VOID *) &sockaddr_ptr, NX_BSD_TIMEOUT);
14671 
14672         /* Check for error status.  */
14673         if (status != TX_SUCCESS)
14674         {
14675 
14676             /* Set the error. */
14677             nx_bsd_set_errno(ENOMEM);
14678 
14679             /* If head is not null, free the memory. */
14680             if(addrinfo_head_ptr)
14681                 nx_bsd_freeaddrinfo(addrinfo_head_ptr);
14682 
14683 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14684             if(hints -> ai_flags & AI_CANONNAME)
14685                 tx_block_release((VOID *)cname_buffer);
14686 #endif
14687 
14688             /* Error getting NetX socket memory.  */
14689             NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
14690 
14691             /* Return memory allocation error. */
14692             return(EAI_MEMORY);
14693         }
14694 
14695         /* Clear the  memory.  */
14696         memset((VOID*)sockaddr_ptr, 0, sizeof(struct nx_bsd_addrinfo));
14697 
14698         if(i < ipv4_addr_count)
14699         {
14700 
14701             /* Process IPv4 address. */
14702             ((struct nx_bsd_sockaddr_in*)sockaddr_ptr) -> sin_family = AF_INET;
14703             ((struct nx_bsd_sockaddr_in*)sockaddr_ptr) -> sin_port   = (USHORT)port;
14704             ((struct nx_bsd_sockaddr_in*)sockaddr_ptr) -> sin_addr.s_addr = nx_bsd_ipv4_addr_buffer[i];
14705 
14706             NX_CHANGE_ULONG_ENDIAN(((struct nx_bsd_sockaddr_in*)sockaddr_ptr) -> sin_addr.s_addr);
14707         }
14708         else
14709         {
14710 
14711             /* Process IPv6 address. */
14712             ((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_family = AF_INET6;
14713             ((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_port   = (USHORT)port;
14714             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. */
14715 
14716             NX_CHANGE_ULONG_ENDIAN(*(ULONG*)&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr.s6_addr32[0]));
14717             NX_CHANGE_ULONG_ENDIAN(*(ULONG*)&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr.s6_addr32[1]));
14718             NX_CHANGE_ULONG_ENDIAN(*(ULONG*)&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr.s6_addr32[2]));
14719             NX_CHANGE_ULONG_ENDIAN(*(ULONG*)&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr.s6_addr32[3]));
14720 
14721         }
14722 
14723         for(j = 0; j < match_service_count; j++)
14724         {
14725 
14726             /* Allocate a block from the addrinfo block pool. */
14727             status = tx_block_allocate(&nx_bsd_addrinfo_block_pool, (VOID *) &addrinfo_cur_ptr, NX_BSD_TIMEOUT);
14728 
14729             /* Check for error status.  */
14730             if (status != TX_SUCCESS)
14731             {
14732 
14733                 /* Set the error. */
14734                 nx_bsd_set_errno(ENOMEM);
14735 
14736                 /* If head is not null, free the memory. */
14737                 if(addrinfo_head_ptr)
14738                     nx_bsd_freeaddrinfo(addrinfo_head_ptr);
14739 
14740                 tx_block_release((VOID *)sockaddr_ptr);
14741 
14742 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14743                 if(hints -> ai_flags & AI_CANONNAME)
14744                     tx_block_release((VOID *)cname_buffer);
14745 #endif
14746 
14747                 /* Error getting NetX socket memory.  */
14748                 NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
14749 
14750                 /* Return memory allocation error. */
14751                 return(EAI_MEMORY);
14752             }
14753 
14754             /* Clear the socket memory.  */
14755             memset((VOID*)addrinfo_cur_ptr, 0, sizeof(struct nx_bsd_addrinfo));
14756 
14757             if(i < ipv4_addr_count)
14758             {
14759 
14760                 /* IPv4 */
14761                 addrinfo_cur_ptr -> ai_family  = AF_INET;
14762                 addrinfo_cur_ptr -> ai_addrlen = sizeof(struct nx_bsd_sockaddr_in);
14763             }
14764             else
14765             {
14766 
14767                 /* IPv6 */
14768                 addrinfo_cur_ptr -> ai_family = AF_INET6;
14769                 addrinfo_cur_ptr -> ai_addrlen = sizeof(struct nx_bsd_sockaddr_in6);
14770             }
14771 
14772             addrinfo_cur_ptr -> ai_socktype = (INT)(match_service_socktype[j]);
14773             addrinfo_cur_ptr -> ai_protocol = (INT)(match_service_protocol[j]);
14774             addrinfo_cur_ptr -> ai_addr = sockaddr_ptr;
14775             if((i == 0) && (j == 0) && (hints -> ai_flags & AI_CANONNAME))
14776                 addrinfo_cur_ptr -> ai_canonname = (CHAR *)cname_buffer;
14777             else
14778                 addrinfo_cur_ptr -> ai_canonname = NX_NULL;
14779             addrinfo_cur_ptr -> ai_next = NX_NULL;
14780 
14781             /* Make a list. */
14782             if(addrinfo_head_ptr == NX_NULL)
14783                 addrinfo_head_ptr = addrinfo_cur_ptr;
14784             else
14785                 addrinfo_tail_ptr -> ai_next = addrinfo_cur_ptr;
14786 
14787             addrinfo_tail_ptr = addrinfo_cur_ptr;
14788 
14789         }
14790     }
14791 
14792     *res = addrinfo_head_ptr;
14793 
14794     return 0;
14795 }
14796 
14797 /**************************************************************************/
14798 /*                                                                        */
14799 /*  FUNCTION                                               RELEASE        */
14800 /*                                                                        */
14801 /*    freeaddrinfo                                        PORTABLE C      */
14802 /*                                                           6.3.0        */
14803 /*  AUTHOR                                                                */
14804 /*                                                                        */
14805 /*    Yuxin Zhou, Microsoft Corporation                                   */
14806 /*                                                                        */
14807 /*  DESCRIPTION                                                           */
14808 /*                                                                        */
14809 /*    This function releases the memory allocated by getaddrinfo.         */
14810 /*                                                                        */
14811 /*  INPUT                                                                 */
14812 /*                                                                        */
14813 /*    res                                   Pointer to a addrinfo struct  */
14814 /*                                                                        */
14815 /*  OUTPUT                                                                */
14816 /*                                                                        */
14817 /*    None                                                                */
14818 /*                                                                        */
14819 /*  CALLS                                                                 */
14820 /*                                                                        */
14821 /*    tx_block_release                      Release socket memory         */
14822 /*                                                                        */
14823 /*  CALLED BY                                                             */
14824 /*                                                                        */
14825 /*    Application Code                                                    */
14826 /*                                                                        */
14827 /*  RELEASE HISTORY                                                       */
14828 /*                                                                        */
14829 /*    DATE              NAME                      DESCRIPTION             */
14830 /*                                                                        */
14831 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14832 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
14833 /*                                            resulting in version 6.1    */
14834 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
14835 /*                                            used new API/structs naming,*/
14836 /*                                            resulting in version 6.3.0  */
14837 /*                                                                        */
14838 /**************************************************************************/
nx_bsd_freeaddrinfo(struct nx_bsd_addrinfo * res)14839 VOID nx_bsd_freeaddrinfo(struct nx_bsd_addrinfo *res)
14840 {
14841 
14842 struct nx_bsd_addrinfo *next_addrinfo;
14843 struct nx_bsd_sockaddr *ai_addr_ptr = NX_NULL;
14844 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14845 CHAR *ai_canonname_ptr = NX_NULL;
14846 #endif
14847 
14848     while(res)
14849     {
14850 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14851         if((res -> ai_canonname) &&
14852            (res -> ai_canonname != ai_canonname_ptr))
14853         {
14854 
14855             /* Release  the CNAME memory. */
14856             tx_block_release((VOID *)res -> ai_canonname);
14857 
14858             ai_canonname_ptr = res -> ai_canonname;
14859         }
14860 #endif
14861         if((res -> ai_addr) &&
14862            (res -> ai_addr != ai_addr_ptr))
14863         {
14864 
14865             /* Release the address memory. */
14866             tx_block_release((VOID *)res -> ai_addr);
14867 
14868             ai_addr_ptr = res -> ai_addr;
14869         }
14870 
14871         /* Move next. */
14872         next_addrinfo = res -> ai_next;
14873 
14874         /* Release the addrinfo memory. */
14875         tx_block_release((VOID *)res);
14876 
14877         res = next_addrinfo;
14878     }
14879 }
14880 
14881 
14882 /**************************************************************************/
14883 /*                                                                        */
14884 /*  FUNCTION                                               RELEASE        */
14885 /*                                                                        */
14886 /*    bsd_string_to_number                                PORTABLE C      */
14887 /*                                                           6.1          */
14888 /*  AUTHOR                                                                */
14889 /*                                                                        */
14890 /*    Yuxin Zhou, Microsoft Corporation                                   */
14891 /*                                                                        */
14892 /*  DESCRIPTION                                                           */
14893 /*                                                                        */
14894 /*    This function converts string to number.                            */
14895 /*                                                                        */
14896 /*  INPUT                                                                 */
14897 /*                                                                        */
14898 /*    string                                Pointer to a string           */
14899 /*    number                                Pointer to a number           */
14900 /*                                                                        */
14901 /*  OUTPUT                                                                */
14902 /*                                                                        */
14903 /*    status                                                              */
14904 /*                                                                        */
14905 /*  CALLS                                                                 */
14906 /*                                                                        */
14907 /*    nx_bsd_isdigit                        Indicate char is a number     */
14908 /*                                                                        */
14909 /*  CALLED BY                                                             */
14910 /*                                                                        */
14911 /*    Application Code                                                    */
14912 /*                                                                        */
14913 /*  RELEASE HISTORY                                                       */
14914 /*                                                                        */
14915 /*    DATE              NAME                      DESCRIPTION             */
14916 /*                                                                        */
14917 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14918 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
14919 /*                                            resulting in version 6.1    */
14920 /*                                                                        */
14921 /**************************************************************************/
bsd_string_to_number(const CHAR * string,UINT * number)14922 static INT bsd_string_to_number(const CHAR *string, UINT *number)
14923 {
14924 
14925     /* Initialize the numbet to zero. */
14926     *number = 0;
14927 
14928     while(*string != '\0')
14929     {
14930 
14931         /* Check if the current character is a digit character. */
14932         if(!nx_bsd_isdigit((UCHAR)(*string)))
14933             return NX_SOC_ERROR;
14934 
14935         *number = (*number * 10) + (UINT)(*string - 0x30);
14936 
14937         string++;
14938     }
14939 
14940     return NX_SOC_OK;
14941 }
14942 
14943 /**************************************************************************/
14944 /*                                                                        */
14945 /*  FUNCTION                                               RELEASE        */
14946 /*                                                                        */
14947 /*    getnameinfo                                         PORTABLE C      */
14948 /*                                                           6.3.0        */
14949 /*  AUTHOR                                                                */
14950 /*                                                                        */
14951 /*    Yuxin Zhou, Microsoft Corporation                                   */
14952 /*                                                                        */
14953 /*  DESCRIPTION                                                           */
14954 /*                                                                        */
14955 /*    This function converts a socket address to a corresponding host and */
14956 /*    service.                                                            */
14957 /*                                                                        */
14958 /*  INPUT                                                                 */
14959 /*                                                                        */
14960 /*    sa                                   Pointer to a generic socket    */
14961 /*                                           address structure            */
14962 /*    salen                                Length of sa structure         */
14963 /*    host                                 Pointer to caller-allocated    */
14964 /*                                           buffer for hostname          */
14965 /*    hostlen                              Host buffer size               */
14966 /*    serv                                 Pointer to caller-allocated    */
14967 /*                                           buffer for service name      */
14968 /*    servlen                              Service buffer size            */
14969 /*                                                                        */
14970 /*  OUTPUT                                                                */
14971 /*                                                                        */
14972 /*    status                               0 if OK, nonzero on errors     */
14973 /*                                                                        */
14974 /*  CALLS                                                                 */
14975 /*                                                                        */
14976 /*    nx_dns_host_by_address_get           Get hostname by IPv4 address   */
14977 /*    nxd_dns_host_by_address_get          Get hostname by IPv6 address   */
14978 /*                                                                        */
14979 /*  CALLED BY                                                             */
14980 /*                                                                        */
14981 /*    Application Code                                                    */
14982 /*                                                                        */
14983 /*  RELEASE HISTORY                                                       */
14984 /*                                                                        */
14985 /*    DATE              NAME                      DESCRIPTION             */
14986 /*                                                                        */
14987 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
14988 /*  09-30-2020     Yuxin Zhou               Modified comment(s), and      */
14989 /*                                            verified memcpy use cases,  */
14990 /*                                            resulting in version 6.1    */
14991 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s), and      */
14992 /*                                            used new API/structs naming,*/
14993 /*                                            resulting in version 6.3.0  */
14994 /*                                                                        */
14995 /**************************************************************************/
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)14996 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)
14997 {
14998 
14999 UINT        i = 0;
15000 /* Flag used to identify whether host/service is numeric, 0 no, 1 yes. */
15001 UINT        numeric_flag;
15002 USHORT     *temp;
15003 #ifdef NX_BSD_ENABLE_DNS
15004 UINT        status;
15005 #ifdef FEATURE_NX_IPV6
15006 NXD_ADDRESS nxd_ipv6_addr;
15007 #endif
15008 #endif
15009 const CHAR  *rt_ptr;
15010 
15011     if(!sa)
15012     {
15013 
15014         /* sa is NULL. */
15015         return EAI_FAMILY;
15016     }
15017     else
15018     {
15019         if((sa -> sa_family != AF_INET)  &&
15020            (sa -> sa_family != AF_INET6))
15021         {
15022 
15023             /* sa isn't NULL, but family type is invalid. */
15024             return EAI_FAMILY;
15025         }
15026         else if((sa -> sa_family == AF_INET && salen != sizeof(struct nx_bsd_sockaddr_in)) ||
15027                 (sa -> sa_family == AF_INET6 && salen != sizeof(struct nx_bsd_sockaddr_in6)))
15028         {
15029 
15030             /* Address length is invalid. */
15031             return EAI_FAMILY;
15032         }
15033     }
15034 
15035     /* Both host and service null are invalid */
15036     if((host == NX_NULL) && (serv == NX_NULL) && ((flags & NI_NAMEREQD) == 0))
15037         return EAI_NONAME;
15038 
15039     if(serv && servlen > 0)
15040     {
15041         numeric_flag = 1;
15042 
15043         /* If NUMERICSERV bit is set, set to 1. */
15044         if(flags & NI_NUMERICSERV)
15045         {
15046             numeric_flag = 1;
15047         }
15048         else if(flags & NI_DGRAM)
15049         {
15050             /* Socket type must be SOCK_DGRAM. */
15051 
15052             for(i = 0; i < _nx_bsd_serv_list_len; i++)
15053             {
15054                 temp = (USHORT *)(sa -> sa_data);
15055                 if((_nx_bsd_serv_list_ptr[i].service_port == *temp) &&
15056                    (_nx_bsd_serv_list_ptr[i].service_socktype == SOCK_DGRAM))
15057                 {
15058 
15059                     /* Found a matched service, set numeric flag to 0. */
15060                     numeric_flag = 0;
15061                     break;
15062                 }
15063             }
15064         }
15065         else
15066         {
15067 
15068             /* Socket type is SOCK_STREAM. */
15069             for(i = 0; i < _nx_bsd_serv_list_len; i++)
15070             {
15071                 temp = (USHORT *)(sa -> sa_data);
15072                 if((_nx_bsd_serv_list_ptr[i].service_port == *temp) &&
15073                    (_nx_bsd_serv_list_ptr[i].service_socktype == SOCK_STREAM))
15074                 {
15075 
15076                     /* Found a matched service, set numeric flag to 0. */
15077                     numeric_flag = 0;
15078                     break;
15079                 }
15080             }
15081         }
15082 
15083         if(numeric_flag)
15084         {
15085 
15086             /* Service is numeric, copy the service port. Then convert host byte order to network byte order. */
15087             temp = (USHORT *)(sa -> sa_data);
15088             if(bsd_number_convert(htons(*temp), (CHAR *)serv, servlen, 10) == 0)
15089                 return EAI_OVERFLOW;
15090         }
15091         else
15092         {
15093 
15094             /* Service isn't numeric, copy the service name. */
15095             if(_nx_bsd_string_length(_nx_bsd_serv_list_ptr[i].service_name) > servlen)
15096                 return EAI_OVERFLOW;
15097 
15098             memcpy(serv, _nx_bsd_serv_list_ptr[i].service_name, /* Use case of memcpy is verified. */
15099                    _nx_bsd_string_length(_nx_bsd_serv_list_ptr[i].service_name));
15100         }
15101     }
15102 
15103     if(host && hostlen > 0)
15104     {
15105         numeric_flag = 1;
15106 
15107         /* If NUMERIC bit is set, set flag to 1. */
15108         if(flags & NI_NUMERICHOST)
15109             numeric_flag = 1;
15110         else
15111         {
15112 
15113 #ifdef NX_BSD_ENABLE_DNS
15114             if(sa -> sa_family == AF_INET)
15115             {
15116 
15117 #ifndef NX_DISABLE_IPV4
15118                 /* Get host name by IPv4 address via DNS. */
15119                 status = nx_dns_host_by_address_get(_nx_dns_instance_ptr, ntohl(((struct nx_bsd_sockaddr_in *)sa) -> sin_addr.s_addr),
15120                                                     (UCHAR *)host, hostlen, NX_BSD_TIMEOUT);
15121 #else
15122                 status = NX_DNS_NO_SERVER;
15123 #endif /* NX_DISABLE_IPV4 */
15124             }
15125             else
15126             {
15127 #ifdef FEATURE_NX_IPV6
15128                 /* copy data from sockaddr structure to NXD_ADDRESS structure. */
15129                 nxd_ipv6_addr.nxd_ip_version = NX_IP_VERSION_V6;
15130                 nxd_ipv6_addr.nxd_ip_address.v6[0] = ntohl(((struct nx_bsd_sockaddr_in6 *)sa) -> sin6_addr.s6_addr32[0]);
15131                 nxd_ipv6_addr.nxd_ip_address.v6[1] = ntohl(((struct nx_bsd_sockaddr_in6 *)sa) -> sin6_addr.s6_addr32[1]);
15132                 nxd_ipv6_addr.nxd_ip_address.v6[2] = ntohl(((struct nx_bsd_sockaddr_in6 *)sa) -> sin6_addr.s6_addr32[2]);
15133                 nxd_ipv6_addr.nxd_ip_address.v6[3] = ntohl(((struct nx_bsd_sockaddr_in6 *)sa) -> sin6_addr.s6_addr32[3]);
15134 
15135                 /* Get host name by IPv6 address via DNS. */
15136                 status = nxd_dns_host_by_address_get(_nx_dns_instance_ptr, &nxd_ipv6_addr,
15137                                                      (UCHAR *) host, hostlen, NX_BSD_TIMEOUT);
15138 #else
15139                 status = NX_DNS_NO_SERVER;
15140 #endif
15141             }
15142 
15143 
15144             if(status == NX_DNS_SIZE_ERROR)
15145                 return EAI_OVERFLOW;
15146             else if(status != NX_SUCCESS)
15147             {
15148 
15149                 /* DNS query fails. */
15150                 if(flags & NI_NAMEREQD)
15151                     return EAI_NONAME;
15152             }
15153             else
15154             {
15155 
15156                 /* DNS query succeeds. */
15157                 numeric_flag = 0;
15158             }
15159 #else
15160             if(flags & NI_NAMEREQD)
15161                 return EAI_NONAME;
15162 #endif
15163         }
15164 
15165         if(numeric_flag)
15166         {
15167 
15168             /* Host must be numeric string. Convert IP address from numeric to presentation. */
15169             if(sa -> sa_family == AF_INET)
15170                 rt_ptr = nx_bsd_inet_ntop(AF_INET, &((struct nx_bsd_sockaddr_in*)sa) -> sin_addr, (CHAR *)host, hostlen);
15171             else
15172                 rt_ptr = nx_bsd_inet_ntop(AF_INET6, &((struct nx_bsd_sockaddr_in6*)sa) -> sin6_addr, (CHAR *)host, hostlen);
15173 
15174             if(!rt_ptr)
15175                 return EAI_OVERFLOW;
15176         }
15177 
15178     }
15179 
15180     return 0;
15181 }
15182 
15183 /**************************************************************************/
15184 /*                                                                        */
15185 /*  FUNCTION                                               RELEASE        */
15186 /*                                                                        */
15187 /*    nx_bsd_set_service_list                             PORTABLE C      */
15188 /*                                                           6.1          */
15189 /*  AUTHOR                                                                */
15190 /*                                                                        */
15191 /*    Yuxin Zhou, Microsoft Corporation                                   */
15192 /*                                                                        */
15193 /*  DESCRIPTION                                                           */
15194 /*                                                                        */
15195 /*    This function lets user set the service list used by getaddrinfo    */
15196 /*                                                                        */
15197 /*  INPUT                                                                 */
15198 /*                                                                        */
15199 /*    serv_list_ptr                        Pointer to a service list      */
15200 /*    serv_list_len                        Service list length            */
15201 /*                                                                        */
15202 /*  OUTPUT                                                                */
15203 /*                                                                        */
15204 /*    None                                                                */
15205 /*                                                                        */
15206 /*  CALLS                                                                 */
15207 /*                                                                        */
15208 /*    None                                                                */
15209 /*                                                                        */
15210 /*  CALLED BY                                                             */
15211 /*                                                                        */
15212 /*    Application Code                                                    */
15213 /*                                                                        */
15214 /*  RELEASE HISTORY                                                       */
15215 /*                                                                        */
15216 /*    DATE              NAME                      DESCRIPTION             */
15217 /*                                                                        */
15218 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
15219 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
15220 /*                                            resulting in version 6.1    */
15221 /*                                                                        */
15222 /**************************************************************************/
nx_bsd_set_service_list(struct NX_BSD_SERVICE_LIST * serv_list_ptr,ULONG serv_list_len)15223 VOID nx_bsd_set_service_list(struct NX_BSD_SERVICE_LIST *serv_list_ptr, ULONG serv_list_len)
15224 {
15225     _nx_bsd_serv_list_ptr = serv_list_ptr;
15226     _nx_bsd_serv_list_len = serv_list_len;
15227 }
15228 
15229 
15230 /**************************************************************************/
15231 /*                                                                        */
15232 /*  FUNCTION                                               RELEASE        */
15233 /*                                                                        */
15234 /*    _nx_bsd_string_length                               PORTABLE C      */
15235 /*                                                           6.1          */
15236 /*  AUTHOR                                                                */
15237 /*                                                                        */
15238 /*    Yuxin Zhou, Microsoft Corporation                                   */
15239 /*                                                                        */
15240 /*  DESCRIPTION                                                           */
15241 /*                                                                        */
15242 /*    This function returns the length of string.                         */
15243 /*                                                                        */
15244 /*  INPUT                                                                 */
15245 /*                                                                        */
15246 /*    string                               Pointer to a string            */
15247 /*                                                                        */
15248 /*  OUTPUT                                                                */
15249 /*                                                                        */
15250 /*    ULONG                                String length                  */
15251 /*                                                                        */
15252 /*  CALLS                                                                 */
15253 /*                                                                        */
15254 /*    None                                                                */
15255 /*                                                                        */
15256 /*  CALLED BY                                                             */
15257 /*                                                                        */
15258 /*    NetX Duo BSD Layer Source Code                                      */
15259 /*                                                                        */
15260 /*  RELEASE HISTORY                                                       */
15261 /*                                                                        */
15262 /*    DATE              NAME                      DESCRIPTION             */
15263 /*                                                                        */
15264 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
15265 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
15266 /*                                            resulting in version 6.1    */
15267 /*                                                                        */
15268 /**************************************************************************/
_nx_bsd_string_length(CHAR * string)15269 static ULONG _nx_bsd_string_length(CHAR * string)
15270 {
15271 int length = 0;
15272 
15273     while(*string != '\0')
15274     {
15275         length++;
15276         string++;
15277     }
15278 
15279     return((ULONG)length);
15280 
15281 }
15282 
15283 
15284 /**************************************************************************/
15285 /*                                                                        */
15286 /*  FUNCTION                                               RELEASE        */
15287 /*                                                                        */
15288 /*    _nx_bsd_fast_periodic_timer_entry                   PORTABLE C      */
15289 /*                                                           6.1          */
15290 /*  AUTHOR                                                                */
15291 /*                                                                        */
15292 /*    Yuxin Zhou, Microsoft Corporation                                   */
15293 /*                                                                        */
15294 /*  DESCRIPTION                                                           */
15295 /*                                                                        */
15296 /*    This function handles BSD system clock. When the timer expires, the */
15297 /*    BSD system clock is updated and then default IP fast periodic entry */
15298 /*    routine is invoked.                                                 */
15299 /*                                                                        */
15300 /*  INPUT                                                                 */
15301 /*                                                                        */
15302 /*    id                                   Argument of default timer entry*/
15303 /*                                                                        */
15304 /*  OUTPUT                                                                */
15305 /*                                                                        */
15306 /*    None                                                                */
15307 /*                                                                        */
15308 /*  CALLS                                                                 */
15309 /*                                                                        */
15310 /*    None                                                                */
15311 /*                                                                        */
15312 /*  CALLED BY                                                             */
15313 /*                                                                        */
15314 /*    None                                                                */
15315 /*                                                                        */
15316 /*  RELEASE HISTORY                                                       */
15317 /*                                                                        */
15318 /*    DATE              NAME                      DESCRIPTION             */
15319 /*                                                                        */
15320 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
15321 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
15322 /*                                            resulting in version 6.1    */
15323 /*                                                                        */
15324 /**************************************************************************/
_nx_bsd_fast_periodic_timer_entry(ULONG id)15325 static VOID  _nx_bsd_fast_periodic_timer_entry(ULONG id)
15326 {
15327 
15328     /* Update the BSD system clock. */
15329     nx_bsd_system_clock += nx_bsd_timer_rate;
15330 
15331     /* Call default IP fast periodic timer entry. */
15332     nx_bsd_ip_fast_periodic_timer_entry(id);
15333 }
15334 
15335 
15336 /**************************************************************************/
15337 /*                                                                        */
15338 /*  FUNCTION                                               RELEASE        */
15339 /*                                                                        */
15340 /*    poll                                                PORTABLE C      */
15341 /*                                                           6.3.0        */
15342 /*  AUTHOR                                                                */
15343 /*                                                                        */
15344 /*    Chaoqiong Xiao, Microsoft Corporation                               */
15345 /*                                                                        */
15346 /*  DESCRIPTION                                                           */
15347 /*                                                                        */
15348 /*    This function allows for list of sockets to be checked for incoming */
15349 /*    events.                                                             */
15350 /*                                                                        */
15351 /*    Before invoked, each item inside fds array should be initialized,   */
15352 /*    pollfd::fd must be the descriptor ID to check and pollfd::events    */
15353 /*    must be the events (bits) to check.                                 */
15354 /*                                                                        */
15355 /*    Returned, the pollfd::revents of each item is updated, to indicate  */
15356 /*    if the checked events happen.                                       */
15357 /*                                                                        */
15358 /*    The event (bit) currently supported:                                */
15359 /*    - POLLIN : checking socket read FD                                  */
15360 /*    - POLLOUT: checking socket write FD                                 */
15361 /*    - POLLPRI: checking socket exception FD                             */
15362 /*                                                                        */
15363 /*    NOTE:  ****** When select returns NX_SOC_ERROR it won't update      */
15364 /*           the fds descriptor.                                          */
15365 /*                                                                        */
15366 /*  INPUT                                                                 */
15367 /*                                                                        */
15368 /*    fds                                  Socket descriptor list to poll */
15369 /*                                           and report actual status     */
15370 /*    nfds                                 Number of socket descriptors   */
15371 /*    timeOut                              Timeout in microseconds, set   */
15372 /*                                         to below 0 to wait infinitely  */
15373 /*                                                                        */
15374 /*  OUTPUT                                                                */
15375 /*                                                                        */
15376 /*    NX_SUCCESS                            Descriptors check ends        */
15377 /*                                           (successful completion)      */
15378 /*    NX_SOC_ERROR (-1)                     Error occured                 */
15379 /*                                                                        */
15380 /*  CALLS                                                                 */
15381 /*                                                                        */
15382 /*    FD_ZERO                               Clear a socket ready list     */
15383 /*    FD_ISSET                              Check a socket is ready       */
15384 /*    FD_SET                                Set a socket                  */
15385 /*    select                                Perform checks, see select()  */
15386 /*    set_errno                             Set the error code            */
15387 /*                                                                        */
15388 /*  CALLED BY                                                             */
15389 /*                                                                        */
15390 /*    Application Code                                                    */
15391 /*                                                                        */
15392 /*  RELEASE HISTORY                                                       */
15393 /*                                                                        */
15394 /*    DATE              NAME                      DESCRIPTION             */
15395 /*                                                                        */
15396 /*  10-31-2023     Chaoqiong Xiao           Initial Version 6.3.0         */
15397 /*                                                                        */
15398 /**************************************************************************/
nx_bsd_poll(struct nx_bsd_pollfd * fds,ULONG nfds,INT timeout)15399 INT  nx_bsd_poll(struct nx_bsd_pollfd *fds, ULONG nfds, INT timeout)
15400 {
15401 nx_bsd_fd_set           read_fds;
15402 nx_bsd_fd_set           write_fds;
15403 nx_bsd_fd_set           except_fds;
15404 struct nx_bsd_timeval   stime;
15405 struct nx_bsd_timeval   *ptime;
15406 INT                     n_ready_fds;
15407 INT                     max_fd;
15408 ULONG                   i;
15409 struct nx_bsd_pollfd    *poll_fd;
15410 
15411     /* Check input parameter.  */
15412     if (fds == NX_NULL)
15413     {
15414         nx_bsd_set_errno(EFAULT);
15415         return(NX_SOC_ERROR);
15416     }
15417     if (nfds == 0)
15418     {
15419         nx_bsd_set_errno(EFAULT);
15420         return(NX_SOC_ERROR);
15421     }
15422 
15423     /* Initialize local FDs.  */
15424     NX_BSD_FD_ZERO(&read_fds);
15425     NX_BSD_FD_ZERO(&write_fds);
15426     NX_BSD_FD_ZERO(&except_fds);
15427 
15428     /* Map the poll() FD to select() FDs.  */
15429     max_fd = 0;
15430     for(i = 0; i < nfds; i ++)
15431     {
15432         poll_fd = &fds[i];
15433 
15434         /* Skip bad FDs.  */
15435         if (poll_fd -> fd < 0)
15436             continue;
15437 
15438         /* POLLIN.  */
15439         if (poll_fd -> events & POLLIN)
15440         {
15441             NX_BSD_FD_SET(poll_fd -> fd, &read_fds);
15442         }
15443 
15444         /* POLLOUT.  */
15445         if (poll_fd -> events & POLLOUT)
15446         {
15447             NX_BSD_FD_SET(poll_fd -> fd, &write_fds);
15448         }
15449 
15450         /* POLLPRI.  */
15451         if (poll_fd -> events & POLLPRI)
15452         {
15453             NX_BSD_FD_SET(poll_fd -> fd, &except_fds);
15454         }
15455 
15456         /* Update max FD.  */
15457         if (poll_fd -> fd > max_fd)
15458             max_fd = poll_fd -> fd;
15459     }
15460 
15461     /* Map the select() timeout.  */
15462     if (timeout < 0)
15463     {
15464 
15465         /* select() wait infinitely.  */
15466         ptime = NX_NULL;
15467     }
15468     else
15469     {
15470 
15471         /* select() uses timeval option.  */
15472         ptime = &stime;
15473 
15474         if (timeout == 0)
15475         {
15476 
15477             /* select() no wait.  */
15478             ptime -> tv_sec = 0;
15479             ptime -> tv_usec = 0;
15480         }
15481         else
15482         {
15483 
15484             /* select() wait specific time in ms.  */
15485             ptime -> tv_sec = (timeout / 1000);
15486             ptime -> tv_usec = (timeout % 1000);
15487         }
15488 
15489     }
15490 
15491     /* Invoke select().  */
15492     n_ready_fds = nx_bsd_select(max_fd + 1, &read_fds, &write_fds, &except_fds, ptime);
15493 
15494     /* Parse result events if FDs updated.  */
15495     if (n_ready_fds)
15496     {
15497 
15498         for (i = 0; i < nfds; i ++)
15499         {
15500             poll_fd = &fds[i];
15501 
15502             /* Skip bad FDs.  */
15503             if (poll_fd -> fd < 0)
15504                 continue;
15505 
15506             /* Exceptions.  */
15507             if (NX_BSD_FD_ISSET(poll_fd -> fd, &except_fds))
15508                 poll_fd -> revents |= POLLPRI;
15509 
15510             else
15511             {
15512 
15513                 /* Inputs.  */
15514                 if (NX_BSD_FD_ISSET(poll_fd -> fd, &read_fds))
15515                     poll_fd -> revents |= POLLIN;
15516             }
15517 
15518             /* Outputs.  */
15519             if (NX_BSD_FD_ISSET(poll_fd -> fd, &write_fds))
15520                 poll_fd -> revents |= POLLOUT;
15521         }
15522     }
15523 
15524     return(n_ready_fds);
15525 }
15526