1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** BSD 4.3 Socket API Compatible Interface to NetX Duo */
16 /** */
17 /**************************************************************************/
18 /**************************************************************************/
19
20
21 /* Include necessary files. */
22 #include "nx_api.h"
23 #include "nx_packet.h"
24 #include "nx_tcp.h"
25 #include "nx_ip.h"
26
27 #include "nx_ipv6.h"
28 #include "nx_ipv4.h"
29 #include "nxd_bsd.h"
30
31 #ifdef NX_BSD_ENABLE_DNS
32 #include "nxd_dns.h"
33 #endif
34
35
36 #include "nx_udp.h"
37 #include "nx_igmp.h"
38 #include "nx_system.h"
39 #ifdef FEATURE_NX_IPV6
40 #include "nx_icmpv6.h"
41 #endif
42 #include "tx_timer.h"
43
44 /* Define a NetX packet pool pointer for BSD use. */
45
46 NX_PACKET_POOL *nx_bsd_default_packet_pool;
47
48
49 /* Define the default IP instance for BSD use. */
50
51 NX_IP *nx_bsd_default_ip;
52
53
54 /* Define the single mutex protection for the BSD layer calls. */
55
56 TX_MUTEX *nx_bsd_protection_ptr;
57
58
59 /* Define IP fast periodic timer entry. */
60 VOID (*nx_bsd_ip_fast_periodic_timer_entry)(ULONG id);
61
62 /* Define BSD system clock time. The precision depends on _nx_ip_fast_timer_rate. */
63 ULONG nx_bsd_system_clock;
64
65 /* Define BSD system clock timer rate. */
66 ULONG nx_bsd_timer_rate;
67
68 /* Define the event flag group for notifying threads suspended on BSD sockets to wakeup. */
69
70 TX_EVENT_FLAGS_GROUP nx_bsd_events;
71
72
73 /* Define the array of BSD managed sockets. */
74
75 NX_BSD_SOCKET nx_bsd_socket_array[NX_BSD_MAX_SOCKETS];
76
77 /* Define the raw socket protocol hash table. */
78
79 NX_BSD_SOCKET *nx_bsd_socket_raw_protocol_table[NX_BSD_SOCKET_RAW_PROTOCOL_TABLE_SIZE];
80
81 /* Create some buffer space for number string conversions. */
82 #define NX_BSD_URL_BUFSIZE 18
83 CHAR nx_bsd_url_buffer[NX_BSD_URL_BUFSIZE];
84
85 /* Define the search index for the BSD array. */
86
87 UINT nx_bsd_socket_array_index;
88
89
90 /* Define the block pool that will be used to dynamically allocate either NetX UDP or TCP sockets. */
91
92 TX_BLOCK_POOL nx_bsd_socket_block_pool;
93
94 /* Define the memory area for the socket block pool... use TCP socket size, since it is the larger. */
95
96 static ULONG nx_bsd_socket_pool_memory[NX_BSD_MAX_SOCKETS * (sizeof(NX_TCP_SOCKET) + sizeof(VOID *)) / sizeof(ULONG)];
97
98 /* Define the block pool that will be used to dynamically allocate addrinfo struct. */
99
100 TX_BLOCK_POOL nx_bsd_addrinfo_block_pool;
101
102 /* Define the memory area for addrinfo pool. sizeof(addrinfo) is the MAX of:
103 * {sizeof(addrinfo)== 32, sizeof(sockaddr_in) == 16, or sizeof(sockaddr_in6)} = 28.
104 * Every address may be mapped to 3 socktypes, SOCK_STREAM, SOCK_DGRAM and SOCK_RAW,
105 * 3 blocks for addrinfo) + 1 block for IP adddress = 4 blocks */
106
107 static ULONG nx_bsd_addrinfo_pool_memory[(NX_BSD_IPV4_ADDR_MAX_NUM + NX_BSD_IPV6_ADDR_MAX_NUM) * 4
108 *(sizeof(struct nx_bsd_addrinfo) + sizeof(VOID *)) / sizeof(ULONG)];
109
110 #ifdef NX_BSD_ENABLE_DNS
111
112 /* The global DNS client instance. */
113 extern NX_DNS *_nx_dns_instance_ptr;
114
115 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
116 /* Define the block pool that will be used to dynamically allocate canonical name buffer. */
117 TX_BLOCK_POOL nx_bsd_cname_block_pool;
118
119 /* Here we just support a CNAME per IP address. */
120 static ULONG nx_bsd_cname_pool_memory[(NX_BSD_IPV4_ADDR_MAX_NUM + NX_BSD_IPV6_ADDR_MAX_NUM) *
121 (NX_DNS_NAME_MAX + 1) / sizeof(ULONG)];
122 #endif /* NX_DNS_ENABLE_EXTENDED_RR_TYPES */
123 #endif /* NX_BSD_ENABLE_DNS */
124
125 /* Buffer used to store IP address get from DNS. */
126 static ULONG nx_bsd_ipv4_addr_buffer[NX_BSD_IPV4_ADDR_PER_HOST];
127 static ULONG nx_bsd_ipv6_addr_buffer[NX_BSD_IPV6_ADDR_PER_HOST * 4];
128
129 /* Utility character type functions*/
130 static UINT nx_bsd_isspace(UCHAR c);
131 static UINT nx_bsd_islower(UCHAR c);
132 static UINT nx_bsd_isdigit(UCHAR c);
133 static UINT nx_bsd_isxdigit(UCHAR c);
134
135 /* Standard BSD callback functions to register with NetX Duo. */
136
137 static VOID nx_bsd_tcp_receive_notify(NX_TCP_SOCKET *socket_ptr);
138 static VOID nx_bsd_tcp_socket_disconnect_notify(NX_TCP_SOCKET *socket_ptr);
139 static VOID nx_bsd_udp_receive_notify(NX_UDP_SOCKET *socket_ptr);
140 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
141 static UINT nx_bsd_raw_packet_filter(NX_IP *ip_ptr, ULONG protocol, NX_PACKET *packet_ptr);
142 #ifdef FEATURE_NX_IPV6
143 static VOID _nxd_bsd_swap_ipv6_extension_headers(NX_PACKET *packet_ptr, UCHAR header_type);
144 #endif /* FEATURE_NX_IPV6 */
145 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
146 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
147 static VOID nx_bsd_tcp_establish_notify(NX_TCP_SOCKET *socket_ptr);
148 #endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */
149 static VOID nx_bsd_select_wakeup(UINT sock_id, UINT fdsets);
150 static VOID nx_bsd_set_error_code(NX_BSD_SOCKET *bsd_socket_ptr, UINT status_code);
151 static VOID nx_bsd_udp_packet_received(INT sockID, NX_PACKET *packet_ptr);
152 static UINT nx_bsd_tcp_syn_received_notify(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr);
153 static INT nx_bsd_tcp_create_listen_socket(INT master_sockid, INT backlog);
154 static VOID nx_bsd_tcp_pending_connection(UINT local_port, NX_TCP_SOCKET *socket_ptr);
155 static INT nx_bsd_find_interface_by_source_addr(UINT addr_family, ULONG* ip_addr);
156 #ifndef NX_DISABLE_IPV4
157 static VOID _nxd_bsd_ipv4_packet_send(NX_PACKET *packet_ptr);
158 #endif /* NX_DISABLE_IPV4 */
159 static INT nx_bsd_send_internal(INT sockID, const CHAR *msg, INT msgLength, INT flags,
160 NXD_ADDRESS *dst_address, USHORT dst_port, UINT local_interface_index);
161
162 #ifdef FEATURE_NX_IPV6
163 static VOID _nxd_bsd_ipv6_packet_send(NX_PACKET *packet_ptr, ULONG *src_addr, ULONG *dest_addr);
164 #endif /* FEATURE_NX_IPV6 */
165
166 static INT inet_ntoa_internal(const VOID *src, CHAR *dst, ULONG dst_size);
167 static INT bsd_string_to_number(const CHAR *string, UINT *number);
168 static ULONG _nx_bsd_string_length(CHAR * string);
169
170 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
171 static INT nx_bsd_pppoe_internal_sendto(NX_BSD_SOCKET *bsd_socket_ptr, CHAR *msg, INT msgLength,
172 INT flags, struct nx_bsd_sockaddr* destAddr, INT destAddrLen);
173 static UINT nx_bsd_socket_create_id = 0;
174 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
175
176 #ifdef NX_BSD_RAW_SUPPORT
177 static INT _nx_bsd_hardware_internal_sendto(NX_BSD_SOCKET *bsd_socket_ptr, CHAR *msg, INT msgLength,
178 INT flags, struct nx_bsd_sockaddr* destAddr, INT destAddrLen);
179 static VOID _nx_bsd_hardware_packet_received(NX_PACKET *packet_ptr, UCHAR *consumed);
180 #endif /* NX_BSD_RAW_SUPPORT */
181 static VOID _nx_bsd_fast_periodic_timer_entry(ULONG id);
182
183 #ifndef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
184 TX_THREAD nx_bsd_task_thread;
185 static VOID nx_bsd_thread_entry(ULONG info);
186 #else
187 static TX_TIMER nx_bsd_timer;
188 static VOID nx_bsd_timer_entry(ULONG info);
189 #endif
190 UINT bsd_number_convert(UINT number, CHAR *string, ULONG buffer_len, UINT base);
191 VOID nx_bsd_socket_timed_wait_callback(NX_TCP_SOCKET *tcp_socket_ptr);
192
193 #define FDSET_READ 1
194 #define FDSET_WRITE 2
195 #define FDSET_EXCEPTION 4
196
197 extern TX_THREAD *_tx_thread_current_ptr;
198
199 static ULONG _nx_bsd_serv_list_len;
200 static struct NX_BSD_SERVICE_LIST *_nx_bsd_serv_list_ptr;
201
202
203 /**************************************************************************/
204 /* */
205 /* FUNCTION RELEASE */
206 /* */
207 /* bsd_initialize PORTABLE C */
208 /* 6.3.0 */
209 /* AUTHOR */
210 /* */
211 /* Yuxin Zhou, Microsoft Corporation */
212 /* */
213 /* DESCRIPTION */
214 /* */
215 /* This function sets up all data structures and NetX, and ThreadX */
216 /* resources needed by the BSD compatibility layer. It is recommended */
217 /* to call this routine from tx_application_define. */
218 /* */
219 /* INPUTS */
220 /* */
221 /* *default_ip NX_IP created for BSD API */
222 /* *default_pool Packet Pool used by BSD API */
223 /* *bsd_thread_stack_area Stack memory pointer for the */
224 /* BSD thread stack space */
225 /* bsd_thread_stack_size Size of thread stack */
226 /* bsd_thread_priority BSD thread priority */
227 /* */
228 /* OUTPUT */
229 /* */
230 /* NX_SUCCESS Successful completion */
231 /* NX_BSD_BLOCK_POOL_ERROR Error creating socket block */
232 /* pool */
233 /* NX_BSD_EVENT_ERROR Error creating the event flag */
234 /* group */
235 /* NX_BSD_MUTEX_ERROR Error creating mutex */
236 /* NX_BSD_ENVIRONMENT_ERROR Error environment */
237 /* */
238 /* CALLS */
239 /* */
240 /* memset Set memory */
241 /* tx_block_pool_create Create a block pool */
242 /* tx_block_pool_delete Delete a block pool */
243 /* tx_event_flags_create Create event flag group */
244 /* tx_mutex_create Create protection mutex */
245 /* tx_mutex_delete Delete protection mutex */
246 /* */
247 /* CALLED BY */
248 /* */
249 /* Start-up code */
250 /* */
251 /* RELEASE HISTORY */
252 /* */
253 /* DATE NAME DESCRIPTION */
254 /* */
255 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
256 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
257 /* resulting in version 6.1 */
258 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
259 /* used new API/structs naming,*/
260 /* resulting in version 6.3.0 */
261 /* */
262 /**************************************************************************/
nx_bsd_initialize(NX_IP * default_ip,NX_PACKET_POOL * default_pool,CHAR * bsd_thread_stack_area,ULONG bsd_thread_stack_size,UINT bsd_thread_priority)263 INT nx_bsd_initialize(NX_IP *default_ip, NX_PACKET_POOL *default_pool, CHAR *bsd_thread_stack_area,
264 ULONG bsd_thread_stack_size, UINT bsd_thread_priority)
265 {
266
267 INT i;
268 UINT status;
269 ULONG info;
270
271 #ifndef NX_ENABLE_EXTENDED_NOTIFY_SUPPORT
272
273 /* Error, return the error message. */
274 /* BSD doesn't work with out NX_ENABLE_EXTENDED_NOTIFY_SUPPORT option. */
275 NX_BSD_ERROR(NX_BSD_ENVIRONMENT_ERROR, __LINE__);
276 return(NX_BSD_ENVIRONMENT_ERROR);
277 #endif /* NX_ENABLE_EXTENDED_NOTIFY_SUPPORT */
278
279 /* Create a block pool for dynamically allocating sockets. */
280 status = tx_block_pool_create(&nx_bsd_socket_block_pool, "NetX BSD Socket Block Pool", sizeof(NX_TCP_SOCKET),
281 nx_bsd_socket_pool_memory, sizeof(nx_bsd_socket_pool_memory));
282
283 /* Determine if the pool was created. */
284 if (status)
285 {
286
287 /* Error, return the error message. */
288 NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
289 return(NX_BSD_BLOCK_POOL_ERROR);
290 }
291
292 /* Create a block pool for dynamically allocating addrinfo. */
293 status = tx_block_pool_create(&nx_bsd_addrinfo_block_pool, "NetX BSD Addrinfo Block Pool", sizeof(struct nx_bsd_addrinfo),
294 nx_bsd_addrinfo_pool_memory, sizeof(nx_bsd_addrinfo_pool_memory));
295
296 /* Determine if the pool was created. */
297 if(status)
298 {
299
300 /* Error, return the error messafe. */
301 NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
302
303 /* Delete the block pool. */
304 tx_block_pool_delete(&nx_bsd_socket_block_pool);
305 return(NX_BSD_BLOCK_POOL_ERROR);
306
307 }
308
309 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
310 /* Create a block pool for dynamically allocating canonical name buffer. */
311 status = tx_block_pool_create(&nx_bsd_cname_block_pool, "NetX BSD CNAME Block Pool", (NX_DNS_NAME_MAX + 1),
312 nx_bsd_cname_pool_memory, sizeof(nx_bsd_cname_pool_memory));
313
314 /* Determine if the pool was created. */
315 if(status)
316 {
317
318 /* Error, return the error messafe. */
319 NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
320
321 /* Delete the block pool. */
322 tx_block_pool_delete(&nx_bsd_socket_block_pool);
323 tx_block_pool_delete(&nx_bsd_addrinfo_block_pool);
324 return(NX_BSD_BLOCK_POOL_ERROR);
325
326 }
327 #endif
328
329 nx_bsd_protection_ptr = &default_ip -> nx_ip_protection;
330
331 /* Create the BSD event flag group. */
332 status = tx_event_flags_create(&nx_bsd_events, "NetX BSD Events");
333
334 /* Check the return status. */
335 if (status)
336 {
337 /* Delete the block pool. */
338 tx_block_pool_delete(&nx_bsd_socket_block_pool);
339 tx_block_pool_delete(&nx_bsd_addrinfo_block_pool);
340 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
341 tx_block_pool_delete(&nx_bsd_cname_block_pool);
342 #endif
343
344 /* Error present, return error code. */
345 NX_BSD_ERROR(NX_BSD_EVENT_ERROR, __LINE__);
346 return(NX_BSD_EVENT_ERROR);
347 }
348
349 /* Set the array index to 0. */
350 nx_bsd_socket_array_index = 0;
351
352 /* Loop through the BSD socket array and clear it out! */
353 for (i = 0; i < NX_BSD_MAX_SOCKETS; i++)
354 {
355
356 /* Clear the BSD socket structure. */
357 memset((VOID*) &nx_bsd_socket_array[i], 0, sizeof(NX_BSD_SOCKET));
358 }
359
360 /* Save the IP instance and NX_PACKET_POOL for BSD Socket API. */
361 nx_bsd_default_ip = default_ip;
362 nx_bsd_default_packet_pool = default_pool;
363
364
365 if ((bsd_thread_stack_area == TX_NULL) || (bsd_thread_stack_size == 0))
366 {
367 /* Return error. */
368 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
369 return(NX_SOC_ERROR);
370 }
371
372 #ifndef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
373 /* Create a thread for BSD socket features requiring periodic tasks. */
374 info = 0 ;
375 status = tx_thread_create(&nx_bsd_task_thread, "BSD thread task", nx_bsd_thread_entry, info,
376 bsd_thread_stack_area, bsd_thread_stack_size, bsd_thread_priority,
377 bsd_thread_priority, 1, TX_AUTO_START);
378
379 if (status != TX_SUCCESS)
380 {
381 /* Delete the event flag group. */
382 tx_event_flags_delete(&nx_bsd_events);
383
384 /* Delete the block pool. */
385 tx_block_pool_delete(&nx_bsd_socket_block_pool);
386 tx_block_pool_delete(&nx_bsd_addrinfo_block_pool);
387 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
388 tx_block_pool_delete(&nx_bsd_cname_block_pool);
389 #endif
390
391 /* Error, return the error message. */
392 NX_BSD_ERROR(NX_BSD_THREAD_ERROR, __LINE__);
393
394 /* Return an error. */
395 return(NX_IP_INTERNAL_ERROR);
396 }
397 #else
398
399 info = 0 ;
400
401 /* Create a one shot timer. Do not activate it. We will use it if
402 a socket being disconnected is NOT enabled for REUSEADDR socket option. */
403 status = tx_timer_create(&nx_bsd_timer, "BSD Timer",
404 nx_bsd_timer_entry, info,
405 NX_BSD_TIMER_RATE, NX_BSD_TIMER_RATE, TX_AUTO_START);
406
407 if (status != TX_SUCCESS)
408 {
409
410 /* Delete the event flag group. */
411 tx_event_flags_delete(&nx_bsd_events);
412
413 /* Delete the block pool. */
414 tx_block_pool_delete(&nx_bsd_socket_block_pool);
415 tx_block_pool_delete(&nx_bsd_addrinfo_block_pool);
416 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
417 tx_block_pool_delete(&nx_bsd_cname_block_pool);
418 #endif
419
420 #ifndef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
421 /* Delete the thread. */
422 tx_thread_delete(&nx_bsd_task_thread);
423 #endif
424 /* Error, return the error message. */
425 NX_BSD_ERROR(NX_BSD_THREAD_ERROR, __LINE__);
426
427 /* Return an error. */
428 return(NX_IP_INTERNAL_ERROR);
429 }
430 #endif
431
432 #ifdef NX_BSD_RAW_SUPPORT
433 _nx_driver_hardware_packet_received_callback = _nx_bsd_hardware_packet_received;
434 #endif /* NX_BSD_RAW_SUPPORT */
435
436 /* Calculate BSD system timer rate. */
437 nx_bsd_timer_rate = (NX_IP_PERIODIC_RATE + (NX_IP_FAST_TIMER_RATE - 1)) / NX_IP_FAST_TIMER_RATE;
438
439 /* Return success! */
440 return(NX_SOC_OK);
441 }
442
443
444 /**************************************************************************/
445 /* */
446 /* FUNCTION RELEASE */
447 /* */
448 /* nx_bsd_timeout_process PORTABLE C */
449 /* 6.1 */
450 /* AUTHOR */
451 /* */
452 /* Yuxin Zhou, Microsoft Corporation */
453 /* */
454 /* DESCRIPTION */
455 /* */
456 /* This function checks for sockets waiting to make a TCP connection. */
457 /* */
458 /* INPUT */
459 /* */
460 /* None */
461 /* */
462 /* OUTPUT */
463 /* */
464 /* None */
465 /* */
466 /* CALLS */
467 /* */
468 /* tx_mutex_get Obtain exclusive access to */
469 /* tx_mutex_put Release exclusive access */
470 /* nx_tcp_server_socket_unaccept Remove socket from listen list */
471 /* nx_tcp_server_socket_relisten Restore socket to listening */
472 /* nx_tcp_server_socket_accept Accept to connection request */
473 /* */
474 /* CALLED BY */
475 /* */
476 /* ThreadX */
477 /* */
478 /* RELEASE HISTORY */
479 /* */
480 /* DATE NAME DESCRIPTION */
481 /* */
482 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
483 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
484 /* resulting in version 6.1 */
485 /* */
486 /**************************************************************************/
nx_bsd_timeout_process()487 static VOID nx_bsd_timeout_process()
488 {
489
490 INT i;
491 ULONG status;
492 INT master_socket_index;
493 NX_BSD_SOCKET *bsd_socket_ptr;
494
495
496 /* Obtain the BSD lock. */
497 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
498
499 if(status)
500 {
501 /* Mutex operation failed. This should be fatal. */
502 return;
503 }
504
505 for( i = 0; i < NX_BSD_MAX_SOCKETS; i++)
506 {
507
508 /* Skip the unused sockets. */
509 if(!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
510 {
511
512 continue;
513 }
514
515 /* Skip if it is not TCP server socket. */
516 if((nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket == NX_NULL) ||
517 ((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CLIENT)))
518 {
519 continue;
520 }
521
522 /* Check for sockets trying to make a TCP connection.
523 Detect that the socket state is CLOSED, which is an indication
524 that the attempted connection failed, and we shall signal any pending
525 select on the socket. */
526 if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_INPROGRESS)
527 {
528
529 /* Is the NetX socket closed? */
530 if(nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket -> nx_tcp_socket_state == NX_TCP_CLOSED)
531 {
532
533 /* Yes. Set up a local pointer to the BSD socket. */
534 bsd_socket_ptr = &nx_bsd_socket_array[i];
535
536 /* Is this a secondary socket (passive open)? */
537 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET)
538 {
539
540 /* Yes; Is the socket is connected yet? */
541 if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED))
542 {
543
544 /* No; Turn off the disconnection_request flag. */
545 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_DISCONNECTION_REQUEST);
546
547 /* Remove the underlying NetX socket from the listen state. */
548 nx_tcp_server_socket_unaccept(bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
549
550 /* Check if a listen request is queued up for this socket. */
551 nx_bsd_tcp_pending_connection(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port,
552 bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
553
554 /* Relisten on this socket. */
555 status = nx_tcp_server_socket_relisten(nx_bsd_default_ip,
556 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port,
557 bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
558 /* Set the socket to accept the connection. */
559 nx_tcp_server_socket_accept(bsd_socket_ptr -> nx_bsd_socket_tcp_socket, NX_NO_WAIT);
560
561 /* Check the result of the relisten call. */
562 if(status == NX_CONNECTION_PENDING)
563 {
564
565 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
566 }
567 else if(status != NX_SUCCESS)
568 {
569
570
571 /* Failed the relisten on the secondary socket. Set the error code on the
572 master socket, and wake it up. */
573
574 master_socket_index = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id;
575
576 nx_bsd_socket_array[master_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
577 nx_bsd_set_error_code(&nx_bsd_socket_array[master_socket_index], status);
578
579 nx_bsd_select_wakeup((UINT)master_socket_index, (FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION));
580 }
581 }
582 }
583 else
584 {
585 /* The underlying socket is closed. This indicates an error, and since is a non-blocking
586 socket, we need to wake up the corresponding thread. */
587
588 /* Mark this socket as error, and remove the CONNECT and INPROGRESS flags */
589 nx_bsd_socket_array[i].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
590 nx_bsd_socket_array[i].nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
591 nx_bsd_socket_array[i].nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTED);
592 nx_bsd_socket_array[i].nx_bsd_socket_error_code = ECONNREFUSED;
593
594 /* Wake up the socket that could be listening on it. */
595 /* Notice that on error the both read and write are selectable. */
596 nx_bsd_select_wakeup((UINT)i, FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION);
597 }
598 }
599 }
600 }
601
602 /* Release the mutex. */
603 tx_mutex_put(nx_bsd_protection_ptr);
604 }
605
606 /**************************************************************************/
607 /* */
608 /* FUNCTION RELEASE */
609 /* */
610 /* nx_bsd_thread_entry PORTABLE C */
611 /* 6.1 */
612 /* AUTHOR */
613 /* */
614 /* Yuxin Zhou, Microsoft Corporation */
615 /* */
616 /* DESCRIPTION */
617 /* */
618 /* This function checks for events indicating BSD TCP socket tasks are */
619 /* waiting to be performed. */
620 /* */
621 /* INPUT */
622 /* */
623 /* None */
624 /* */
625 /* OUTPUT */
626 /* */
627 /* None */
628 /* */
629 /* CALLS */
630 /* */
631 /* tx_event_flags_get Check for registered events */
632 /* nx_bsd_timeout_process Process BSD tasks */
633 /* */
634 /* CALLED BY */
635 /* */
636 /* ThreadX */
637 /* */
638 /* RELEASE HISTORY */
639 /* */
640 /* DATE NAME DESCRIPTION */
641 /* */
642 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
643 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
644 /* resulting in version 6.1 */
645 /* */
646 /**************************************************************************/
647
648 #ifndef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
nx_bsd_thread_entry(ULONG info)649 VOID nx_bsd_thread_entry(ULONG info)
650 {
651 NX_PARAMETER_NOT_USED(info);
652
653 while(1)
654 {
655
656 /* Wait for timeout. */
657 tx_thread_sleep(NX_BSD_TIMER_RATE);
658
659 /* Timeout process. */
660 nx_bsd_timeout_process();
661 }
662 }
663 #endif
664
665 /**************************************************************************/
666 /* */
667 /* FUNCTION RELEASE */
668 /* */
669 /* socket PORTABLE C */
670 /* 6.3.0 */
671 /* AUTHOR */
672 /* */
673 /* Yuxin Zhou, Microsoft Corporation */
674 /* */
675 /* DESCRIPTION */
676 /* */
677 /* Creates a TCP or UDP socket, which may then be used as an end point */
678 /* of communication for sending and receiving data using the specified */
679 /* protocol. */
680 /* */
681 /* INPUT */
682 /* */
683 /* protocolFamily Protocol family e.g AF_INET */
684 /* type Type of the socket TCP or UDP */
685 /* protocol Socket protocol */
686 /* */
687 /* OUTPUT */
688 /* */
689 /* socket descriptor On success */
690 /* NX_SOC_ERROR (-1) On failure */
691 /* */
692 /* CALLS */
693 /* */
694 /* memset Clears memory */
695 /* nx_tcp_socket_create Create TCP BSD Socket */
696 /* nx_udp_socket_create Create UDP BSD Socket */
697 /* nx_tcp_socket_receive_notify TCP receive notify function */
698 /* nx_udp_socket_receive_notify UDP receive notify function */
699 /* tx_block_allocate Allocate socket memory */
700 /* tx_block_release Release socket memory */
701 /* tx_mutex_get Get protection */
702 /* tx_mutex_put Release protection */
703 /* */
704 /* CALLED BY */
705 /* */
706 /* Application Code */
707 /* */
708 /* RELEASE HISTORY */
709 /* */
710 /* DATE NAME DESCRIPTION */
711 /* */
712 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
713 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
714 /* resulting in version 6.1 */
715 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
716 /* used new API/structs naming,*/
717 /* resulting in version 6.3.0 */
718 /* */
719 /**************************************************************************/
nx_bsd_socket(INT protocolFamily,INT type,INT protocol)720 INT nx_bsd_socket(INT protocolFamily, INT type, INT protocol)
721 {
722
723 INT i;
724 UINT status;
725 NX_TCP_SOCKET *tcp_socket_ptr;
726 NX_UDP_SOCKET *udp_socket_ptr;
727 VOID *socket_memory = NX_NULL;
728 NX_BSD_SOCKET *bsd_socket_ptr;
729
730 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
731 UINT index;
732 #else
733
734 NX_PARAMETER_NOT_USED(protocol);
735 #endif
736
737 /* Check for a supported protocol family. */
738 #ifndef NX_DISABLE_IPV4
739 if (protocolFamily == AF_INET)
740 {
741 }
742 else
743 #endif /* NX_DISABLE_IPV4 */
744 #ifdef FEATURE_NX_IPV6
745 if (protocolFamily == AF_INET6)
746 {
747 }
748 else
749 #endif /* FEATURE_NX_IPV6 */
750 #if defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)
751 if (protocolFamily == AF_PACKET)
752 {
753 }
754 else
755 #endif /* defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT) */
756 {
757
758 /* Set the socket error. */
759 nx_bsd_set_errno(EAFNOSUPPORT);
760
761 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
762 return(NX_SOC_ERROR);
763 }
764
765 /* Check for a supported socket type. */
766 #if defined(NX_ENABLE_IP_RAW_PACKET_FILTER) || defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT)
767 if ((type != SOCK_STREAM) && (type != SOCK_DGRAM) && (type != SOCK_RAW))
768 #else
769 if ((type != SOCK_STREAM) && (type != SOCK_DGRAM))
770 #endif
771 {
772
773 /* Set the socket error. */
774 nx_bsd_set_errno(EPROTOTYPE);
775
776 /* Invalid type. */
777 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
778 return(NX_SOC_ERROR);
779 }
780
781 #if defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)
782 /* An extra check when BSD RAW Packet type is enabled:
783 Only RAW_SOCKET type is supported in AF_PACKET family. */
784 if((protocolFamily == AF_PACKET) && (type != SOCK_RAW))
785 {
786 /* Set the socket error. */
787 nx_bsd_set_errno(EPROTOTYPE);
788
789 /* Invalid type. */
790 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
791 return(NX_SOC_ERROR);
792 }
793 #endif /* defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT) */
794
795
796 /* Obtain the BSD protection socket. */
797 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
798
799 /* Check the status. */
800 if (status)
801 {
802
803 /* Set the socket error. */
804 nx_bsd_set_errno(EACCES);
805
806 /* Error getting the protection mutex. */
807 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
808 return(NX_SOC_ERROR);
809 }
810
811 /* Check whether IP fast timer is created or not. */
812 if ((nx_bsd_ip_fast_periodic_timer_entry == NX_NULL) ||
813 (nx_bsd_default_ip -> nx_ip_fast_periodic_timer.tx_timer_internal.tx_timer_internal_timeout_function != _nx_bsd_fast_periodic_timer_entry))
814 {
815
816 /* BSD socket requires a fast periodic timer to calculate wait option in recv() function. */
817 /* Create IP fast periodic timer. */
818 _nx_ip_fast_periodic_timer_create(nx_bsd_default_ip);
819
820 /* Replace timer expiration function entry. */
821 nx_bsd_ip_fast_periodic_timer_entry = nx_bsd_default_ip -> nx_ip_fast_periodic_timer.tx_timer_internal.tx_timer_internal_timeout_function;
822 nx_bsd_default_ip -> nx_ip_fast_periodic_timer.tx_timer_internal.tx_timer_internal_timeout_function = _nx_bsd_fast_periodic_timer_entry;
823 }
824
825 /* Now find a free slot in the BSD socket array. */
826 for (i = 0; i < NX_BSD_MAX_SOCKETS; i++)
827 {
828
829 /* See if this entry is available. Check the in use flag. */
830 if (!(nx_bsd_socket_array[nx_bsd_socket_array_index].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
831 {
832
833 /* Yes, Ok to use this socket. */
834
835 /* Clear the entire structure. */
836 memset((VOID*) &nx_bsd_socket_array[nx_bsd_socket_array_index], 0, sizeof(NX_BSD_SOCKET));
837 nx_bsd_socket_array[nx_bsd_socket_array_index].nx_bsd_socket_id = (INT)nx_bsd_socket_array_index;
838
839 /* Mark this socket as in-use. */
840 nx_bsd_socket_array[nx_bsd_socket_array_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_IN_USE;
841
842 /* Get out of the loop. */
843 break;
844 }
845 else
846 {
847
848 /* Try the next socket. */
849 nx_bsd_socket_array_index++;
850
851 /* Check if we need to wrap around to the start of the socket table. */
852 if (nx_bsd_socket_array_index >= NX_BSD_MAX_SOCKETS)
853 {
854
855 /* Reset the index to 0. */
856 nx_bsd_socket_array_index = 0;
857 }
858 }
859 }
860
861 /* Check if a free socket was found. */
862 if (i >= NX_BSD_MAX_SOCKETS)
863 {
864
865 /* No, set the error status and return. */
866
867 /* Set the socket error. */
868 nx_bsd_set_errno(ENFILE);
869
870 /* Release the mutex. */
871 tx_mutex_put(nx_bsd_protection_ptr);
872
873 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
874 return(NX_SOC_ERROR);
875 }
876
877 /* Mark the location of the free socket. */
878 i = (INT)nx_bsd_socket_array_index;
879
880 /* Update the socket index to the next entry. */
881 nx_bsd_socket_array_index++;
882
883 /* Check if we need to wrap around to the start of the table. */
884 if (nx_bsd_socket_array_index >= NX_BSD_MAX_SOCKETS)
885 {
886
887 /* Reset the index to 0. */
888 nx_bsd_socket_array_index = 0;
889 }
890
891 /* Set up a pointer to the BSD socket to use. */
892 bsd_socket_ptr = &nx_bsd_socket_array[i];
893
894 /* For TCP or UDP sockets we need to allocate memory to create the NetX Duo socket
895 (not necessary for raw socket). */
896
897 if ((type == SOCK_STREAM) || (type == SOCK_DGRAM))
898 {
899
900 /* Allocate a socket from the block pool. */
901 status = tx_block_allocate(&nx_bsd_socket_block_pool, &socket_memory, NX_BSD_TIMEOUT);
902
903 /* Check for error status. */
904 if (status != TX_SUCCESS)
905 {
906
907 /* Set the socket error. */
908 nx_bsd_set_errno(ENOMEM);
909
910 /* Clear the allocated internal BSD socket. */
911 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_IN_USE);
912
913 /* Release the mutex. */
914 tx_mutex_put(nx_bsd_protection_ptr);
915
916 /* Error getting NetX socket memory. */
917 NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
918 return(NX_SOC_ERROR);
919 }
920
921 /* Clear the socket memory. */
922 memset((VOID*) socket_memory, 0, sizeof(NX_TCP_SOCKET));
923
924 }
925
926 /* Is this a stream socket e.g. TCP? */
927 if (type == SOCK_STREAM)
928 {
929 bsd_socket_ptr -> nx_bsd_socket_protocol = NX_PROTOCOL_TCP;
930
931 /* Mark the master/secondary socket id as invalid. */
932 (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id = NX_BSD_MAX_SOCKETS;
933 (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = NX_BSD_MAX_SOCKETS;
934
935 /* Yes, allocate memory for a TCP socket. */
936 tcp_socket_ptr = (NX_TCP_SOCKET *) socket_memory;
937
938 /* Create a NetX TCP socket. */
939 /* Note that the nx_bsd_tcp_socket_disconnect_notify is invoked when an
940 established connection is disconnected.
941 The disconnect_complete_notify is called for all types of disconnect,
942 including the ones covered by tcp_socket_disconnect_notify. */
943
944 status = nx_tcp_socket_create(nx_bsd_default_ip, tcp_socket_ptr, "NetX BSD TCP Socket",
945 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, NX_BSD_TCP_WINDOW, NX_NULL,
946 nx_bsd_tcp_socket_disconnect_notify);
947
948 /* Check for a successful status. */
949 if (status == NX_SUCCESS)
950 {
951
952 /* Register a receive notify callback. */
953 status = nx_tcp_socket_receive_notify(tcp_socket_ptr, nx_bsd_tcp_receive_notify);
954
955 /* Check for invalid input. */
956 if (status != NX_SUCCESS)
957 {
958
959 /* Set the socket error if extended socket options enabled. */
960 nx_bsd_set_errno(EINVAL);
961
962 /* Release the allocated socket memory block. */
963 tx_block_release(socket_memory);
964
965 /* Release the mutex. */
966 tx_mutex_put(nx_bsd_protection_ptr);
967
968 /* Error getting NetX socket memory. */
969 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
970 return(NX_SOC_ERROR);
971 }
972
973 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
974
975 /* Set the SYN received notify function */
976 tcp_socket_ptr -> nx_tcp_socket_syn_received_notify = nx_bsd_tcp_syn_received_notify;
977 #endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */
978
979 #ifdef NX_ENABLE_TCP_KEEPALIVE
980 /* Set the keep alive feature to disabled. */
981 tcp_socket_ptr -> nx_tcp_socket_keepalive_enabled = NX_FALSE;
982 #endif /* NX_ENABLE_TCP_KEEPALIVE */
983
984 /* Set the socket reuse feature to enabled. This is the default NetX socket behavior. */
985 bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR;
986
987 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
988 /* Register an establish notify callback for the specified server socket with NetX. */
989 nx_tcp_socket_establish_notify(tcp_socket_ptr, nx_bsd_tcp_establish_notify);
990
991 /* Register a disconnect complete notify callback for the specified server socket with NetX. */
992 /* The callback function is the same as the one used for TCP disconnect callback. */
993 status += nx_tcp_socket_disconnect_complete_notify(tcp_socket_ptr, nx_bsd_tcp_socket_disconnect_notify);
994 #endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */
995
996 /* Return successful completion. */
997
998 /* Save the TCP pointer in the appropriate place. */
999 bsd_socket_ptr -> nx_bsd_socket_tcp_socket = tcp_socket_ptr;
1000
1001 /* Set up pointer in the NetX socket back to the BSD socket. */
1002 tcp_socket_ptr -> nx_tcp_socket_reserved_ptr = (VOID *) i;
1003
1004
1005 }
1006 }
1007 else if (type == SOCK_DGRAM)
1008 {
1009
1010 bsd_socket_ptr -> nx_bsd_socket_protocol = NX_PROTOCOL_UDP;
1011
1012 /* Make a double circular list. */
1013 bsd_socket_ptr -> nx_bsd_socket_next = bsd_socket_ptr;
1014 bsd_socket_ptr -> nx_bsd_socket_previous = bsd_socket_ptr;
1015
1016 /* Allocate memory for a UDP socket. */
1017 udp_socket_ptr = (NX_UDP_SOCKET *) socket_memory;
1018
1019 /* Create a NetX UDP socket */
1020 status = nx_udp_socket_create(nx_bsd_default_ip, udp_socket_ptr, "NetX BSD UDP Socket",
1021 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE,
1022 (nx_bsd_default_packet_pool -> nx_packet_pool_total)/8+1);
1023
1024 /* Check for successful result. */
1025 if (status == NX_SUCCESS)
1026 {
1027
1028 /* Register a receive notify callback. */
1029 status = nx_udp_socket_receive_notify(udp_socket_ptr, nx_bsd_udp_receive_notify);
1030
1031 /* Check for errors. */
1032 if (status != NX_SUCCESS)
1033 {
1034
1035 /* Release the allocated socket memory block. */
1036 tx_block_release(socket_memory);
1037
1038 /* Release the mutex. */
1039 tx_mutex_put(nx_bsd_protection_ptr);
1040
1041 /* Set the socket error if extended socket options enabled. */
1042 nx_bsd_set_errno(EINVAL);
1043
1044 /* Error getting NetX socket memory. */
1045 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1046 return(NX_SOC_ERROR);
1047 }
1048
1049 /* Save the UDP pointer in the BSD socket. */
1050 bsd_socket_ptr -> nx_bsd_socket_udp_socket = udp_socket_ptr;
1051
1052 /* Set the reserved UDP socket pointer back to the BSD socket. */
1053 udp_socket_ptr -> nx_udp_socket_reserved_ptr = (VOID *) (i + 0x00010000);
1054 }
1055 }
1056 #if defined(NX_ENABLE_IP_RAW_PACKET_FILTER) || defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT)
1057 else if (type == SOCK_RAW)
1058 {
1059
1060 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
1061 /* Check if raw sockets are enabled in NetX Duo. */
1062 if (((protocolFamily == AF_INET) ||
1063 (protocolFamily == AF_INET6)) &&
1064 (nx_bsd_default_ip -> nx_ip_raw_ip_processing == NX_NULL))
1065 {
1066 /* No, Enable raw socket handling in NetX Duo. */
1067 status = nx_ip_raw_packet_enable(nx_bsd_default_ip);
1068
1069 if (status != NX_SUCCESS)
1070 {
1071
1072 /* Release the mutex. */
1073 tx_mutex_put(nx_bsd_protection_ptr);
1074
1075 nx_bsd_set_errno(EPROTONOSUPPORT);
1076
1077 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1078 return NX_SOC_ERROR;
1079 }
1080 }
1081
1082 /* Check if we set the packet filter already. */
1083 if (((protocolFamily == AF_INET) ||
1084 (protocolFamily == AF_INET6)) &&
1085 (nx_bsd_default_ip -> nx_ip_raw_packet_filter == NX_NULL))
1086 {
1087
1088 /* We have not. Do so now. Set the raw packet filter to the IP instance. */
1089 status = nx_ip_raw_packet_filter_set(nx_bsd_default_ip, nx_bsd_raw_packet_filter);
1090
1091 /* Has a raw packet filter been successfully set? */
1092 if (status != NX_SUCCESS)
1093 {
1094
1095 /* Release the mutex. */
1096 tx_mutex_put(nx_bsd_protection_ptr);
1097
1098 nx_bsd_set_errno(EPROTONOSUPPORT);
1099
1100 /* No, return error status. */
1101 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1102 return NX_SOC_ERROR;
1103 }
1104 }
1105
1106 /* For IPv6 raw socket, by default the header is not included in the received packet. */
1107 if(protocolFamily == AF_INET6)
1108 {
1109 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_RX_NO_HDR;
1110 }
1111
1112 /* Set the raw socket protocol to the BSD raw socket. */
1113 bsd_socket_ptr -> nx_bsd_socket_protocol = (USHORT)protocol;
1114 bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_RAW_SOCKET;
1115
1116 /* Calculate the hash index in the raw socket protocol table. */
1117 index = (UINT) ((protocol + (protocol >> 8)) & NX_BSD_SOCKET_RAW_PROTOCOL_TABLE_MASK);
1118
1119 /* Determine if the list is NULL. */
1120 if(nx_bsd_socket_raw_protocol_table[index])
1121 {
1122 /* There are already sockets on the list... just add this one to the end. */
1123 bsd_socket_ptr -> nx_bsd_socket_next = nx_bsd_socket_raw_protocol_table[index];
1124 bsd_socket_ptr -> nx_bsd_socket_previous = (nx_bsd_socket_raw_protocol_table[index]) -> nx_bsd_socket_previous;
1125 ((nx_bsd_socket_raw_protocol_table[index]) -> nx_bsd_socket_previous) -> nx_bsd_socket_next = bsd_socket_ptr;
1126 (nx_bsd_socket_raw_protocol_table[index]) -> nx_bsd_socket_previous = bsd_socket_ptr;
1127 }
1128 else
1129 {
1130 /* Nothing is on the list. Add this one to an empty list. */
1131 bsd_socket_ptr -> nx_bsd_socket_next = bsd_socket_ptr;
1132 bsd_socket_ptr -> nx_bsd_socket_previous = bsd_socket_ptr;
1133 nx_bsd_socket_raw_protocol_table[index] = bsd_socket_ptr;
1134 }
1135 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
1136
1137 if(protocolFamily == AF_PACKET)
1138 {
1139 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
1140 bsd_socket_ptr -> nx_bsd_socket_create_id = nx_bsd_socket_create_id;
1141 nx_bsd_socket_create_id++;
1142 #elif defined(NX_BSD_RAW_SUPPORT)
1143 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
1144 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
1145 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
1146 }
1147
1148 }
1149 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER || NX_BSD_RAW_PPPOE_SUPPORT || NX_BSD_RAW_SUPPORT */
1150
1151 else
1152 {
1153 /* Not a supported socket type. */
1154 nx_bsd_set_errno(EOPNOTSUPP);
1155
1156 /* Invalid type. */
1157 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1158 return(NX_SOC_ERROR);
1159 }
1160
1161 /* Set the protocol family: AF_INET or AF_INET6. */
1162 bsd_socket_ptr -> nx_bsd_socket_family = (ULONG)protocolFamily;
1163
1164 /* For UDP and RAW sockets, set the maximum receive queue depth. */
1165 if(bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
1166 {
1167
1168 bsd_socket_ptr -> nx_bsd_socket_received_packet_count_max = NX_BSD_SOCKET_QUEUE_MAX;
1169 }
1170
1171 /* Check for error creating the NetX Duo socket. */
1172 if (status != NX_SUCCESS)
1173 {
1174
1175 /* Release the BSD protection. */
1176
1177 /* Clear the BSD socket in use flag. */
1178 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_IN_USE);
1179
1180 if ((type == SOCK_DGRAM) || (type == SOCK_STREAM))
1181 {
1182 /* Release the socket memory block allocated for TCP or UDP socket. */
1183 tx_block_release(socket_memory);
1184 }
1185
1186 /* Release the mutex. */
1187 tx_mutex_put(nx_bsd_protection_ptr);
1188
1189 /* Set the socket error if extended socket options enabled. */
1190 nx_bsd_set_errno(EINVAL);
1191
1192 /* Error present, return error code. */
1193 NX_BSD_ERROR(status, __LINE__);
1194 return(NX_SOC_ERROR);
1195 }
1196
1197 /* Release the mutex. */
1198 tx_mutex_put(nx_bsd_protection_ptr);
1199
1200 /* Return success! */
1201 return(i + NX_BSD_SOCKFD_START);
1202 }
1203
1204
1205 /**************************************************************************/
1206 /* */
1207 /* FUNCTION RELEASE */
1208 /* */
1209 /* connect PORTABLE C */
1210 /* 6.3.0 */
1211 /* AUTHOR */
1212 /* */
1213 /* Yuxin Zhou, Microsoft Corporation */
1214 /* */
1215 /* DESCRIPTION */
1216 /* */
1217 /* Establishes a connection between a client socket and a remote server*/
1218 /* socket associated with the remote address, if any. Upon returning */
1219 /* successfully, the given socket's local and remote IP address and */
1220 /* port information are filled in. If the socket was not previously */
1221 /* bound to a local port, one is assigned randomly. */
1222 /* */
1223 /* For TCP sockets, connect() completes with a connection handshake is */
1224 /* complete, or if an error occurs. A TCP negotiation is performed */
1225 /* to open a connection and success implies the existence of a reliable*/
1226 /* channel to that socket. */
1227 /* */
1228 /* For UDP sockets, the connection is established simply by setting the*/
1229 /* supplied destination (remote) IP address and port for the remote */
1230 /* host. */
1231 /* */
1232 /* For non blocking sockets, the function returns immediately if a */
1233 /* connection is not possible. The socket thread error is set to */
1234 /* EINPROGRESS to distinguish from blocking sockets. */
1235 /* */
1236 /* INPUT */
1237 /* */
1238 /* sockID Socket descriptor */
1239 /* *remoteAddress Remote address structure */
1240 /* addressLength Address structure length */
1241 /* */
1242 /* OUTPUT */
1243 /* */
1244 /* NX_SOC_OK (0) If success */
1245 /* NX_SOC_ERROR (-1) If failure or if called with */
1246 /* an UDP socket */
1247 /* */
1248 /* CALLS */
1249 /* */
1250 /* nx_ip_status_check Check to make sure link is up */
1251 /* nx_tcp_client_socket_bind Bind a TCP socket to a port */
1252 /* nxd_tcp_client_socket_connect Connect to a TCP server */
1253 /* tx_mutex_get Get protection */
1254 /* tx_mutex_put Release protection */
1255 /* tx_thread_identify Get current thread pointer */
1256 /* */
1257 /* CALLED BY */
1258 /* */
1259 /* Application Code */
1260 /* */
1261 /* RELEASE HISTORY */
1262 /* */
1263 /* DATE NAME DESCRIPTION */
1264 /* */
1265 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1266 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1267 /* resulting in version 6.1 */
1268 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
1269 /* used new API/structs naming,*/
1270 /* resulting in version 6.3.0 */
1271 /* */
1272 /**************************************************************************/
nx_bsd_connect(INT sockID,struct nx_bsd_sockaddr * remoteAddress,INT addressLength)1273 INT nx_bsd_connect(INT sockID, struct nx_bsd_sockaddr *remoteAddress, INT addressLength)
1274 {
1275 UINT status;
1276 NX_TCP_SOCKET *tcp_socket_ptr;
1277 NX_UDP_SOCKET *udp_socket_ptr;
1278 NX_BSD_SOCKET *bsd_socket_ptr;
1279 ULONG timeout;
1280 ULONG actual_status;
1281
1282 /* Check for a valid socket ID. */
1283 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
1284 {
1285
1286 /* Set the socket error. */
1287 nx_bsd_set_errno(EBADF);
1288
1289 /* Return an error. */
1290 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1291 return(NX_SOC_ERROR);
1292 }
1293
1294 /* Adjust the sockID to index into the BSD socket table. */
1295 sockID = sockID - NX_BSD_SOCKFD_START;
1296
1297 /* Ensure the IP instance has been initialized. */
1298 status = nx_ip_status_check(nx_bsd_default_ip, NX_IP_INITIALIZE_DONE, &actual_status, NX_BSD_TIMEOUT);
1299
1300 /* Check the status. */
1301 if (status != NX_SUCCESS)
1302 {
1303
1304 /* Set the socket error. */
1305 nx_bsd_set_errno(EFAULT);
1306
1307 /* Return an error. */
1308 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1309 return(NX_SOC_ERROR);
1310 }
1311
1312 /* Set a pointer to the BSD socket. */
1313 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
1314
1315 /* Make sure the socket is valid. */
1316 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
1317 {
1318
1319 /* Socket is no longer in use. */
1320
1321 /* Set the socket error if extended socket options enabled. */
1322 nx_bsd_set_errno(EBADF);
1323
1324 /* Return an error. */
1325 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1326 return(NX_SOC_ERROR);
1327 }
1328
1329 /* Obtain the BSD protection. */
1330 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
1331
1332 /* Check the status. */
1333 if (status != NX_SUCCESS)
1334 {
1335
1336 /* Set the socket error if extended socket options enabled. */
1337 nx_bsd_set_errno(EACCES);
1338
1339 /* Return an error. */
1340 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
1341 return(NX_SOC_ERROR);
1342 }
1343
1344 /* Check whether supplied address structure and length is valid */
1345 if (remoteAddress == NX_NULL )
1346 {
1347
1348 /* For UDP socket or RAW socket, a NULL remoteAddress dis-associate
1349 a remote address bound to the socket. */
1350 if (bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
1351 {
1352 memset(&bsd_socket_ptr -> nx_bsd_socket_peer_ip, 0, sizeof(NXD_ADDRESS));
1353 bsd_socket_ptr -> nx_bsd_socket_peer_port = 0;
1354
1355 /* Clear the connect flag. */
1356 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTED);
1357
1358 /* All done. Return. */
1359
1360 /* Release the mutex. */
1361 tx_mutex_put(nx_bsd_protection_ptr);
1362
1363 return(NX_SOC_OK);
1364
1365 }
1366 else
1367 {
1368 /* For TCP socket, each socket can only be connected once, and
1369 the remote address must be set correctly. */
1370
1371 /* Release the mutex. */
1372 tx_mutex_put(nx_bsd_protection_ptr);
1373 /* Set the socket error if extended socket options enabled. */
1374 nx_bsd_set_errno(EAFNOSUPPORT);
1375
1376 /* Return an error. */
1377 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1378 return(NX_SOC_ERROR);
1379 }
1380 }
1381
1382
1383 /* Check if the remote address family matches the local BSD socket address family. */
1384 if((remoteAddress -> sa_family != bsd_socket_ptr -> nx_bsd_socket_family) ||
1385 ((remoteAddress -> sa_family == AF_INET) && (addressLength != sizeof(struct nx_bsd_sockaddr_in))) ||
1386 ((remoteAddress -> sa_family == AF_INET6) && (addressLength != sizeof(struct nx_bsd_sockaddr_in6))))
1387 {
1388
1389 /* Mismatch! */
1390
1391 /* Release the mutex. */
1392 tx_mutex_put(nx_bsd_protection_ptr);
1393
1394 /* Set the socket error if extended socket options enabled. */
1395 nx_bsd_set_errno(EAFNOSUPPORT);
1396
1397 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1398 return(ERROR);
1399 }
1400
1401 #ifndef NX_DISABLE_IPV4
1402 /* Check the socket family type. */
1403 if(remoteAddress -> sa_family == AF_INET)
1404 {
1405
1406 /* This is an IPv4 socket type. */
1407
1408 /* Set the UDP remote host IP address and port for the UDP 'connection'; for NetX Duo
1409 set the IP version. */
1410 /* NetX API expects multi byte values to be in host byte order.
1411 Therefore ntohl/s are used to make the conversion. */
1412 bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_version = NX_IP_VERSION_V4;
1413 bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v4 = htonl(((struct nx_bsd_sockaddr_in *) remoteAddress ) -> sin_addr.s_addr);
1414 bsd_socket_ptr -> nx_bsd_socket_peer_port = htons(((struct nx_bsd_sockaddr_in *) remoteAddress ) -> sin_port);
1415 }
1416 else
1417 #endif /* NX_DISABLE_IPV4 */
1418
1419 #ifdef FEATURE_NX_IPV6
1420 if(remoteAddress -> sa_family == AF_INET6)
1421 {
1422
1423 /* This is an IPv6 enabled socket family type). */
1424 bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_version = NX_IP_VERSION_V6;
1425 /* NetX API expects multi byte values to be in host byte order.
1426 Therefore ntohl/s are used to make the conversion. */
1427 /* Get remote address and port. */
1428 bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[0] = htonl(((struct nx_bsd_sockaddr_in6*)remoteAddress) -> sin6_addr._S6_un._S6_u32[0]);
1429 bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[1] = htonl(((struct nx_bsd_sockaddr_in6*)remoteAddress) -> sin6_addr._S6_un._S6_u32[1]);
1430 bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[2] = htonl(((struct nx_bsd_sockaddr_in6*)remoteAddress) -> sin6_addr._S6_un._S6_u32[2]);
1431 bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[3] = htonl(((struct nx_bsd_sockaddr_in6*)remoteAddress) -> sin6_addr._S6_un._S6_u32[3]);
1432
1433 bsd_socket_ptr -> nx_bsd_socket_peer_port = htons(((struct nx_bsd_sockaddr_in6 *) remoteAddress ) -> sin6_port);
1434
1435 }
1436 else
1437 #endif /* FEATURE_NX_IPV6 */
1438 {
1439
1440 /* Address family not supported. */
1441
1442 /* Release the mutex. */
1443 tx_mutex_put(nx_bsd_protection_ptr);
1444
1445 /* Set the socket error if extended socket options enabled. */
1446 nx_bsd_set_errno(EAFNOSUPPORT);
1447
1448 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1449 return(ERROR);
1450 }
1451
1452
1453 /* Handle the UDP 'connection' request. */
1454 if (bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
1455 {
1456
1457 udp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_udp_socket;
1458
1459 /* Check to see if the UDP socket is already bound. */
1460 if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND))
1461 {
1462
1463 /* Not yet, bind to a randomly selected available free port. */
1464 status = nx_udp_socket_bind(udp_socket_ptr, NX_ANY_PORT, NX_BSD_TIMEOUT);
1465
1466 /* Check for error. */
1467 if (status != NX_SUCCESS)
1468 {
1469
1470 /* Release the mutex. */
1471 tx_mutex_put(nx_bsd_protection_ptr);
1472
1473 /* Set the socket error based on NetX error status return. */
1474 nx_bsd_set_error_code(bsd_socket_ptr, status);
1475
1476 /* Return an error. */
1477 NX_BSD_ERROR(ERROR, __LINE__);
1478 return(ERROR);
1479 }
1480
1481 /* Bind is successful. Obtain the port number. */
1482 bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)udp_socket_ptr -> nx_udp_socket_port;
1483 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
1484 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
1485 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
1486 }
1487
1488 /* Mark the socket as connected. */
1489 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
1490
1491 /* Release the mutex. */
1492 tx_mutex_put(nx_bsd_protection_ptr);
1493
1494 /* Return successful status. */
1495 return(NX_SOC_OK);
1496 }
1497 else if (bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
1498 {
1499
1500 /* This is not UDP or TCP socket. So it must be raw socket. */
1501 /* We treat raw socket the same as UDP socket. For connec, raw socket
1502 associates the remote address as its default destination address when
1503 transmit, and also limit the reception of data from that remote address. */
1504
1505 /* Mark the socket as connected. */
1506 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
1507
1508 /* Release the mutex. */
1509 tx_mutex_put(nx_bsd_protection_ptr);
1510
1511 /* Return successful status. */
1512 return(NX_SOC_OK);
1513 }
1514
1515 /* This is a TCP BSD socket. */
1516
1517 /* If the socket is already connected. */
1518 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
1519 {
1520
1521 /* If INPROGRESS is set, clear the INPROGRESS flag and return OK.
1522 The INPROGRESS flag needs to be cleared so the next connect call would return EISCONN */
1523 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_INPROGRESS)
1524 {
1525
1526 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
1527
1528 /* Release the protection mutex. */
1529 tx_mutex_put(nx_bsd_protection_ptr);
1530
1531 return(NX_SOC_OK);
1532 }
1533
1534 /* Already connected. */
1535 nx_bsd_set_errno(EISCONN);
1536
1537 tx_mutex_put(nx_bsd_protection_ptr);
1538
1539 /* Return an error. */
1540 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1541 return(NX_SOC_ERROR);
1542
1543 }
1544
1545 /* If the socket is marked as EINPROGRESS, return EALREADY. */
1546 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_INPROGRESS)
1547 {
1548
1549
1550 nx_bsd_set_errno(EALREADY);
1551
1552 /* Release the protection mutex. */
1553 tx_mutex_put(nx_bsd_protection_ptr);
1554
1555 /* Return an error. */
1556 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1557 return(NX_SOC_ERROR);
1558
1559 }
1560 /* If the socket has an error */
1561 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
1562 {
1563 INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
1564
1565 /* Now clear the error code. */
1566 bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
1567
1568 /* Clear the error flag. The application is expected to close the socket at this point.*/
1569 bsd_socket_ptr -> nx_bsd_socket_status_flags =
1570 bsd_socket_ptr -> nx_bsd_socket_status_flags & ((ULONG)(~NX_BSD_SOCKET_ERROR));
1571
1572 nx_bsd_set_errno(errcode);
1573
1574 /* Release the protection mutex. */
1575 tx_mutex_put(nx_bsd_protection_ptr);
1576
1577 /* Return an error. */
1578 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1579
1580 /* At this point the error flag is cleared. Application should
1581 detect and handle the error codition. This socket is still bound
1582 to the port (either the application called bind(), or a bind
1583 operation was executed as part of the connect call) is able to
1584 handle another "connect" call, or be closed. */
1585 return(NX_SOC_ERROR);
1586 }
1587
1588 /* Set a NetX tcp pointer. */
1589 tcp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
1590
1591 /* Mark this as a client TCP socket. */
1592 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CLIENT;
1593
1594 /* Is the TCP socket already bound? */
1595 if (tcp_socket_ptr -> nx_tcp_socket_port == 0)
1596 {
1597
1598 /* Not yet; bind to a randomly selected available free port. */
1599
1600 /* Call NetX TCP bind service with NX_NO_WAIT. */
1601 status = nx_tcp_client_socket_bind(tcp_socket_ptr, NX_ANY_PORT, NX_NO_WAIT);
1602
1603 /* Check for error. */
1604 if (status != NX_SUCCESS)
1605 {
1606
1607 /* Clear the client socket flag. */
1608 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CLIENT);
1609
1610 /* Set the socket error depending on NetX error status return. */
1611 nx_bsd_set_error_code(bsd_socket_ptr, status);
1612
1613 /* Return an error. */
1614 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1615
1616 /* Release the protection mutex. */
1617 tx_mutex_put(nx_bsd_protection_ptr);
1618
1619 return(NX_SOC_ERROR);
1620 }
1621
1622 /* Mark the socket as bound. */
1623 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
1624 bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)tcp_socket_ptr -> nx_tcp_socket_port;
1625 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
1626 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
1627
1628 }
1629
1630 /* Mark this BSD socket as busy. */
1631 bsd_socket_ptr -> nx_bsd_socket_busy = tx_thread_identify();
1632
1633 /* Attempt to make the connection. If the socket is non-blocking,
1634 set the timeout to 0. Otherwise, use wait-forever */
1635 if (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING)
1636 {
1637
1638 /* Yes, the socket is enabled for non blocking. Do not wait. */
1639 timeout = 0;
1640 }
1641 else
1642 {
1643 /* This call may be blocked internally. Release the mutex
1644 so the nx_tcp_client_socket_connect can suspend waiting
1645 for a connection. */
1646 timeout = NX_WAIT_FOREVER;
1647 tx_mutex_put(nx_bsd_protection_ptr);
1648 }
1649
1650 /* Make the connection. */
1651 status = nxd_tcp_client_socket_connect(tcp_socket_ptr, &(bsd_socket_ptr -> nx_bsd_socket_peer_ip), bsd_socket_ptr -> nx_bsd_socket_peer_port, timeout);
1652 if(timeout != 0)
1653 {
1654 /* The mutex was released prior to the call. Accquire the mutex
1655 again. */
1656 tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
1657
1658 /* Verify that the socket is still valid. */
1659 if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
1660 {
1661 /* The socket is no longer in use. */
1662
1663 /* Set the socket error code. */
1664 nx_bsd_set_errno(EBADF);
1665
1666 /* Release the protection mutex. */
1667 tx_mutex_put(nx_bsd_protection_ptr);
1668
1669 /* Return error code. */
1670 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1671 return(NX_SOC_ERROR);
1672 }
1673
1674 if (status == NX_NOT_CONNECTED)
1675 {
1676
1677 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR) ||
1678 (tcp_socket_ptr -> nx_tcp_socket_timeout_retries >= tcp_socket_ptr -> nx_tcp_socket_timeout_max_retries))
1679 {
1680
1681 /* Connect timeouts since NX_BSD_SOCKET_ERROR is not set or
1682 * number of timeout retry has been exceeded. */
1683 status = NX_WAIT_ABORTED;
1684 }
1685
1686 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
1687 bsd_socket_ptr -> nx_bsd_socket_error_code = ENOTCONN;
1688 }
1689 }
1690
1691 /* Check for an error. */
1692 if (status != NX_SUCCESS)
1693 {
1694
1695 /* Set the socket error depending on NetX error status return. */
1696 nx_bsd_set_error_code(bsd_socket_ptr, status);
1697
1698
1699 /* Make sure this thread is still the owner. */
1700 if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
1701 {
1702
1703 /* Clear the busy flag. */
1704 bsd_socket_ptr -> nx_bsd_socket_busy = TX_NULL;
1705 }
1706
1707 /* Release the protection mutex. */
1708 tx_mutex_put(nx_bsd_protection_ptr);
1709
1710 /* Return error code. */
1711 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1712 return(NX_SOC_ERROR);
1713 }
1714
1715 /* At this point NX TCP connect service returns success, so the connection is established. */
1716
1717 /* Mark the socket as connected. */
1718 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
1719
1720 /* Clear the CONNECTION_INPROGRESS flag. */
1721 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
1722
1723 /* Mark the connection_request flag */
1724 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_REQUEST;
1725
1726 /* Make sure thread making the bind call is the current thread. */
1727 if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
1728 {
1729
1730 /* OK to clear the busy flag. */
1731 bsd_socket_ptr -> nx_bsd_socket_busy = TX_NULL;
1732
1733 /* Check if the connect call was successful. */
1734 if (status == NX_SUCCESS)
1735 {
1736
1737 /* It was. Release the protection mutex. */
1738 tx_mutex_put(nx_bsd_protection_ptr);
1739
1740 /* Successful connection. Return the success status. */
1741 return(NX_SOC_OK);
1742 }
1743 }
1744
1745 /* Error condition: the thread that was executing connect is not the current thread. */
1746
1747 /* Clear the connected flags and peer infomration .*/
1748 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTED);
1749 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_REQUEST);
1750 memset(&bsd_socket_ptr -> nx_bsd_socket_source_ip_address, 0, sizeof(NXD_ADDRESS));
1751 bsd_socket_ptr -> nx_bsd_socket_source_port = 0;
1752
1753 /* Release the protection mutex. */
1754 tx_mutex_put(nx_bsd_protection_ptr);
1755
1756 /* Set the socket error. */
1757 nx_bsd_set_errno(EINTR);
1758
1759 /* Return an error. */
1760 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1761 return(NX_SOC_ERROR);
1762 }
1763
1764 /**************************************************************************/
1765 /* */
1766 /* FUNCTION RELEASE */
1767 /* */
1768 /* bind PORTABLE C */
1769 /* 6.3.0 */
1770 /* AUTHOR */
1771 /* */
1772 /* Yuxin Zhou, Microsoft Corporation */
1773 /* */
1774 /* DESCRIPTION */
1775 /* */
1776 /* This function binds a socket to a local port. The port in the struct*/
1777 /* in the struct sockaddr structure may be wildcarded, in which case */
1778 /* NetX will select a port number. */
1779 /* */
1780 /* To wildcard the port, set the sin_port field of the address to 0. */
1781 /* */
1782 /* INPUT */
1783 /* */
1784 /* sockID Socket descriptor */
1785 /* *localAddress Populated socket address */
1786 /* addressLength Socket address length */
1787 /* */
1788 /* OUTPUT */
1789 /* */
1790 /* NX_SOC_OK (0) If success */
1791 /* NX_SOC_ERROR (-1) If failure */
1792 /* */
1793 /* CALLS */
1794 /* */
1795 /* nx_ip_status_check Check for link up */
1796 /* nx_tcp_client_socket_bind Binds a TCP socket to a port */
1797 /* nx_udp_client_socket_bind Binds a UDP socket to a port */
1798 /* tx_mutex_get Get protection */
1799 /* tx_mutex_put Release protection */
1800 /* tx_thread_identify Gets the current thread */
1801 /* */
1802 /* CALLED BY */
1803 /* */
1804 /* Application Code */
1805 /* */
1806 /* RELEASE HISTORY */
1807 /* */
1808 /* DATE NAME DESCRIPTION */
1809 /* */
1810 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1811 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1812 /* resulting in version 6.1 */
1813 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
1814 /* used new API/structs naming,*/
1815 /* resulting in version 6.3.0 */
1816 /* */
1817 /**************************************************************************/
nx_bsd_bind(INT sockID,const struct nx_bsd_sockaddr * localAddress,INT addressLength)1818 INT nx_bsd_bind(INT sockID, const struct nx_bsd_sockaddr *localAddress, INT addressLength)
1819 {
1820
1821 INT local_port = 0;
1822 UINT status;
1823 NX_TCP_SOCKET *tcp_socket_ptr;
1824 NX_UDP_SOCKET *udp_socket_ptr;
1825 NX_BSD_SOCKET *bsd_socket_ptr;
1826 INT i;
1827 INT address_conflict;
1828
1829
1830 /* Check for invalid socket ID. */
1831 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
1832 {
1833
1834 /* Set the socket error. */
1835 nx_bsd_set_errno(EBADF);
1836
1837 /* Error, invalid socket ID. */
1838 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1839 return(NX_SOC_ERROR);
1840 }
1841
1842 /* Check for a valid input local address and address length input buffer. */
1843 if ((localAddress == NX_NULL ) || (addressLength == 0))
1844 {
1845
1846 /* Set the socket error if extended socket options enabled. */
1847 nx_bsd_set_errno(EFAULT);
1848
1849 /* Error, invalid local address. */
1850 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1851 return(NX_SOC_ERROR);
1852 }
1853
1854 if (((localAddress -> sa_family == AF_INET) && (addressLength != sizeof(struct nx_bsd_sockaddr_in))) ||
1855 ((localAddress -> sa_family == AF_INET6) && (addressLength != sizeof(struct nx_bsd_sockaddr_in6))))
1856 {
1857 nx_bsd_set_errno(EAFNOSUPPORT);
1858
1859 /* Return an error. */
1860 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1861 return(NX_SOC_ERROR);
1862 }
1863
1864 /* Normalize the socket ID. */
1865 sockID = sockID - NX_BSD_SOCKFD_START;
1866
1867 /* Get the protection mutex. */
1868 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
1869
1870 /* Check the status. */
1871 if (status != NX_SUCCESS)
1872 {
1873
1874 /* Set the socket error if extended socket options enabled. */
1875 nx_bsd_set_errno(EACCES);
1876
1877 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
1878 return(NX_SOC_ERROR);
1879 }
1880
1881 /* Set up a pointer to the BSD socket. */
1882 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
1883
1884 /* See if the socket is still in use. */
1885 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
1886 {
1887
1888 /* Socket is no longer in use. */
1889
1890 /* Release the protection mutex. */
1891 tx_mutex_put(nx_bsd_protection_ptr);
1892
1893 /* Set the socket error if extended socket options enabled. */
1894 nx_bsd_set_errno(EBADF);
1895
1896 /* Return an error. */
1897 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1898 return(NX_SOC_ERROR);
1899 }
1900
1901 /* If the socket has an error */
1902 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
1903 {
1904
1905 /* Clear the error flag. The application is expected to close the socket at this point.*/
1906 bsd_socket_ptr -> nx_bsd_socket_status_flags =
1907 bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
1908
1909 nx_bsd_set_errno(bsd_socket_ptr -> nx_bsd_socket_error_code);
1910
1911 /* Clear the error code. */
1912 bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
1913
1914 /* Release the protection mutex. */
1915 tx_mutex_put(nx_bsd_protection_ptr);
1916
1917 /* Return an error. */
1918 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1919
1920 /* At this point the error flag is cleared. Application should
1921 detect and handle the error codition. This socket is still bound
1922 to the port (either the application called bind(), or a bind
1923 operation was executed as part of the connect call) is able to
1924 handle another "connect" call, or be closed. */
1925 return(NX_SOC_ERROR);
1926 }
1927
1928 /* Check the address family. */
1929 if (bsd_socket_ptr -> nx_bsd_socket_family != localAddress -> sa_family)
1930 {
1931 nx_bsd_set_errno(EAFNOSUPPORT);
1932 /* Release the protection mutex. */
1933 tx_mutex_put(nx_bsd_protection_ptr);
1934
1935 /* Return an error. */
1936 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1937 return(NX_SOC_ERROR);
1938 }
1939
1940 /* Check to see if the socket is already bound. */
1941 if (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND)
1942 {
1943
1944 /* It is. */
1945
1946 /* Set the socket error if extended socket options enabled. */
1947 nx_bsd_set_errno(EINVAL);
1948
1949 /* Release the protection mutex. */
1950 tx_mutex_put(nx_bsd_protection_ptr);
1951
1952 /* Return an error. */
1953 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1954 return(NX_SOC_ERROR);
1955 }
1956
1957 /* Zero out the local bind info */
1958 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = 0;
1959
1960 #ifndef NX_DISABLE_IPV4
1961 if(localAddress -> sa_family == AF_INET)
1962 {
1963
1964 ULONG local_addr;
1965 INT if_index;
1966
1967 /* Pickup the local port. */
1968 local_port = ntohs(((struct nx_bsd_sockaddr_in *) localAddress) -> sin_port);
1969
1970 /* Pick up the local IP address */
1971 local_addr = ntohl(((struct nx_bsd_sockaddr_in*)localAddress) -> sin_addr.s_addr);
1972
1973 if(local_addr == INADDR_ANY)
1974 {
1975
1976 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
1977 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
1978 }
1979 else
1980 {
1981
1982 for(if_index = 0; if_index < NX_MAX_IP_INTERFACES; if_index++)
1983 {
1984
1985 if((nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_valid) &&
1986 (nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_ip_address == local_addr))
1987 {
1988
1989 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = (ULONG)(&nx_bsd_default_ip -> nx_ip_interface[if_index]);
1990 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = (UINT)if_index;
1991 break;
1992 }
1993 }
1994 }
1995 }
1996 #endif /* NX_DISABLE_IPV4 */
1997 #ifdef FEATURE_NX_IPV6
1998 if(localAddress -> sa_family == AF_INET6)
1999 {
2000
2001 ULONG ipv6_addr[4];
2002 INT if_index;
2003
2004 /* Pickup the local port. */
2005 local_port = ntohs(((struct nx_bsd_sockaddr_in6 *) localAddress) -> sin6_port);
2006
2007 ipv6_addr[0] = ntohl((((struct nx_bsd_sockaddr_in6*)localAddress)) -> sin6_addr._S6_un._S6_u32[0]);
2008 ipv6_addr[1] = ntohl((((struct nx_bsd_sockaddr_in6*)localAddress)) -> sin6_addr._S6_un._S6_u32[1]);
2009 ipv6_addr[2] = ntohl((((struct nx_bsd_sockaddr_in6*)localAddress)) -> sin6_addr._S6_un._S6_u32[2]);
2010 ipv6_addr[3] = ntohl((((struct nx_bsd_sockaddr_in6*)localAddress)) -> sin6_addr._S6_un._S6_u32[3]);
2011
2012 if((ipv6_addr[0] | ipv6_addr[1] | ipv6_addr[2] | ipv6_addr[3]) == 0)
2013 {
2014
2015 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
2016 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
2017 }
2018 else
2019 {
2020
2021 for(if_index = 0; if_index < NX_MAX_IPV6_ADDRESSES; if_index++)
2022 {
2023
2024 if((nx_bsd_default_ip -> nx_ipv6_address[if_index].nxd_ipv6_address[0] == ipv6_addr[0]) &&
2025 (nx_bsd_default_ip -> nx_ipv6_address[if_index].nxd_ipv6_address[1] == ipv6_addr[1]) &&
2026 (nx_bsd_default_ip -> nx_ipv6_address[if_index].nxd_ipv6_address[2] == ipv6_addr[2]) &&
2027 (nx_bsd_default_ip -> nx_ipv6_address[if_index].nxd_ipv6_address[3] == ipv6_addr[3]))
2028 {
2029
2030 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = (ULONG)(&nx_bsd_default_ip -> nx_ipv6_address[if_index]);
2031
2032 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = (UINT)if_index;
2033 break;
2034 }
2035 }
2036 }
2037 }
2038 #endif
2039 #ifdef NX_BSD_RAW_SUPPORT
2040 if ((localAddress -> sa_family == AF_PACKET) && (addressLength == sizeof(struct nx_bsd_sockaddr_ll)))
2041 {
2042 UINT if_index;
2043
2044 if_index = (UINT)(((struct sockaddr_ll *)localAddress) -> sll_ifindex);
2045 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = (ULONG)(&nx_bsd_default_ip -> nx_ip_interface[if_index]);
2046 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = if_index;
2047 }
2048 #endif /* NX_BSD_RAW_SUPPORT */
2049
2050 /* Check if the bind information is correctly set. */
2051 if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == 0)
2052 {
2053
2054 /* Release the protection mutex. */
2055 tx_mutex_put(nx_bsd_protection_ptr);
2056
2057 /* Set the socket error if extended socket options enabled. */
2058 nx_bsd_set_errno(EADDRNOTAVAIL);
2059
2060 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
2061 return(NX_SOC_ERROR);
2062 }
2063
2064 /* At this point the local bind interface and port are known.
2065 If port number is specified, we need to go through the existing sockets
2066 and make sure there is no conflict. */
2067 address_conflict = 0;
2068
2069 if(local_port)
2070 {
2071
2072 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
2073 {
2074
2075 /* Skip its own entry. */
2076 if((i == sockID) ||
2077 /* Skip invalid entries. */
2078 (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE)) ||
2079 /* Skip the entries with different protocol ID */
2080 (nx_bsd_socket_array[i].nx_bsd_socket_protocol != bsd_socket_ptr -> nx_bsd_socket_protocol) ||
2081 /* Skip the unbound entries */
2082 (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND)))
2083 {
2084
2085 continue;
2086 }
2087
2088 /* Check for port number and interface ID */
2089 if(nx_bsd_socket_array[i].nx_bsd_socket_local_port == (USHORT)local_port)
2090 {
2091
2092 address_conflict = 1;
2093
2094 if((nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface == bsd_socket_ptr -> nx_bsd_socket_local_bind_interface) &&
2095 (nx_bsd_socket_array[i].nx_bsd_socket_family == bsd_socket_ptr -> nx_bsd_socket_family))
2096 {
2097
2098 /* This is completely duplicate binding. */
2099
2100 /* If it is a TCP non-listen socket (in other words a TCP server socket that is
2101 already in connection, and the REUSEADDR is set, it is OK. */
2102 if((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED) &&
2103 (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CLIENT)) &&
2104 (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR))
2105 {
2106
2107 address_conflict = 0;
2108 }
2109 }
2110 else
2111 {
2112
2113 /* If the REUSEADDR option is set, the socket can be bound to its specififed local address. */
2114 if(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR)
2115 {
2116
2117 address_conflict = 0;
2118
2119 if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
2120 {
2121
2122 UINT counter;
2123
2124 /* For UDP socket, it needs to share the underlying NetX UDP socket. */
2125 nx_udp_socket_delete(bsd_socket_ptr -> nx_bsd_socket_udp_socket);
2126
2127 /* Free the memory. */
2128 memset((VOID*)bsd_socket_ptr -> nx_bsd_socket_udp_socket, 0, sizeof(NX_UDP_SOCKET));
2129
2130 tx_block_release((VOID*)bsd_socket_ptr -> nx_bsd_socket_udp_socket);
2131
2132 /* Add this bsd udp socket to the list that map to the same NetX udp socket. */
2133
2134 /* See if this is the only bsd udp socket on the list. */
2135 if ((&nx_bsd_socket_array[i]) == nx_bsd_socket_array[i].nx_bsd_socket_next)
2136 {
2137
2138 /* Yes, the only bsd udp socket on the list. */
2139 /* Update the list. */
2140 bsd_socket_ptr -> nx_bsd_socket_next = &nx_bsd_socket_array[i];
2141 bsd_socket_ptr -> nx_bsd_socket_previous = &nx_bsd_socket_array[i];
2142 nx_bsd_socket_array[i].nx_bsd_socket_next = bsd_socket_ptr;
2143 nx_bsd_socket_array[i].nx_bsd_socket_previous = bsd_socket_ptr;
2144
2145 }
2146 else
2147 {
2148
2149 /* At least one more bsd udp socket on this list. */
2150 /* Update the list. */
2151 bsd_socket_ptr -> nx_bsd_socket_next = nx_bsd_socket_array[i].nx_bsd_socket_next;
2152 bsd_socket_ptr -> nx_bsd_socket_previous = &nx_bsd_socket_array[i];
2153 (nx_bsd_socket_array[i].nx_bsd_socket_next) -> nx_bsd_socket_previous = bsd_socket_ptr;
2154 nx_bsd_socket_array[i].nx_bsd_socket_next = bsd_socket_ptr;
2155 }
2156
2157
2158 bsd_socket_ptr -> nx_bsd_socket_udp_socket = nx_bsd_socket_array[i].nx_bsd_socket_udp_socket;
2159
2160 /* Increase the counter. */
2161 counter = (UINT)bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_reserved_ptr;
2162 counter = ((counter & 0xFFFF0000) + 0x00010000 + (counter & 0x0000FFFF)) & 0xFFFFFFFF;
2163
2164 bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_reserved_ptr = (VOID*)counter;
2165
2166 bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)local_port;
2167 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
2168
2169 /* Release the protection mutex. */
2170 tx_mutex_put(nx_bsd_protection_ptr);
2171
2172 return(NX_SOC_OK);
2173 }
2174 else if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
2175 {
2176
2177 /* Just point this BSD TCP socket to the same secondary socket. */
2178 (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id;
2179
2180 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
2181
2182 bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)local_port;
2183 #if defined(__PRODUCT_NETXDUO__) && !defined(NX_DISABLE_IPV4)
2184 /* Handle client sockets differently. Share the port here for sockets with different IP/IPv6 addresses. */
2185 if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_client_type == NX_TRUE)
2186 {
2187
2188 /* Handle client sockets differently. Share the port here for sockets with different IP/IPv6 addresses. */
2189 if (((bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6) && (nx_bsd_socket_array[i].nx_bsd_socket_family == AF_INET)) ||
2190 ((bsd_socket_ptr -> nx_bsd_socket_family == AF_INET) && (nx_bsd_socket_array[i].nx_bsd_socket_family == AF_INET6)))
2191
2192 {
2193
2194 NX_IP *ip_ptr = nx_bsd_default_ip;
2195 NX_TCP_SOCKET *socket_ptr = bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
2196
2197
2198 /* Calculate the hash index in the TCP port array of the associated IP instance. */
2199 UINT index = (UINT) ((local_port + (local_port >> 8)) & NX_TCP_PORT_TABLE_MASK);
2200
2201 /* This non server socket needs to share a port with the other client socket. */
2202 socket_ptr -> nx_tcp_socket_port = (UINT)local_port;
2203
2204
2205 tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
2206
2207 /* Add this socket to the list of bound sockets. */
2208 socket_ptr -> nx_tcp_socket_bound_next = ip_ptr -> nx_ip_tcp_port_table[index];
2209 socket_ptr -> nx_tcp_socket_bound_previous = (ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous;
2210 ((ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous) -> nx_tcp_socket_bound_next = socket_ptr;
2211 (ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous = socket_ptr;
2212
2213
2214 tx_mutex_put(&ip_ptr -> nx_ip_protection);
2215 }
2216 }
2217 #endif
2218
2219 /* Release the protection mutex. */
2220 tx_mutex_put(nx_bsd_protection_ptr);
2221
2222 return(NX_SOC_OK);
2223 }
2224 }
2225 }
2226
2227 if(address_conflict)
2228 {
2229
2230 break; /* Break out of the for loop */
2231 }
2232 }
2233 }
2234 }
2235
2236 #ifdef NX_BSD_RAW_SUPPORT
2237 if (localAddress -> sa_family == AF_PACKET)
2238 {
2239 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
2240 {
2241
2242 /* Skip its own entry. */
2243 if((i == sockID) ||
2244 /* Skip invalid entries. */
2245 (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE)) ||
2246 /* Skip the entries with different protocol ID */
2247 (nx_bsd_socket_array[i].nx_bsd_socket_protocol != bsd_socket_ptr -> nx_bsd_socket_protocol) ||
2248 /* Skip the entries with different address family. */
2249 (nx_bsd_socket_array[i].nx_bsd_socket_family != bsd_socket_ptr -> nx_bsd_socket_family) ||
2250 /* Skip the unbound entries */
2251 (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND)))
2252 {
2253
2254 continue;
2255 }
2256
2257 if (nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface_index == bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index)
2258 {
2259
2260 /* Bind to same interface. */
2261 address_conflict = 1;
2262 break;
2263 }
2264
2265 if (nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface_index == NX_BSD_LOCAL_IF_INADDR_ANY)
2266 {
2267
2268 /* A socket is bound to any interface. */
2269 address_conflict = 1;
2270 break;
2271 }
2272 }
2273 }
2274 #endif /* NX_BSD_RAW_SUPPORT */
2275
2276 if(address_conflict)
2277 {
2278
2279 /* Release the protection mutex. */
2280 tx_mutex_put(nx_bsd_protection_ptr);
2281
2282 /* Set the socket error if extended socket options enabled. */
2283 nx_bsd_set_errno(EADDRINUSE);
2284
2285 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
2286 return(NX_SOC_ERROR);
2287 }
2288
2289 /* Mark this BSD socket as busy. */
2290 bsd_socket_ptr -> nx_bsd_socket_busy = tx_thread_identify();
2291
2292 /* Determine what type of bind is required. */
2293 if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
2294 {
2295
2296 /* Setup TCP socket pointer. */
2297 tcp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
2298
2299 /* Call NetX to bind the client socket. */
2300 status = nx_tcp_client_socket_bind(tcp_socket_ptr, (UINT)local_port, NX_NO_WAIT);
2301
2302 /* Update the port. */
2303 if((status == NX_SUCCESS) && (local_port == 0))
2304 local_port = (INT)(tcp_socket_ptr -> nx_tcp_socket_port);
2305
2306 }
2307 else if (bsd_socket_ptr -> nx_bsd_socket_udp_socket)
2308 {
2309
2310 /* Set up a pointer to the UDP socket. */
2311 udp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_udp_socket;
2312
2313 /* Bind the UDP socket to the specified port in NetX. */
2314 status = nx_udp_socket_bind(udp_socket_ptr, (UINT)local_port, NX_BSD_TIMEOUT);
2315
2316 /* Update the port. */
2317 if((status == NX_SUCCESS) && (local_port == 0))
2318 local_port = (INT)(udp_socket_ptr -> nx_udp_socket_port);
2319 }
2320 else
2321 {
2322
2323 /* Raw socket. All done. Just need to set status = NX_SUCCESS and continue. */
2324 status = NX_SUCCESS;
2325 }
2326
2327
2328 /* Check if we were able to bind the port. */
2329 if (status == NX_SUCCESS)
2330 {
2331
2332 bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)local_port;
2333 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
2334
2335
2336 /* Make sure this thread is still the owner. */
2337 if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
2338 {
2339
2340 /* Clear the busy flag. */
2341 bsd_socket_ptr -> nx_bsd_socket_busy = TX_NULL;
2342 }
2343
2344 /* Release the protection mutex. */
2345 tx_mutex_put(nx_bsd_protection_ptr);
2346
2347 /* Return successful status. */
2348 return(NX_SOC_OK);
2349
2350 }
2351
2352 /* Release the protection mutex. */
2353 tx_mutex_put(nx_bsd_protection_ptr);
2354
2355 /* Set the socket error, if extended socket options enabled, depending on the status returned by NetX. */
2356 nx_bsd_set_error_code(bsd_socket_ptr, status);
2357
2358 /* Return an error, unsuccessful socket bind call. */
2359 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2360 return(NX_SOC_ERROR);
2361
2362 }
2363
2364
2365 /**************************************************************************/
2366 /* */
2367 /* FUNCTION RELEASE */
2368 /* */
2369 /* listen PORTABLE C */
2370 /* 6.3.0 */
2371 /* AUTHOR */
2372 /* */
2373 /* Yuxin Zhou, Microsoft Corporation */
2374 /* */
2375 /* DESCRIPTION */
2376 /* */
2377 /* This function sets the given socket ready to accept incoming client */
2378 /* connections. The socket must already be associated with a local port*/
2379 /* which means the bind() must have been called previously. */
2380 /* After this call, incoming TCP connections requests addressed to the */
2381 /* local port (and IP address, if specified previously) will be */
2382 /* completed & queued until they are passed to the program via accept()*/
2383 /* */
2384 /* INPUT */
2385 /* */
2386 /* sockID socket descriptor */
2387 /* backlog Maximum number of new */
2388 /* connections queued */
2389 /* */
2390 /* */
2391 /* OUTPUT */
2392 /* */
2393 /* NX_SOC_OK (0) If success */
2394 /* NX_SOC_ERROR (-1) If failure. */
2395 /* */
2396 /* CALLS */
2397 /* */
2398 /* socket Create a server socket */
2399 /* nx_tcp_server_socket_listen Enable a server socket listen */
2400 /* tx_mutex_get Get protection */
2401 /* tx_mutex_put Release protection */
2402 /* */
2403 /* */
2404 /* CALLED BY */
2405 /* */
2406 /* Application Code */
2407 /* */
2408 /* RELEASE HISTORY */
2409 /* */
2410 /* DATE NAME DESCRIPTION */
2411 /* */
2412 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2413 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2414 /* resulting in version 6.1 */
2415 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
2416 /* used new API/structs naming,*/
2417 /* resulting in version 6.3.0 */
2418 /* */
2419 /**************************************************************************/
nx_bsd_listen(INT sockID,INT backlog)2420 INT nx_bsd_listen(INT sockID, INT backlog)
2421 {
2422
2423 UINT status;
2424 NX_BSD_SOCKET *bsd_socket_ptr;
2425 NX_BSD_SOCKET *bsd_secondary_socket;
2426 INT secondary_sockID;
2427 INT ret;
2428
2429
2430 /* Check whether supplied socket ID is valid. */
2431 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
2432 {
2433
2434 /* Set the socket error if extended socket options enabled. */
2435 nx_bsd_set_errno(EBADF);
2436
2437 /* Return an error. */
2438 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2439 return(NX_SOC_ERROR);
2440 }
2441
2442 /* Normalize the socket ID. */
2443 sockID = sockID - NX_BSD_SOCKFD_START;
2444
2445 /* Get the protection mutex. */
2446 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
2447
2448 /* Check the status. */
2449 if (status)
2450 {
2451
2452 /* Set the socket error if extended socket options enabled. */
2453 nx_bsd_set_errno(EACCES);
2454
2455 /* Return an error. */
2456 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
2457 return(NX_SOC_ERROR);
2458 }
2459
2460 /* Set up a pointer to the BSD socket. */
2461 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
2462
2463 /* Determine if the socket is a UDP socket or raw */
2464 if (bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
2465 {
2466
2467 /* The underlying protocol is not TCP, therefore it does not support the listen operation. */
2468 nx_bsd_set_errno(EOPNOTSUPP);
2469
2470 /* Release the protection mutex. */
2471 tx_mutex_put(nx_bsd_protection_ptr);
2472
2473 /* Return an error code. */
2474 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2475 return(NX_SOC_ERROR);
2476 }
2477
2478 /* Is the socket still in use? */
2479 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
2480 {
2481
2482 /* Set the socket error if extended socket options enabled. */
2483 nx_bsd_set_errno(EBADF);
2484
2485 /* Release the protection mutex. */
2486 tx_mutex_put(nx_bsd_protection_ptr);
2487
2488 /* Return error code. */
2489 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2490 return(NX_SOC_ERROR);
2491 }
2492
2493 /* Check if the socket has an error */
2494 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
2495 {
2496 INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
2497
2498 /* Now clear the error code. */
2499 bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
2500
2501 /* Clear the error flag. The application is expected to close the socket at this point.*/
2502 bsd_socket_ptr -> nx_bsd_socket_status_flags =
2503 bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
2504
2505 nx_bsd_set_errno(errcode);
2506
2507 /* Release the protection mutex. */
2508 tx_mutex_put(nx_bsd_protection_ptr);
2509
2510 /* Return an error. */
2511 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2512
2513 /* At this point the error flag is cleared. Application should
2514 detect and handle the error codition. This socket is still bound
2515 to the port (either the application called bind(), or a bind
2516 operation was executed as part of the connect call) is able to
2517 handle another "connect" call, or be closed. */
2518 return(NX_SOC_ERROR);
2519 }
2520
2521 /* Have we already started listening? */
2522 if (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN)
2523 {
2524
2525 /* Error, socket is already listening. */
2526
2527 /* Release the protection mutex. */
2528 tx_mutex_put(nx_bsd_protection_ptr);
2529
2530 /* Set the socket error if extended socket options enabled. */
2531 nx_bsd_set_errno(EINVAL);
2532
2533 /* Return error code. */
2534 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2535 return(NX_SOC_ERROR);
2536 }
2537
2538 /* Check if this is a secondary server socket. */
2539 if (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET)
2540 {
2541
2542 /* Error, socket is a secondary server socket. */
2543
2544 /* Release the protection mutex. */
2545 tx_mutex_put(nx_bsd_protection_ptr);
2546
2547 /* Set the socket error if extended socket options enabled. */
2548 nx_bsd_set_errno(EOPNOTSUPP);
2549
2550 /* Return error code. */
2551 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2552 return(NX_SOC_ERROR);
2553 }
2554
2555 /* Check if bound to a port. */
2556 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND))
2557 {
2558
2559 /* Release the protection mutex. */
2560 tx_mutex_put(nx_bsd_protection_ptr);
2561
2562 /* Set the socket error code. */
2563 nx_bsd_set_errno(EDESTADDRREQ);
2564
2565 /* Return error code. */
2566 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2567 return(NX_SOC_ERROR);
2568 }
2569
2570 /* Check if this master (listening) socket's secondary socket is not marked invalid. If not, it means this socket will
2571 share the secondary socket with another master socket. */
2572 if((bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id != NX_BSD_MAX_SOCKETS)
2573 {
2574
2575 /* It is set. */
2576
2577 secondary_sockID = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id;
2578
2579 bsd_secondary_socket = &nx_bsd_socket_array[secondary_sockID];
2580
2581 /* Now check if the other master socket is in listen mode. */
2582 if(bsd_secondary_socket -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN)
2583 {
2584
2585 /* It is ready.. we are ready to listen on this socket. */
2586
2587 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ENABLE_LISTEN;
2588 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET);
2589 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_client_type = NX_FALSE;
2590 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_SERVER_MASTER_SOCKET;
2591
2592 /* Release the protection mutex. */
2593 tx_mutex_put(nx_bsd_protection_ptr);
2594
2595 return(NX_SOC_OK);
2596 }
2597 }
2598
2599 if(backlog < NX_BSD_TCP_LISTEN_MIN_BACKLOG)
2600 {
2601 backlog = NX_BSD_TCP_LISTEN_MIN_BACKLOG;
2602 }
2603
2604 /* We need to set up this socket as a listen socket. */
2605 ret = nx_bsd_tcp_create_listen_socket(sockID, backlog);
2606
2607 /* Release the mutex protection. */
2608 tx_mutex_put(nx_bsd_protection_ptr);
2609
2610 /* Return success. */
2611 return(ret);
2612 }
2613
2614
2615 /**************************************************************************/
2616 /* */
2617 /* FUNCTION RELEASE */
2618 /* */
2619 /* accept PORTABLE C */
2620 /* 6.3.0 */
2621 /* AUTHOR */
2622 /* */
2623 /* Yuxin Zhou, Microsoft Corporation */
2624 /* */
2625 /* DESCRIPTION */
2626 /* */
2627 /* This function blocks while waiting for connections addressed to the */
2628 /* IP address and port to which this socket is bound. A listen() must */
2629 /* previously have been called on this given socket. */
2630 /* */
2631 /* When a connection arrives and the TCP handshake is successfully */
2632 /* completed, this function returns with a new socket with local and */
2633 /* remote address and port numbers filled in. */
2634 /* */
2635 /* For non blocking sockets, this function returns immediately. */
2636 /* */
2637 /* INPUT */
2638 /* */
2639 /* sockID socket descriptor */
2640 /* clientAddress Originating socket IP address */
2641 /* and port. */
2642 /* addressLength Length of sockaddr buffer (in)*/
2643 /* returned address (out) */
2644 /* */
2645 /* OUTPUT */
2646 /* */
2647 /* socket id Socket ID for new connection */
2648 /* NX_SOC_ERROR (-1) If failure */
2649 /* */
2650 /* CALLS */
2651 /* */
2652 /* memset Clears memory */
2653 /* socket Create a server socket */
2654 /* nx_tcp_server_socket_relisten Relisten with a new TCP soc */
2655 /* nx_tcp_server_socket_accept Accept a client connection */
2656 /* tx_mutex_get Get protection */
2657 /* tx_mutex_put Release protection */
2658 /* tx_thread_identify Gets the current thread */
2659 /* */
2660 /* CALLED BY */
2661 /* */
2662 /* Application Code */
2663 /* */
2664 /* RELEASE HISTORY */
2665 /* */
2666 /* DATE NAME DESCRIPTION */
2667 /* */
2668 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2669 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
2670 /* verified memcpy use cases, */
2671 /* resulting in version 6.1 */
2672 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
2673 /* used new API/structs naming,*/
2674 /* resulting in version 6.3.0 */
2675 /* */
2676 /**************************************************************************/
nx_bsd_accept(INT sockID,struct nx_bsd_sockaddr * ClientAddress,INT * addressLength)2677 INT nx_bsd_accept(INT sockID, struct nx_bsd_sockaddr *ClientAddress, INT *addressLength)
2678 {
2679 /* Define the accept function if NetX BSD accept() is not set to asynchronous (on automatic callback). */
2680
2681 UINT status;
2682 NX_BSD_SOCKET *bsd_socket_ptr;
2683 NX_BSD_SOCKET *bsd_secondary_socket;
2684 INT sec_sock_id;
2685 INT ret = 0;
2686 INT connected = 0;
2687 ULONG requested_events;
2688 INT secondary_socket_id = 0;
2689 #ifndef NX_DISABLE_IPV4
2690 struct nx_bsd_sockaddr_in
2691 peer4_address;
2692 #endif /* NX_DISABLE_IPV4 */
2693 #ifdef FEATURE_NX_IPV6
2694 struct nx_bsd_sockaddr_in6
2695 peer6_address;
2696 #endif
2697
2698
2699 /* Check for valid socket ID. */
2700 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
2701 {
2702
2703 /* Set the socket error if extended socket options enabled. */
2704 nx_bsd_set_errno(EBADF);
2705
2706 /* Return an error.*/
2707 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2708 return(NX_SOC_ERROR);
2709 }
2710
2711 /* Normalize the socket ID. */
2712 sockID = sockID - NX_BSD_SOCKFD_START;
2713
2714 /* Setup pointer to the BSD socket. */
2715 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
2716
2717 /* Get the protection mutex. */
2718 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
2719
2720 /* Check the status. */
2721 if (status != NX_SUCCESS)
2722 {
2723
2724 /* Set the socket error if extended socket options enabled. */
2725 nx_bsd_set_errno(EACCES);
2726
2727 /* Return an error.*/
2728 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
2729 return(NX_SOC_ERROR);
2730 }
2731
2732 /* Is the socket still in use? */
2733 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
2734 {
2735
2736 /* Release the protection mutex. */
2737 tx_mutex_put(nx_bsd_protection_ptr);
2738
2739 /* Set the socket error if extended socket options enabled. */
2740 nx_bsd_set_errno(EBADF);
2741
2742 /* Return an error. */
2743 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2744 return(NX_SOC_ERROR);
2745 }
2746
2747 /* If the socket has an error */
2748 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
2749 {
2750
2751 INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
2752
2753 /* Now clear the error code. */
2754 bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
2755
2756 /* Clear the error flag. The application is expected to close the socket at this point.*/
2757 bsd_socket_ptr -> nx_bsd_socket_status_flags =
2758 bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
2759
2760 nx_bsd_set_errno(errcode);
2761
2762 /* Release the protection mutex. */
2763 tx_mutex_put(nx_bsd_protection_ptr);
2764
2765 /* Return an error. */
2766 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2767
2768 /* At this point the error flag is cleared. Application should
2769 detect and handle the error codition. This socket is still bound
2770 to the port (either the application called bind(), or a bind
2771 operation was executed as part of the connect call) is able to
2772
2773 handle another "connect" call, or be closed. */
2774 return(NX_SOC_ERROR);
2775 }
2776
2777 /* Determine if the socket is a UDP socket. */
2778 if (bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
2779 {
2780
2781 /* Error, UDP or raw sockets do not perform listen. */
2782
2783 /* Release the protection mutex. */
2784 tx_mutex_put(nx_bsd_protection_ptr);
2785
2786 /* Set the socket error if extended socket options enabled. */
2787 nx_bsd_set_errno(EOPNOTSUPP);
2788
2789 /* Return error code. */
2790 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2791 return(NX_SOC_ERROR);
2792 }
2793
2794 /* Has listening been enabled on this socket? */
2795 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN))
2796 {
2797
2798 /* No, this socket is not ready to accept TCP connections. */
2799
2800 /* Release the protection mutex. */
2801 tx_mutex_put(nx_bsd_protection_ptr);
2802
2803 /* Set the socket error if extended socket options enabled. */
2804 nx_bsd_set_errno(EINVAL);
2805
2806 /* Return error code. */
2807 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2808 return(NX_SOC_ERROR);
2809 }
2810
2811 /* Make sure the accept call operates on the master socket. */
2812 if((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) == 0)
2813 {
2814 /* This is not a master socket.
2815 BSD accept is only allowed on the master socket.
2816 Return. */
2817
2818 /* Release the protection mutex. */
2819 tx_mutex_put(nx_bsd_protection_ptr);
2820
2821 /* Set the socket error if extended socket options enabled. */
2822 nx_bsd_set_errno(EBADF);
2823
2824 /* Return error code. */
2825 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2826 return(NX_SOC_ERROR);
2827 }
2828
2829 /* Validate the secondary server socket. */
2830 if ((bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id >= NX_BSD_MAX_SOCKETS)
2831 {
2832
2833 /* This secondary socket is not available yet. This could happen if the
2834 previous accept call fails to allocate a new secondary socket. */
2835 ret = nx_bsd_tcp_create_listen_socket(sockID, 0);
2836
2837 if(ret < 0)
2838 {
2839
2840 /* Failed to allocate a secondary socket, release the protection mutex. */
2841 tx_mutex_put(nx_bsd_protection_ptr);
2842
2843 /* Errno is already set inside nx_bsd_tcp_create_listen_socket. Therefore
2844 there is no need to set errno here. */
2845
2846 /* Return an error. */
2847 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2848 return(NX_SOC_ERROR);
2849 }
2850 }
2851
2852 /* At this point, we have found and marked a secondary server socket for the connection request. */
2853
2854 /* Set up a pointer to the secondary server socket. */
2855 sec_sock_id = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id;
2856 bsd_secondary_socket = &nx_bsd_socket_array[sec_sock_id];
2857
2858 /* Mark this BSD socket as busy. */
2859 bsd_socket_ptr -> nx_bsd_socket_busy = tx_thread_identify();
2860
2861 /* If the master socket is marked as non-blocking, we just need to check if the
2862 secondary socket has a connection already. */
2863 while(!connected)
2864 {
2865
2866 secondary_socket_id = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id;
2867
2868 if((secondary_socket_id < NX_BSD_MAX_SOCKETS) &&
2869 (nx_bsd_socket_array[secondary_socket_id].nx_bsd_socket_union_id.nx_bsd_socket_master_socket_id == sockID) &&
2870 (nx_bsd_socket_array[secondary_socket_id].nx_bsd_socket_status_flags & (NX_BSD_SOCKET_CONNECTED | NX_BSD_SOCKET_ERROR)))
2871 {
2872
2873 connected = 1;
2874 bsd_secondary_socket = &nx_bsd_socket_array[secondary_socket_id];
2875 bsd_secondary_socket -> nx_bsd_socket_family = bsd_socket_ptr -> nx_bsd_socket_family;
2876 bsd_secondary_socket -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
2877
2878 }
2879 else
2880 {
2881
2882 if(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING)
2883 {
2884
2885 /* No connection yet. Return EWOULDBLOCK */
2886
2887 tx_mutex_put(nx_bsd_protection_ptr);
2888
2889 /* Set the socket error if extended socket options enabled. */
2890 nx_bsd_set_errno(EWOULDBLOCK);
2891
2892 /* Return an error. */
2893 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2894
2895 if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
2896 {
2897 bsd_socket_ptr -> nx_bsd_socket_busy = NX_NULL;
2898 }
2899 return(NX_SOC_ERROR);
2900 }
2901
2902 tx_mutex_put(nx_bsd_protection_ptr);
2903 tx_event_flags_get(&nx_bsd_events, NX_BSD_RECEIVE_EVENT, TX_OR_CLEAR, &requested_events, TX_WAIT_FOREVER);
2904 tx_mutex_get(nx_bsd_protection_ptr, TX_WAIT_FOREVER);
2905
2906 /* Verify the socket is still valid. */
2907 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
2908 {
2909 /* The socket is no longer in use. */
2910
2911 /* Set the socket error code. */
2912 nx_bsd_set_errno(EBADF);
2913
2914 /* Release the protection mutex. */
2915 tx_mutex_put(nx_bsd_protection_ptr);
2916
2917 /* Return error code. */
2918 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2919 return(NX_SOC_ERROR);
2920 }
2921 }
2922 }
2923
2924 /* If we get here, we should have a valid connection, or an error occured. */
2925 if(bsd_secondary_socket -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
2926 {
2927 INT errcode = bsd_secondary_socket -> nx_bsd_socket_error_code;
2928
2929 /* Now clear the error code. */
2930 bsd_secondary_socket -> nx_bsd_socket_error_code = 0;
2931
2932 /* Clear the error flag. The application is expected to close the socket at this point.*/
2933 bsd_secondary_socket -> nx_bsd_socket_status_flags =
2934 bsd_secondary_socket -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
2935
2936 nx_bsd_set_errno(errcode);
2937
2938 /* Return an error. */
2939 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2940
2941 /* Release the protection mutex. */
2942 tx_mutex_put(nx_bsd_protection_ptr);
2943
2944 /* At this point the error flag is cleared. Application should
2945 detect and handle the error codition. This socket is still bound
2946 to the port (either the application called bind(), or a bind
2947 operation was executed as part of the connect call) is able to
2948 handle another "connect" call, or be closed. */
2949 return(NX_SOC_ERROR);
2950 }
2951
2952 /* Update the BSD socket source port and sender IP address. */
2953 status = nxd_tcp_socket_peer_info_get(bsd_secondary_socket -> nx_bsd_socket_tcp_socket,
2954 &bsd_secondary_socket -> nx_bsd_socket_source_ip_address,
2955 (ULONG *)(&bsd_secondary_socket -> nx_bsd_socket_source_port));
2956
2957 memcpy(&bsd_secondary_socket -> nx_bsd_socket_peer_ip, &bsd_secondary_socket -> nx_bsd_socket_source_ip_address, sizeof(NXD_ADDRESS)); /* Use case of memcpy is verified. */
2958
2959 bsd_secondary_socket -> nx_bsd_socket_peer_port = (USHORT)(bsd_secondary_socket -> nx_bsd_socket_source_port);
2960
2961 /* Record the peer information. */
2962 #ifndef NX_DISABLE_IPV4
2963 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
2964 {
2965
2966 bsd_secondary_socket -> nx_bsd_socket_source_ip_address.nxd_ip_address.v4 =
2967 bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v4;
2968 }
2969 #endif /* NX_DISABLE_IPV4 */
2970 #ifdef FEATURE_NX_IPV6
2971 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
2972 {
2973
2974 bsd_secondary_socket -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[0] = bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[0];
2975 bsd_secondary_socket -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[1] = bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[1];
2976 bsd_secondary_socket -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[2] = bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[2];
2977 bsd_secondary_socket -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[3] = bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[3];
2978 }
2979 #endif
2980
2981 /* Attempt to obtain peer address if ClientAddress is not NULL. */
2982 if(ClientAddress && addressLength != 0)
2983 {
2984
2985 #ifndef NX_DISABLE_IPV4
2986 /* Handle the IPv4 socket type. */
2987 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
2988 {
2989
2990 /* Update the Client address with socket family, remote host IPv4 address and port. */
2991 peer4_address.sin_family = AF_INET;
2992 peer4_address.sin_addr.s_addr = ntohl(bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v4);
2993 peer4_address.sin_port = ntohs((USHORT)bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_port);
2994
2995 /* Copy the peer address/port info to the ClientAddress. Truncate if
2996 addressLength is smaller than the size of struct sockaddr_in */
2997 if(*addressLength > (INT)sizeof(struct nx_bsd_sockaddr_in))
2998 {
2999
3000 memcpy(ClientAddress, &peer4_address, sizeof(struct nx_bsd_sockaddr_in)); /* Use case of memcpy is verified. */
3001 *addressLength = sizeof(struct nx_bsd_sockaddr_in);
3002 }
3003 else
3004 {
3005 memcpy(ClientAddress, &peer4_address, (UINT)(*addressLength)); /* Use case of memcpy is verified. */
3006 }
3007 }
3008 else
3009 #endif /* NX_DISABLE_IPV4 */
3010
3011 #ifdef FEATURE_NX_IPV6
3012 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
3013 {
3014
3015 /* Update the Client address with socket family, remote host IPv6 address and port. */
3016 peer6_address.sin6_family = AF_INET6;
3017
3018 peer6_address.sin6_addr._S6_un._S6_u32[0] = ntohl(bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[0]);
3019 peer6_address.sin6_addr._S6_un._S6_u32[1] = ntohl(bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[1]);
3020 peer6_address.sin6_addr._S6_un._S6_u32[2] = ntohl(bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[2]);
3021 peer6_address.sin6_addr._S6_un._S6_u32[3] = ntohl(bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[3]);
3022
3023 peer6_address.sin6_port = ntohs((USHORT)bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_port);
3024
3025 if((*addressLength) > (INT)sizeof(peer6_address))
3026 {
3027
3028 memcpy(ClientAddress, &peer6_address, sizeof(peer6_address)); /* Use case of memcpy is verified. */
3029 *addressLength = sizeof(peer6_address);
3030 }
3031 else
3032 {
3033 memcpy(ClientAddress, &peer6_address, (UINT)(*addressLength)); /* Use case of memcpy is verified. */
3034 }
3035 }
3036 else
3037 #endif /* !FEATURE_NX_IPV6 */
3038 {
3039
3040 /* Release the protection mutex. */
3041 tx_mutex_put(nx_bsd_protection_ptr);
3042
3043 /* Set the socket error if extended socket options enabled. */
3044 nx_bsd_set_errno(EINVAL);
3045
3046 /* Make sure this thread is still the owner. */
3047 if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
3048 {
3049
3050 /* Clear the busy flag. */
3051 bsd_socket_ptr -> nx_bsd_socket_busy = TX_NULL;
3052 }
3053
3054 /* Error, IPv6 support is not enabled. */
3055 NX_BSD_ERROR(ERROR, __LINE__);
3056 return(ERROR);
3057 }
3058 }
3059
3060 /* Mark the sock_id field in both the master and secondary socket invalid. */
3061 (bsd_secondary_socket -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id = NX_BSD_MAX_SOCKETS;
3062
3063 /* Clear the master socket connect flags. */
3064 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTED);
3065 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_REQUEST);
3066
3067 /* Reset the master_socket_id */
3068 ret = nx_bsd_tcp_create_listen_socket(sockID, 0);
3069
3070 if(ret < 0)
3071 {
3072 (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = NX_BSD_MAX_SOCKETS;
3073 }
3074
3075 /* Make sure this thread is still the owner. */
3076 if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
3077 {
3078
3079 /* Clear the busy flag. */
3080 bsd_socket_ptr -> nx_bsd_socket_busy = TX_NULL;
3081 }
3082
3083 /* Release the protection mutex. */
3084 tx_mutex_put(nx_bsd_protection_ptr);
3085
3086 return(secondary_socket_id + NX_BSD_SOCKFD_START);
3087
3088 }
3089
3090 /**************************************************************************/
3091 /* */
3092 /* FUNCTION RELEASE */
3093 /* */
3094 /* nx_bsd_send_internal PORTABLE C */
3095 /* 6.3.0 */
3096 /* AUTHOR */
3097 /* */
3098 /* Yuxin Zhou, Microsoft Corporation */
3099 /* */
3100 /* DESCRIPTION */
3101 /* */
3102 /* This is sends a message to a given destination address/port */
3103 /* */
3104 /* INPUT */
3105 /* */
3106 /* sockID BSD Socket ID */
3107 /* msg Pointer to the outgoing */
3108 /* message */
3109 /* msgLength The Size of the message */
3110 /* flags Control flags, support */
3111 /* MSG_DONTWAIT */
3112 /* dst_address The Destination Address */
3113 /* dst_port The Destination Port */
3114 /* local_inteterface_index The local outgoing interface */
3115 /* to use */
3116 /* */
3117 /* OUTPUT */
3118 /* */
3119 /* data_sent */
3120 /* */
3121 /* CALLS */
3122 /* */
3123 /* set_errno Sets the BSD errno */
3124 /* nx_packet_allocate Allocate a packet */
3125 /* nx_packet_data_append Append data to the packet */
3126 /* tx_mutex_get Get Mutex protection */
3127 /* tx_mutex_put Release Mutex protection */
3128 /* nx_packet_release Release the packet on error */
3129 /* nx_udp_socket_send UDP packet send */
3130 /* nx_udp_socket_interface_send UDP packet send via a */
3131 /* specific interface */
3132 /* nx_tcp_socket_send TCP packet send */
3133 /* _nxd_bsd_ipv4_packet_send Raw IPv4 packet with header */
3134 /* included */
3135 /* _nxd_bsd_ipv6_packet_send Raw IPv6 packet with header */
3136 /* included */
3137 /* nxd_ip_raw_packet_interface_send Raw packet send via a */
3138 /* specific interface */
3139 /* CALLED BY */
3140 /* */
3141 /* send */
3142 /* sendto */
3143 /* */
3144 /* RELEASE HISTORY */
3145 /* */
3146 /* DATE NAME DESCRIPTION */
3147 /* */
3148 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3149 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3150 /* resulting in version 6.1 */
3151 /* 10-31-2023 Tiejun Zhou Modified comment(s), */
3152 /* supported random IP id, */
3153 /* resulting in version 6.3.0 */
3154 /* */
3155 /**************************************************************************/
nx_bsd_send_internal(INT sockID,const CHAR * msg,INT msgLength,INT flags,NXD_ADDRESS * dst_address,USHORT dst_port,UINT local_interface_index)3156 static INT nx_bsd_send_internal(INT sockID, const CHAR *msg, INT msgLength, INT flags,
3157 NXD_ADDRESS *dst_address, USHORT dst_port, UINT local_interface_index)
3158 {
3159 UINT status;
3160 NX_PACKET *packet_ptr;
3161 NX_TCP_SOCKET *tcp_socket_ptr;
3162 NX_UDP_SOCKET *udp_socket_ptr;
3163 NX_BSD_SOCKET *bsd_socket_ptr;
3164 UINT packet_type = 0;
3165 UINT wait_option;
3166 ULONG data_sent = (ULONG)msgLength;
3167
3168 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
3169
3170 #ifndef NX_DISABLE_IPV4
3171 /* Determine the socket family for allocating a packet. */
3172 if (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
3173 {
3174
3175 /* This is for an IPv4 socket. */
3176 if (bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
3177 {
3178
3179 /* Allocate an IPv4 UDP packet. */
3180 packet_type = NX_IPv4_UDP_PACKET;
3181 }
3182 else if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
3183 {
3184
3185 /* Allocate an IPv4 TCP packet. */
3186 packet_type = NX_IPv4_TCP_PACKET;
3187 }
3188 else if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE)
3189 {
3190
3191 packet_type = NX_PHYSICAL_HEADER;
3192 }
3193 else
3194 {
3195
3196 /* Raw socket. */
3197 packet_type = NX_IPv4_PACKET;
3198 }
3199 }
3200 #endif /* NX_DISABLE_IPV4 */
3201 if (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
3202 {
3203
3204 /* This is for an IPv6 socket. */
3205 if (bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
3206 {
3207
3208 /* Allocate an IPv4 UDP packet. */
3209 packet_type = NX_IPv6_UDP_PACKET;
3210 }
3211 else if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
3212 {
3213 /* Allocate an IPv4 TCP packet. */
3214 packet_type = NX_IPv6_TCP_PACKET;
3215 }
3216 else if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE)
3217 {
3218 packet_type = NX_PHYSICAL_HEADER;
3219 }
3220 else
3221 {
3222 /* Raw socket. */
3223 packet_type = NX_IPv6_PACKET;
3224 }
3225 }
3226
3227 /* Allocate the packet for sending. */
3228 if(packet_type == 0)
3229 {
3230 /* Set the socket error. */
3231 nx_bsd_set_errno(EINVAL);
3232
3233 /* Return an error status.*/
3234 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3235 return(NX_SOC_ERROR);
3236 }
3237
3238 /* Is this a non blocking socket? */
3239 if ((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING) ||
3240 (flags & MSG_DONTWAIT))
3241 {
3242
3243 /* Yes, set to wait to zero on the NetX call. */
3244 wait_option = 0 ;
3245 }
3246 /* Does this socket have a send timeout option set? */
3247 else if (bsd_socket_ptr -> nx_bsd_option_send_timeout)
3248 {
3249
3250 /* Yes, this is our wait option. */
3251 wait_option = bsd_socket_ptr -> nx_bsd_option_send_timeout;
3252 }
3253 else
3254 wait_option = TX_WAIT_FOREVER;
3255
3256 status = nx_packet_allocate(nx_bsd_default_packet_pool, &packet_ptr, packet_type, wait_option);
3257
3258 /* Check for errors. */
3259 if (status != NX_SUCCESS)
3260 {
3261
3262 /* Set the socket error. */
3263 nx_bsd_set_errno(ENOBUFS);
3264
3265 /* Return an error status.*/
3266 NX_BSD_ERROR(status, __LINE__);
3267 return(NX_SOC_ERROR);
3268 }
3269
3270 /* Now copy the data into the NetX packet. */
3271 status = nx_packet_data_append(packet_ptr, (VOID *) msg, (ULONG)msgLength, nx_bsd_default_packet_pool, wait_option);
3272
3273 /* Was the data copy successful? */
3274 if (status != NX_SUCCESS)
3275 {
3276
3277 nx_packet_release(packet_ptr);
3278
3279 /* Set the socket error. */
3280 nx_bsd_set_errno(ENOBUFS);
3281
3282 /* Return an error status.*/
3283 NX_BSD_ERROR(status, __LINE__);
3284 return(NX_SOC_ERROR);
3285 }
3286
3287
3288 /* Get the protection mutex. */
3289 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
3290
3291 /* Check the status. */
3292 if (status != NX_SUCCESS)
3293 {
3294
3295 /* Release the packet. */
3296 nx_packet_release(packet_ptr);
3297
3298 /* Set the socket error if extended socket options enabled. */
3299 nx_bsd_set_errno(EACCES);
3300
3301 /* Return an error status.*/
3302 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
3303 return(NX_SOC_ERROR);
3304 }
3305
3306
3307 /* Is the socket still in use? */
3308 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
3309 {
3310
3311 nx_packet_release(packet_ptr);
3312
3313 /* Set the socket error if extended options enabled. */
3314 nx_bsd_set_errno(EBADF);
3315
3316 /* Release the protection mutex. */
3317 tx_mutex_put(nx_bsd_protection_ptr);
3318
3319 /* Return an error status.*/
3320 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3321 return(NX_SOC_ERROR);
3322 }
3323
3324
3325 /* Determine if the socket is a UDP socket. */
3326 if (bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
3327 {
3328
3329 /* Pickup the NetX UDP socket. */
3330 udp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_udp_socket;
3331
3332 /* Send the UDP packet. */
3333 if(local_interface_index == NX_BSD_LOCAL_IF_INADDR_ANY)
3334 status = nxd_udp_socket_send(udp_socket_ptr, packet_ptr, dst_address, dst_port);
3335 else
3336 status = nxd_udp_socket_interface_send(udp_socket_ptr, packet_ptr, dst_address, dst_port, local_interface_index);
3337 }
3338 else if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
3339 {
3340
3341 /* We have a TCP socket and a packet ready to send. */
3342
3343 /* Set a pointer to the TCP BSD socket. */
3344 tcp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
3345
3346 if(wait_option != TX_NO_WAIT)
3347 {
3348 /* Release the protection mutex. */
3349 tx_mutex_put(nx_bsd_protection_ptr);
3350 }
3351
3352 /* Send the TCP packet. */
3353 status = nx_tcp_socket_send(tcp_socket_ptr, packet_ptr, wait_option);
3354
3355 /* Check partial data sent. */
3356 if (status)
3357 {
3358
3359 /* Get length of data sent. */
3360 data_sent -= packet_ptr -> nx_packet_length;
3361
3362 if (data_sent)
3363 {
3364
3365 /* Partial data sent. Mark as success. */
3366 status = NX_SUCCESS;
3367
3368 /* Release the packet. */
3369 nx_packet_release(packet_ptr);
3370 }
3371 }
3372
3373 if(wait_option != TX_NO_WAIT)
3374 {
3375 /* Obtain the protection mutex. */
3376 tx_mutex_get(nx_bsd_protection_ptr, TX_WAIT_FOREVER);
3377 }
3378 }
3379 else
3380 {
3381 /* Is this BSD socket configured to append the IP header? */
3382 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE)
3383 {
3384
3385 /* Yes it is. Make sure the packet source and destination interface are set. */
3386 ULONG *ip_addr_ptr;
3387 UINT src_interface;
3388
3389 #ifndef NX_DISABLE_IPV4
3390 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
3391 {
3392
3393 ip_addr_ptr = (ULONG*)(packet_ptr -> nx_packet_prepend_ptr + 12);
3394
3395 src_interface = (UINT)nx_bsd_find_interface_by_source_addr(AF_INET, ip_addr_ptr);
3396
3397 if(src_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
3398 src_interface = 0;
3399
3400 packet_ptr -> nx_packet_address.nx_packet_interface_ptr = &(nx_bsd_default_ip -> nx_ip_interface[src_interface]);
3401
3402 /* If the IP ID field is non-zero, the current nx_ip_packet_id
3403 value is modified */
3404 if((*(packet_ptr -> nx_packet_prepend_ptr + 4) == 0) &&
3405 (*(packet_ptr -> nx_packet_prepend_ptr + 5) == 0))
3406 {
3407
3408 #ifdef NX_ENABLE_IP_ID_RANDOMIZATION
3409 ULONG rand_id = (ULONG)NX_RAND();
3410 *(packet_ptr -> nx_packet_prepend_ptr + 4) = (UCHAR)((rand_id & 0xFFFF) >> 8);
3411 *(packet_ptr -> nx_packet_prepend_ptr + 5) = (UCHAR)(rand_id & 0xFF);
3412 #else
3413 *(packet_ptr -> nx_packet_prepend_ptr + 4) = (UCHAR)(((nx_bsd_default_ip -> nx_ip_packet_id) & 0xFFFF) >> 8);
3414 *(packet_ptr -> nx_packet_prepend_ptr + 5) = (UCHAR)((nx_bsd_default_ip -> nx_ip_packet_id) & 0xFF);
3415 #endif /* NX_ENABLE_IP_ID_RANDOMIZATION */
3416 }
3417
3418 /* Clear the checksum field. */
3419 *(packet_ptr -> nx_packet_prepend_ptr + 10) = 0;
3420 *(packet_ptr -> nx_packet_prepend_ptr + 11) = 0;
3421
3422 _nxd_bsd_ipv4_packet_send(packet_ptr);
3423
3424 status = NX_SUCCESS;
3425 }
3426 #endif /* NX_DISABLE_IPV4 */
3427 #ifdef FEATURE_NX_IPV6
3428 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
3429 {
3430
3431 ip_addr_ptr = (ULONG*)(packet_ptr -> nx_packet_prepend_ptr + 8);
3432 src_interface = (UINT)nx_bsd_find_interface_by_source_addr(AF_INET6, ip_addr_ptr);
3433
3434 if(src_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
3435 {
3436 status = NX_NOT_SUCCESSFUL;
3437 }
3438
3439 else
3440 {
3441
3442 NX_IPV6_HEADER *ipv6_header;
3443 ULONG src_addr[4], dest_addr[4];
3444
3445 packet_ptr -> nx_packet_ip_header = packet_ptr -> nx_packet_prepend_ptr;
3446
3447 packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr = &nx_bsd_default_ip -> nx_ipv6_address[src_interface];
3448
3449 ipv6_header = (NX_IPV6_HEADER*)packet_ptr -> nx_packet_ip_header;
3450
3451 /* Set up source / Destination IP */
3452 COPY_IPV6_ADDRESS(ipv6_header -> nx_ip_header_destination_ip, dest_addr);
3453 COPY_IPV6_ADDRESS(ipv6_header -> nx_ip_header_source_ip, src_addr);
3454 NX_IPV6_ADDRESS_CHANGE_ENDIAN(dest_addr);
3455 NX_IPV6_ADDRESS_CHANGE_ENDIAN(src_addr);
3456
3457
3458 _nxd_bsd_ipv6_packet_send(packet_ptr, src_addr, dest_addr);
3459
3460 status = NX_SUCCESS;
3461 }
3462 }
3463 #endif
3464 }
3465 else
3466 {
3467
3468 /* Raw socket without any IP header appended yet. We can send this directly to the NetX Duo IP packet handler. */
3469 if(local_interface_index == NX_BSD_LOCAL_IF_INADDR_ANY)
3470 local_interface_index = 0;
3471
3472 status = nxd_ip_raw_packet_interface_send(nx_bsd_default_ip, packet_ptr, dst_address,
3473 local_interface_index, bsd_socket_ptr -> nx_bsd_socket_protocol,
3474 NX_IP_TIME_TO_LIVE, NX_IP_NORMAL);
3475 }
3476 }
3477
3478 /* Was the packet send successful? */
3479 if (status != NX_SUCCESS)
3480 {
3481
3482 /* No, release the packet. */
3483 nx_packet_release(packet_ptr);
3484
3485 /* Set the socket error. */
3486
3487 /* Set the socket error according to the NetX error status returned. */
3488 switch (status)
3489 {
3490
3491 case NX_IP_ADDRESS_ERROR:
3492 nx_bsd_set_errno(EDESTADDRREQ);
3493 break;
3494
3495 case NX_NOT_ENABLED:
3496 nx_bsd_set_errno(EPROTONOSUPPORT);
3497 break;
3498
3499 case NX_NOT_CONNECTED:
3500 nx_bsd_set_errno(ENOTCONN);
3501 break;
3502
3503 case NX_NO_PACKET:
3504 case NX_UNDERFLOW:
3505 nx_bsd_set_errno(ENOBUFS);
3506 break;
3507
3508 case NX_WINDOW_OVERFLOW:
3509 case NX_WAIT_ABORTED:
3510 case NX_TX_QUEUE_DEPTH:
3511 if ((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING) ||
3512 (flags & MSG_DONTWAIT))
3513 nx_bsd_set_errno( EWOULDBLOCK);
3514 else
3515 nx_bsd_set_errno(ETIMEDOUT);
3516 break;
3517
3518 default:
3519 /* NX_NOT_BOUND */
3520 /* NX_PTR_ERROR */
3521 /* NX_INVALID_PACKET */
3522 nx_bsd_set_errno(EINVAL);
3523 break;
3524 }
3525
3526 /* Return an error status. */
3527 NX_BSD_ERROR(status, __LINE__);
3528
3529 /* Release the protection mutex. */
3530 tx_mutex_put(nx_bsd_protection_ptr);
3531
3532 return(NX_SOC_ERROR);
3533 }
3534
3535 /* Release the protection mutex. */
3536 tx_mutex_put(nx_bsd_protection_ptr);
3537
3538 return((INT)data_sent);
3539 }
3540
3541 /**************************************************************************/
3542 /* */
3543 /* FUNCTION RELEASE */
3544 /* */
3545 /* send PORTABLE C */
3546 /* 6.3.0 */
3547 /* AUTHOR */
3548 /* */
3549 /* Yuxin Zhou, Microsoft Corporation */
3550 /* */
3551 /* DESCRIPTION */
3552 /* */
3553 /* This function sends a packet out the given socket. */
3554 /* When the call returns, the data has been queued for transmission */
3555 /* over the connection. The return value indicates the number of byes */
3556 /* actually transmitted. */
3557 /* */
3558 /* The flags argument is provided for consistency with the BSD send */
3559 /* service. It allows various protocol features, such as out-of-bound */
3560 /* out-of-bound data, to be accessed. However, none of these features */
3561 /* are implemented. */
3562 /* */
3563 /* If packets are being sent out a UDP socket which is not bound to a */
3564 /* local port, this function find an available free port to bind to the*/
3565 /* socket. For TCP sockets, the socket must already by connected (so */
3566 /* also bound to port) */
3567 /* */
3568 /* Note: send() does not support raw sockets. Use the sendto() service */
3569 /* to transmit raw packets. */
3570 /* */
3571 /* INPUT */
3572 /* */
3573 /* sockID Socket */
3574 /* msg Data to be transmitted */
3575 /* msgLength Number of bytes to be sent */
3576 /* flags Control flags, support */
3577 /* MSG_DONTWAIT */
3578 /* */
3579 /* OUTPUT */
3580 /* */
3581 /* number of bytes sent If successful */
3582 /* NX_SOC_ERROR (-1) If failure */
3583 /* */
3584 /* CALLS */
3585 /* */
3586 /* nx_tcp_socket_send Send a packet */
3587 /* nx_packet_allocate Get a free packet */
3588 /* nx_packet_data_append Copy data into packet */
3589 /* nx_packet_release Free a packet used to send */
3590 /* tx_mutex_get Get protection */
3591 /* tx_mutex_put Release protection */
3592 /* */
3593 /* CALLED BY */
3594 /* */
3595 /* Application Code */
3596 /* */
3597 /* RELEASE HISTORY */
3598 /* */
3599 /* DATE NAME DESCRIPTION */
3600 /* */
3601 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3602 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3603 /* resulting in version 6.1 */
3604 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
3605 /* used new API/structs naming,*/
3606 /* resulting in version 6.3.0 */
3607 /* */
3608 /**************************************************************************/
nx_bsd_send(INT sockID,const CHAR * msg,INT msgLength,INT flags)3609 INT nx_bsd_send(INT sockID, const CHAR *msg, INT msgLength, INT flags)
3610 {
3611
3612 NX_BSD_SOCKET *bsd_socket_ptr;
3613
3614
3615 /* Check for invalid socket IDd. */
3616 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
3617 {
3618
3619 /* Set the socket error if extended options enabled. */
3620 nx_bsd_set_errno(EBADF);
3621
3622 /* Return an error status.*/
3623 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3624 return(NX_SOC_ERROR);
3625 }
3626
3627 /* Normalize the socket ID. */
3628 sockID = sockID - NX_BSD_SOCKFD_START;
3629
3630 /* Set up a pointer to the BSD socket. */
3631 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
3632
3633 /* If the socket has an error */
3634 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
3635 {
3636 INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
3637
3638 /* Now clear the error code. */
3639 bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
3640
3641 /* Clear the error flag. The application is expected to close the socket at this point.*/
3642 bsd_socket_ptr -> nx_bsd_socket_status_flags =
3643 bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
3644
3645 nx_bsd_set_errno(errcode);
3646
3647 /* Return an error. */
3648 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3649
3650 /* At this point the error flag is cleared. Application should
3651 detect and handle the error codition. This socket is still bound
3652 to the port (either the application called bind(), or a bind
3653 operation was executed as part of the connect call) is able to
3654 handle another "connect" call, or be closed. */
3655 return(NX_SOC_ERROR);
3656 }
3657
3658 /* Send() requires the socket be connected. A connected socket implies the socket is bound.*/
3659 if((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED) == 0)
3660 {
3661
3662 /* For AF_PACKET family, user shall use the sendto call. */
3663 #if defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)
3664 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
3665 {
3666 /* Set the socket error */
3667 nx_bsd_set_errno(ENOTCONN);
3668
3669 /* Return an error status.*/
3670 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3671 return(NX_SOC_ERROR);
3672 }
3673
3674 #endif /* defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT) */
3675
3676 /* However if the socket is raw socket and HDR_INCLUDE is set, it is OK. */
3677 if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE))
3678 {
3679 /* Set the socket error */
3680 nx_bsd_set_errno(ENOTCONN);
3681
3682 /* Return an error status.*/
3683 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3684 return(NX_SOC_ERROR);
3685 }
3686 }
3687
3688 return nx_bsd_send_internal(sockID, msg, msgLength, flags,
3689 &bsd_socket_ptr -> nx_bsd_socket_peer_ip,
3690 bsd_socket_ptr -> nx_bsd_socket_peer_port,
3691 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index);
3692
3693 }
3694
3695
3696 /**************************************************************************/
3697 /* */
3698 /* FUNCTION RELEASE */
3699 /* */
3700 /* sendto PORTABLE C */
3701 /* 6.3.0 */
3702 /* AUTHOR */
3703 /* */
3704 /* Yuxin Zhou, Microsoft Corporation */
3705 /* */
3706 /* DESCRIPTION */
3707 /* */
3708 /* This function sends a packet out the given socket. */
3709 /* When the call returns, the data has been queued for transmission */
3710 /* over the connection. To use sendto on a TCP BSD socket, the */
3711 /* socket must already be in connected state. */
3712 /* */
3713 /* The flags argument is provided for consistency with the BSD send */
3714 /* service. It allows various protocol features, such as out-of-bound */
3715 /* out-of-bound data, to be accessed. However, none of these features */
3716 /* are implemented. */
3717 /* */
3718 /* INPUT */
3719 /* */
3720 /* sockID Socket (must be connected). */
3721 /* msg Data to transmit. */
3722 /* msgLength Number of bytes to send */
3723 /* flags Control flags, support */
3724 /* MSG_DONTWAIT */
3725 /* sockaddr Destination address */
3726 /* destAddrLen Length of destination address */
3727 /* */
3728 /* OUTPUT */
3729 /* */
3730 /* Number of bytes sent If no error occurs */
3731 /* NX_SOC_ERROR (-1) In case of socket error */
3732 /* */
3733 /* CALLS */
3734 /* */
3735 /* bind Bind NetX UDP sockets */
3736 /* nx_packet_allocate Get a free packet */
3737 /* nx_packet_data_append Copy data into packet */
3738 /* nx_packet_release Free the nx_packet used */
3739 /* nx_tcp_socket_send Send packet over a TCP Socket */
3740 /* nx_udp_socket_send Send packet over a UDP Socket */
3741 /* tx_mutex_get Get protection */
3742 /* tx_mutex_put Release protection */
3743 /* */
3744 /* CALLED BY */
3745 /* */
3746 /* Application Code */
3747 /* */
3748 /* RELEASE HISTORY */
3749 /* */
3750 /* DATE NAME DESCRIPTION */
3751 /* */
3752 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3753 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3754 /* resulting in version 6.1 */
3755 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
3756 /* used new API/structs naming,*/
3757 /* resulting in version 6.3.0 */
3758 /* */
3759 /**************************************************************************/
nx_bsd_sendto(INT sockID,CHAR * msg,INT msgLength,INT flags,struct nx_bsd_sockaddr * destAddr,INT destAddrLen)3760 INT nx_bsd_sendto(INT sockID, CHAR *msg, INT msgLength, INT flags, struct nx_bsd_sockaddr *destAddr, INT destAddrLen)
3761 {
3762 UINT status;
3763 NX_BSD_SOCKET *bsd_socket_ptr;
3764 NXD_ADDRESS peer_ip_address;
3765 USHORT peer_port = 0;
3766
3767 /* Check for a valid socket ID. */
3768 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
3769 {
3770
3771 /* Set the socket error if extended options enabled. */
3772 nx_bsd_set_errno(EBADF);
3773
3774 /* Return an error status. */
3775 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3776 return(NX_SOC_ERROR);
3777 }
3778
3779 /* Set up a socket pointer to the BSD socket. */
3780 bsd_socket_ptr = &nx_bsd_socket_array[sockID - NX_BSD_SOCKFD_START];
3781
3782 /* If the socket has an error */
3783 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
3784 {
3785 INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
3786
3787 /* Now clear the error code. */
3788 bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
3789
3790 /* Clear the error flag. The application is expected to close the socket at this point.*/
3791 bsd_socket_ptr -> nx_bsd_socket_status_flags =
3792 bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
3793
3794 nx_bsd_set_errno(errcode);
3795
3796 /* Return an error. */
3797 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3798
3799 /* At this point the error flag is cleared. Application should
3800 detect and handle the error codition. This socket is still bound
3801 to the port (either the application called bind(), or a bind
3802 operation was executed as part of the connect call) is able to
3803 handle another "connect" call, or be closed. */
3804 return(NX_SOC_ERROR);
3805 }
3806 /* For TCP, make sure the socket is already connected. */
3807 if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
3808 {
3809 if((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED) == 0)
3810 {
3811 nx_bsd_set_errno(ENOTCONN);
3812
3813 /* Return an error. */
3814 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3815
3816 return(NX_SOC_ERROR);
3817 }
3818 return nx_bsd_send_internal((sockID - NX_BSD_SOCKFD_START), msg, msgLength, flags, NX_NULL, 0,
3819 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index);
3820 }
3821 else
3822 {
3823
3824 /* This is a UDP or raw socket. */
3825
3826 /* Check whther or not the socket is AF_PACKET family. */
3827 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
3828 {
3829
3830 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
3831 /* nx_bsd_pppoe_internal_sendto shall returns */
3832 status = (UINT)nx_bsd_pppoe_internal_sendto(bsd_socket_ptr, msg, msgLength, flags, destAddr, destAddrLen);
3833 #elif defined(NX_BSD_RAW_SUPPORT)
3834 /* _nx_bsd_hardware_internal_sendto shall returns */
3835 status = (UINT)_nx_bsd_hardware_internal_sendto(bsd_socket_ptr, msg, msgLength, flags, destAddr, destAddrLen);
3836 #else
3837 NX_PARAMETER_NOT_USED(destAddrLen);
3838 status = (UINT)NX_SOC_ERROR;
3839 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
3840 return((INT)status);
3841
3842 }
3843
3844 /* Perform error checkings on the remote address if the socket is
3845 not raw socket, or HDRINCL is not set for the raw socket. */
3846 if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE))
3847 {
3848
3849 /* Check for an invalid destination. */
3850 if (destAddr == NX_NULL)
3851 {
3852
3853 /* Set the socket error if extended socket options enabled. */
3854 nx_bsd_set_errno(EINVAL);
3855
3856 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3857 return(NX_SOC_ERROR);
3858 }
3859
3860 /* Validate the destination address. */
3861 if(bsd_socket_ptr -> nx_bsd_socket_family != destAddr -> sa_family)
3862 {
3863 nx_bsd_set_errno(EAFNOSUPPORT);
3864
3865 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3866
3867 return(NX_SOC_ERROR);
3868 }
3869 }
3870
3871 /* For UDP socket, make sure the socket is bound. */
3872 if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
3873 {
3874 if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND))
3875 {
3876 status = nx_udp_socket_bind(bsd_socket_ptr -> nx_bsd_socket_udp_socket, NX_ANY_PORT, NX_NO_WAIT);
3877 if((status != NX_SUCCESS) && (status != NX_ALREADY_BOUND))
3878 {
3879 nx_bsd_set_errno(EINVAL);
3880
3881 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3882
3883 return(NX_SOC_ERROR);
3884 }
3885
3886 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
3887 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
3888 bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)(bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_port);
3889 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
3890 }
3891
3892 }
3893
3894
3895
3896 if(destAddr)
3897 {
3898 /* Get the destination IP and port for this UDP socket. */
3899 #ifndef NX_DISABLE_IPV4
3900 if (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
3901 {
3902
3903 /* This is for an IPv4 packet. */
3904 peer_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
3905 peer_ip_address.nxd_ip_address.v4 = htonl(((struct nx_bsd_sockaddr_in *) destAddr) -> sin_addr.s_addr);
3906 peer_port = htons(((struct nx_bsd_sockaddr_in *) destAddr) -> sin_port);
3907
3908 /* Local interface ID is set to invalid value, so the send routine needs to
3909 find the best interface to send the packet based on destination IP address. */
3910
3911 }
3912 #endif /* NX_DISABLE_IPV4 */
3913 #ifdef FEATURE_NX_IPV6
3914 if (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
3915 {
3916
3917 /* This is for an IPv6 packet. Set the NetX Duo IP address version. */
3918 peer_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
3919
3920 peer_ip_address.nxd_ip_address.v6[0] = ntohl(((struct nx_bsd_sockaddr_in6*)destAddr) -> sin6_addr._S6_un._S6_u32[0]);
3921 peer_ip_address.nxd_ip_address.v6[1] = ntohl(((struct nx_bsd_sockaddr_in6*)destAddr) -> sin6_addr._S6_un._S6_u32[1]);
3922 peer_ip_address.nxd_ip_address.v6[2] = ntohl(((struct nx_bsd_sockaddr_in6*)destAddr) -> sin6_addr._S6_un._S6_u32[2]);
3923 peer_ip_address.nxd_ip_address.v6[3] = ntohl(((struct nx_bsd_sockaddr_in6*)destAddr) -> sin6_addr._S6_un._S6_u32[3]);
3924
3925 peer_port = htons(((struct nx_bsd_sockaddr_in6 *) destAddr) -> sin6_port);
3926
3927 }
3928 #endif
3929 }
3930
3931 /* Call the internal send routine to finish the send process. */
3932 /* Local interface ID is set to a special marker, so the send routine needs to
3933 find the best interface to send the packet based on destination IP address. */
3934 return nx_bsd_send_internal((sockID - NX_BSD_SOCKFD_START), msg, msgLength, flags,
3935 &peer_ip_address, peer_port,
3936 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index);
3937
3938 }
3939 }
3940
3941
3942 /**************************************************************************/
3943 /* */
3944 /* FUNCTION RELEASE */
3945 /* */
3946 /* recv PORTABLE C */
3947 /* 6.3.0 */
3948 /* AUTHOR */
3949 /* */
3950 /* Yuxin Zhou, Microsoft Corporation */
3951 /* */
3952 /* DESCRIPTION */
3953 /* */
3954 /* This function copies up to a specified number of bytes received on */
3955 /* the socket into specified location. The given socket must be in the */
3956 /* connected state. Normally, the call blocks until either at least one*/
3957 /* byte is returned or the connection closes.The return value indicates*/
3958 /* the number of bytes actually copied into the buffer starting at the */
3959 /* specified location. */
3960 /* */
3961 /* For a stream socket, the bytes are delivered in the same order as */
3962 /* they were transmitted, without omissions. For a datagram socket, */
3963 /* each recv() returns the data from at most one send(), and order is */
3964 /* not necessarily preserved. */
3965 /* */
3966 /* For non blocking sockets, a receive status of NX_NO_PACKET from NetX*/
3967 /* results in an error status returned from BSD, and the socket error */
3968 /* set to EWOULDBLOCK (if BSD extended socket features are enabled. */
3969 /* */
3970 /* Likewise, an event flag status of TX_NO_EVENTS returned from ThreadX*/
3971 /* on a non blocking socket sets the socket error to EWOULDBLOCK. */
3972 /* */
3973 /* INPUT */
3974 /* */
3975 /* sockID Socket (must be connected). */
3976 /* rcvBuffer Pointer to put data received. */
3977 /* bufferLength Maximum bytes in buffer */
3978 /* flags Control flags, support */
3979 /* MSG_PEEK and MSG_DONTWAIT */
3980 /* */
3981 /* OUTPUT */
3982 /* */
3983 /* Number of bytes received If success */
3984 /* NX_SOC_ERROR (-1) If failure */
3985 /* 0 socket disconnected */
3986 /* */
3987 /* CALLS */
3988 /* */
3989 /* nx_tcp_socket_receive Receive a Packet */
3990 /* nx_packet_allocate Allocate packet for receive */
3991 /* nx_packet_release Free the nx_packet after use */
3992 /* nx_packet_data_extract_offset Retrieve packet data */
3993 /* tx_event_flags_get Wait for data to arrive */
3994 /* tx_mutex_get Get protection */
3995 /* tx_mutex_put Release protection */
3996 /* */
3997 /* CALLED BY */
3998 /* */
3999 /* Application Code */
4000 /* */
4001 /* RELEASE HISTORY */
4002 /* */
4003 /* DATE NAME DESCRIPTION */
4004 /* */
4005 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4006 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
4007 /* verified memcpy use cases, */
4008 /* resulting in version 6.1 */
4009 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
4010 /* used new API/structs naming,*/
4011 /* resulting in version 6.3.0 */
4012 /* */
4013 /**************************************************************************/
nx_bsd_recv(INT sockID,VOID * rcvBuffer,INT bufferLength,INT flags)4014 INT nx_bsd_recv(INT sockID, VOID *rcvBuffer, INT bufferLength, INT flags)
4015 {
4016
4017 UINT status;
4018 NX_PACKET *packet_ptr;
4019 NX_BSD_SOCKET *bsd_socket_ptr;
4020 NX_TCP_SOCKET *tcp_socket_ptr;
4021 ULONG requested_events;
4022 ULONG bytes_received;
4023 UINT wait_option;
4024 UINT remaining_wait_option;
4025 ULONG offset;
4026 INT header_size = 0;
4027 ULONG start_time = nx_bsd_system_clock;
4028
4029
4030 /* Check for a valid socket ID. */
4031 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
4032 {
4033
4034 /* Set the socket error if extended options enabled. */
4035 nx_bsd_set_errno(EBADF);
4036
4037 /* Return an error. */
4038 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4039
4040 return(NX_SOC_ERROR);
4041 }
4042
4043 /* Normalize the socket ID. */
4044 sockID = sockID - NX_BSD_SOCKFD_START;
4045
4046 /* Set up a pointer to the socket. */
4047 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
4048
4049 /* Set the receive wait time to FOREVER for blocking sockets. */
4050 wait_option = NX_WAIT_FOREVER;
4051
4052 /* Is this a nonblocking socket?: */
4053 if ((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING) ||
4054 (flags & MSG_DONTWAIT))
4055 {
4056
4057 /* Yes, set to receive wait option to no wait (zero). */
4058 wait_option = 0;
4059 }
4060 /* Does this socket have a receive timeout option set? */
4061 else if (bsd_socket_ptr -> nx_bsd_option_receive_timeout)
4062 {
4063
4064 /* Yes, this is our wait option. */
4065 wait_option = bsd_socket_ptr -> nx_bsd_option_receive_timeout;
4066 }
4067
4068 /* Get the protection mutex. */
4069 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
4070
4071 /* Check the status. */
4072 if (status)
4073 {
4074
4075 /* Set the socket error if extended socket options enabled. */
4076 nx_bsd_set_errno(EACCES);
4077
4078 /* Return an error. */
4079 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
4080 return(NX_SOC_ERROR);
4081 }
4082
4083 /* If the socket has an error */
4084 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
4085 {
4086
4087 INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
4088
4089 /* Now clear the error code. */
4090 bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
4091
4092 /* Clear the error flag. The application is expected to close the socket at this point.*/
4093 bsd_socket_ptr -> nx_bsd_socket_status_flags =
4094 bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
4095
4096 nx_bsd_set_errno(errcode);
4097
4098 /* Release the protection mutex. */
4099 tx_mutex_put(nx_bsd_protection_ptr);
4100
4101 /* Return an error. */
4102 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4103
4104 /* At this point the error flag is cleared. The application should
4105 detect and handle the error codition. This socket is still bound
4106 to the port (either the application called bind(), or a bind
4107 operation was executed as part of the connect call) and is able to
4108 handle another "connect" call, or be closed. */
4109 return(NX_SOC_ERROR);
4110 }
4111
4112 /* Set pointers to the BSD NetX Duo sockets. */
4113 tcp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
4114
4115 /* Loop to check for a received packet. */
4116 do
4117 {
4118
4119 /* Is the socket still in use? */
4120 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
4121 {
4122
4123 /* Set the socket error if extended options enabled. */
4124 nx_bsd_set_errno(EBADF);
4125
4126 /* Release the protection mutex. */
4127 tx_mutex_put(nx_bsd_protection_ptr);
4128
4129 /* Return an error. */
4130 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4131 return(NX_SOC_ERROR);
4132 }
4133
4134 /* Check if the BSD socket already has received a packet. */
4135 packet_ptr = bsd_socket_ptr -> nx_bsd_socket_received_packet;
4136
4137 if (packet_ptr)
4138 {
4139
4140 /* Got one. Break out of the loop. */
4141 break;
4142 }
4143
4144 /* Check if there is an incoming packet on this socket. */
4145 else
4146 {
4147
4148 /* Determine if this is a TCP BSD socket. */
4149 if (tcp_socket_ptr)
4150 {
4151
4152 /* It is, check the socket TCP receive queue with a zero wait option (no suspension). */
4153 status = nx_tcp_socket_receive(tcp_socket_ptr, &packet_ptr, TX_NO_WAIT);
4154
4155 /* Check for no packet on the queue. */
4156 if (status == NX_NOT_CONNECTED)
4157 {
4158
4159 /* Release the protection mutex. */
4160 tx_mutex_put(nx_bsd_protection_ptr);
4161
4162 /* Is peer shutdown orderly? */
4163 if ((tcp_socket_ptr -> nx_tcp_socket_state == NX_TCP_CLOSE_WAIT) ||
4164 (tcp_socket_ptr -> nx_tcp_socket_state >= NX_TCP_CLOSING))
4165 {
4166
4167 /* Yes. Return 0. */
4168 return(NX_SUCCESS);
4169 }
4170
4171 /* Set the socket status (not really an error). */
4172 nx_bsd_set_errno(ENOTCONN);
4173
4174 /* Return an error. */
4175 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4176 return(NX_SOC_ERROR);
4177 }
4178
4179 if (status == NX_SUCCESS)
4180 {
4181
4182 /* Increase the received count. */
4183 bsd_socket_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
4184 bsd_socket_ptr -> nx_bsd_socket_received_packet_count++;
4185 }
4186 }
4187
4188 /* Have we found a new packet? */
4189 if ((status == NX_SUCCESS) && (packet_ptr))
4190 {
4191
4192 /* Setup the bsd socket with the packet information. */
4193 bsd_socket_ptr -> nx_bsd_socket_received_packet = packet_ptr;
4194 bsd_socket_ptr -> nx_bsd_socket_received_packet_offset = 0;
4195
4196 /* Get out of the loop. */
4197 break;
4198 }
4199 }
4200
4201 /* No packet is available. */
4202
4203 /* Release the protection mutex. */
4204 tx_mutex_put(nx_bsd_protection_ptr);
4205
4206 /* Calculate remaining wait option. */
4207 remaining_wait_option = (UINT)(wait_option - (nx_bsd_system_clock - start_time));
4208 if (remaining_wait_option > wait_option)
4209 {
4210
4211 /* Wait option expired. */
4212 status = TX_NO_EVENTS;
4213 }
4214 else
4215 {
4216
4217 /* Suspend this socket on a RECEIVE event (incoming packet) for the specified wait time. */
4218 status = tx_event_flags_get(&nx_bsd_events, NX_BSD_RECEIVE_EVENT, TX_OR_CLEAR, &requested_events, remaining_wait_option);
4219 }
4220
4221 /* Check for any events. */
4222 if (status == TX_NO_EVENTS)
4223 {
4224
4225 /* No packets received. */
4226
4227 /* Set the socket error depending if this is a non blocking socket. */
4228 if ((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING) ||
4229 (wait_option == NX_WAIT_FOREVER) ||
4230 (flags & MSG_DONTWAIT))
4231 nx_bsd_set_errno(EWOULDBLOCK);
4232 else
4233 nx_bsd_set_errno(EAGAIN);
4234
4235 /* Return an error. */
4236 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4237 return(NX_SOC_ERROR);
4238 }
4239 else if (status != TX_SUCCESS)
4240 {
4241
4242 /* Set the socket error if extended socket options enabled. */
4243 nx_bsd_set_errno(EINVAL);
4244
4245 /* Return an error. */
4246 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4247 return(NX_SOC_ERROR);
4248 }
4249
4250 /* Re-obtain the protection mutex. */
4251 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
4252
4253 /* Check the status. */
4254 if (status)
4255 {
4256
4257 /* Set the socket error if extended socket options enabled. */
4258 nx_bsd_set_errno(EACCES);
4259
4260 /* Return an error. */
4261 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
4262 return(NX_SOC_ERROR);
4263 }
4264
4265 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
4266 {
4267 /* The socket is no longer in use. */
4268
4269 /* Set the socket error code. */
4270 nx_bsd_set_errno(EBADF);
4271
4272 /* Release the protection mutex. */
4273 tx_mutex_put(nx_bsd_protection_ptr);
4274
4275 /* Return error code. */
4276 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4277 return(NX_SOC_ERROR);
4278 }
4279
4280 } while (1);
4281
4282 /* At this point, the socket has received a packet. */
4283
4284
4285 /* Obtain sender information for UDP socket. */
4286 if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
4287 {
4288
4289 /* Get the sender and port from the UDP packet. */
4290 nxd_udp_source_extract(packet_ptr, &bsd_socket_ptr -> nx_bsd_socket_source_ip_address, (UINT *)&bsd_socket_ptr -> nx_bsd_socket_source_port);
4291 }
4292
4293 #if defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)
4294 else if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
4295 {
4296
4297 /* Validate the packet length. */
4298 if (packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr < 14)
4299 {
4300
4301 /* Set the socket error if extended socket options enabled. */
4302 nx_bsd_set_errno(EINVAL);
4303
4304 /* Release the protection mutex. */
4305 tx_mutex_put(nx_bsd_protection_ptr);
4306
4307 /* Release the packet. */
4308 nx_packet_release(packet_ptr);
4309
4310 /* Return an error. */
4311 NX_BSD_ERROR(status, __LINE__);
4312 return(NX_SOC_ERROR);
4313 }
4314
4315 /* Pick up the sender's MAC address. */
4316 bsd_socket_ptr -> nx_bsd_socket_sll_addr[0] = packet_ptr -> nx_packet_prepend_ptr[6];
4317 bsd_socket_ptr -> nx_bsd_socket_sll_addr[1] = packet_ptr -> nx_packet_prepend_ptr[7];
4318 bsd_socket_ptr -> nx_bsd_socket_sll_addr[2] = packet_ptr -> nx_packet_prepend_ptr[8];
4319 bsd_socket_ptr -> nx_bsd_socket_sll_addr[3] = packet_ptr -> nx_packet_prepend_ptr[9];
4320 bsd_socket_ptr -> nx_bsd_socket_sll_addr[4] = packet_ptr -> nx_packet_prepend_ptr[10];
4321 bsd_socket_ptr -> nx_bsd_socket_sll_addr[5] = packet_ptr -> nx_packet_prepend_ptr[11];
4322
4323 /* Pick up the sender's protocol */
4324 bsd_socket_ptr -> nx_bsd_socket_sll_protocol = (USHORT)((packet_ptr -> nx_packet_prepend_ptr[12] << 8) |
4325 (packet_ptr -> nx_packet_prepend_ptr[13]));
4326 if (bsd_socket_ptr -> nx_bsd_socket_sll_protocol == 0x8100)
4327 {
4328
4329 /* Skip VLAN tag. */
4330 bsd_socket_ptr -> nx_bsd_socket_sll_protocol = (USHORT)((packet_ptr -> nx_packet_prepend_ptr[16] << 8) |
4331 (packet_ptr -> nx_packet_prepend_ptr[17]));
4332 }
4333
4334 /* Find the IF Index */
4335 bsd_socket_ptr -> nx_bsd_socket_sll_ifindex = packet_ptr -> nx_packet_ip_interface -> nx_interface_index;
4336
4337 }
4338 #endif /* defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT) */
4339
4340
4341 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4342 /* For raw socket, make sure the source address is extracted. */
4343 else if(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET)
4344 {
4345
4346 /* Get the sender IP address from the raw packet. */
4347 status = nx_bsd_raw_packet_info_extract(packet_ptr, &(bsd_socket_ptr -> nx_bsd_socket_source_ip_address), NX_NULL);
4348 }
4349 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
4350
4351 /* Pickup the current offset. */
4352 offset = bsd_socket_ptr -> nx_bsd_socket_received_packet_offset;
4353
4354 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4355 /* Perform extra processing on this packet if it processed as a raw packet. */
4356 if((bsd_socket_ptr -> nx_bsd_socket_family != AF_PACKET) &&
4357 (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET))
4358 {
4359
4360 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & (NX_BSD_SOCKET_RX_NO_HDR))
4361 {
4362 header_size = 0;
4363 }
4364 else
4365 {
4366 #ifndef NX_DISABLE_IPV4
4367 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
4368 {
4369
4370
4371 header_size = packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_ip_header;
4372
4373 /* Byte-Swap the basic IPv4 header. The NetX Duo IP receive process does not
4374 examine the extension header. Therefore it does not perform byte swap
4375 on extension headers. */
4376 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_word_0));
4377 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_word_1));
4378 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_word_2));
4379 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_source_ip));
4380 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_destination_ip));
4381
4382 if(bufferLength < header_size)
4383 {
4384 header_size = bufferLength;
4385 }
4386 }
4387 #endif /* NX_DISABLE_IPV4 */
4388 #ifdef FEATURE_NX_IPV6
4389 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
4390 {
4391
4392 NX_IPV6_HEADER *ipv6_header_ptr;
4393 UCHAR next_header_type;
4394
4395 header_size = (INT)(packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_ip_header);
4396
4397 if(bufferLength < header_size)
4398 {
4399
4400 header_size = bufferLength;
4401 }
4402
4403 ipv6_header_ptr = (NX_IPV6_HEADER*)packet_ptr -> nx_packet_ip_header;
4404
4405 /* Pick up the next header. */
4406 next_header_type = (ipv6_header_ptr -> nx_ip_header_word_1 >> 8) & 0xFF;
4407
4408 NX_CHANGE_ULONG_ENDIAN(ipv6_header_ptr -> nx_ip_header_word_0);
4409 NX_CHANGE_ULONG_ENDIAN(ipv6_header_ptr -> nx_ip_header_word_1);
4410 NX_IPV6_ADDRESS_CHANGE_ENDIAN(ipv6_header_ptr -> nx_ip_header_destination_ip);
4411 NX_IPV6_ADDRESS_CHANGE_ENDIAN(ipv6_header_ptr -> nx_ip_header_source_ip);
4412
4413 /* Go through the rest of the IPv6 extension headers. */
4414 _nxd_bsd_swap_ipv6_extension_headers(packet_ptr, next_header_type);
4415 }
4416 #endif
4417
4418 memcpy(rcvBuffer, packet_ptr -> nx_packet_ip_header, (UINT)header_size); /* Use case of memcpy is verified. */
4419 }
4420 }
4421 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
4422
4423
4424 /* Copy the packet data into the supplied buffer. */
4425 status = nx_packet_data_extract_offset(packet_ptr, offset, (VOID*)((INT)rcvBuffer + header_size), (ULONG) (bufferLength - header_size), &bytes_received);
4426
4427 /* Check for an error. */
4428 if (status)
4429 {
4430
4431 /* Set the socket error if extended socket options enabled. */
4432 nx_bsd_set_errno(EINVAL);
4433
4434 /* Release the protection mutex. */
4435 tx_mutex_put(nx_bsd_protection_ptr);
4436
4437 /* Release the packet. */
4438 nx_packet_release(packet_ptr);
4439
4440 /* Return an error. */
4441 NX_BSD_ERROR( status, __LINE__);
4442 return(NX_SOC_ERROR);
4443 }
4444
4445 if((flags & MSG_PEEK) == 0)
4446 {
4447
4448 /* Calculate the new offset. */
4449 offset = offset + bytes_received;
4450
4451 /* Determine if all the packet data was consumed. */
4452 if(packet_ptr -> nx_packet_length <= offset)
4453 {
4454
4455 bsd_socket_ptr -> nx_bsd_socket_received_packet = packet_ptr -> nx_packet_queue_next;
4456
4457 /* Release the packet. */
4458 nx_packet_release(packet_ptr);
4459
4460 /* Clear the offset. */
4461 bsd_socket_ptr -> nx_bsd_socket_received_packet_offset = 0;
4462 }
4463 else if((bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
4464 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
4465 || (bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
4466 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
4467 )
4468 {
4469
4470 /* For UDP or raw socket, We extracted as much as can fit in the caller's buffer.
4471 We will discard the remaining bytes. */
4472 bsd_socket_ptr -> nx_bsd_socket_received_packet = packet_ptr -> nx_packet_queue_next;
4473
4474 bytes_received = packet_ptr -> nx_packet_length;
4475
4476 /* No need to retain the packet. */
4477 nx_packet_release(packet_ptr);
4478
4479 /* Clear the offset. */
4480 bsd_socket_ptr -> nx_bsd_socket_received_packet_offset = 0;
4481 }
4482 else
4483 {
4484
4485 /* For TCP, the remaining data is saved for the next recv call.
4486 Just update the offset. */
4487 bsd_socket_ptr -> nx_bsd_socket_received_packet_offset = offset;
4488 }
4489 bsd_socket_ptr -> nx_bsd_socket_received_byte_count -= bytes_received;
4490 bsd_socket_ptr -> nx_bsd_socket_received_packet_count--;
4491 }
4492
4493 /* Release the protection mutex. */
4494 tx_mutex_put(nx_bsd_protection_ptr);
4495
4496 /* Successful received a packet. Return the number of bytes copied to buffer. */
4497 return((INT)bytes_received + (INT)header_size);
4498 }
4499
4500
4501 /**************************************************************************/
4502 /* */
4503 /* FUNCTION RELEASE */
4504 /* */
4505 /* recvfrom PORTABLE C */
4506 /* 6.3.0 */
4507 /* AUTHOR */
4508 /* */
4509 /* Yuxin Zhou, Microsoft Corporation */
4510 /* */
4511 /* DESCRIPTION */
4512 /* */
4513 /* This function copies up to a specified number of bytes, received on */
4514 /* the socket into a specified location. To use recvfrom() on a TCP */
4515 /* socket requires the socket to be in the connected state. */
4516 /* */
4517 /* This function is identical to recv() except for returning the sender*/
4518 /* address and length if non null arguments are supplied. */
4519 /* */
4520 /* INPUT */
4521 /* */
4522 /* sockID Socket(must be connected) */
4523 /* buffer Pointer to hold data received */
4524 /* bufferSize Maximum number of bytes */
4525 /* flags Control flags, support */
4526 /* MSG_PEEK and MSG_DONTWAIT */
4527 /* fromAddr Address data of sender */
4528 /* fromAddrLen Length of address structure */
4529 /* */
4530 /* OUTPUT */
4531 /* */
4532 /* number of bytes received If no error occurs */
4533 /* NX_SOC_ERROR (-1) In case of any error */
4534 /* */
4535 /* CALLS */
4536 /* */
4537 /* memset Clear memory */
4538 /* nx_packet_allocate Allocate a packet */
4539 /* nx_packet_data_extract_offset Extract packet data */
4540 /* nx_packet_release Free the packet used */
4541 /* tx_mutex_get Get protection */
4542 /* tx_mutex_put Release protection */
4543 /* tx_event_flags_get Wait for data to arrive */
4544 /* */
4545 /* CALLED BY */
4546 /* */
4547 /* Application Code */
4548 /* */
4549 /* RELEASE HISTORY */
4550 /* */
4551 /* DATE NAME DESCRIPTION */
4552 /* */
4553 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4554 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
4555 /* verified memcpy use cases, */
4556 /* resulting in version 6.1 */
4557 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
4558 /* used new API/structs naming,*/
4559 /* resulting in version 6.3.0 */
4560 /* */
4561 /**************************************************************************/
nx_bsd_recvfrom(INT sockID,CHAR * rcvBuffer,INT bufferLength,INT flags,struct nx_bsd_sockaddr * fromAddr,INT * fromAddrLen)4562 INT nx_bsd_recvfrom(INT sockID, CHAR *rcvBuffer, INT bufferLength, INT flags, struct nx_bsd_sockaddr *fromAddr, INT *fromAddrLen)
4563 {
4564
4565 INT bytes_received;
4566 NX_BSD_SOCKET *bsd_socket_ptr;
4567 #ifndef NX_DISABLE_IPV4
4568 struct nx_bsd_sockaddr_in
4569 peer4_address;
4570 #endif /* NX_DISABLE_IPV4 */
4571 #ifdef FEATURE_NX_IPV6
4572 struct nx_bsd_sockaddr_in6
4573 peer6_address;
4574 #endif
4575
4576 /* Check for a valid socket ID. */
4577 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
4578 {
4579
4580 /* Set the socket error if extended options enabled. */
4581 nx_bsd_set_errno(EBADF);
4582 /* Return an error. */
4583 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4584 return(NX_SOC_ERROR);
4585 }
4586
4587 /* Set up a pointer to the socket. */
4588 bsd_socket_ptr = &nx_bsd_socket_array[sockID - NX_BSD_SOCKFD_START];
4589
4590 /* Socket error checking is done inside recv() call. */
4591
4592 /* Call the equivalent recv() function. */
4593 bytes_received = nx_bsd_recv(sockID, rcvBuffer, bufferLength, flags);
4594
4595 /* Check for error. */
4596 if (bytes_received < 0)
4597 {
4598
4599 /* Return an error status. */
4600 return NX_SOC_ERROR;
4601 }
4602 /* If no bytes are received do not handle as an error. */
4603 else if (bytes_received == 0)
4604 {
4605 return NX_SOC_OK;
4606 }
4607
4608 /* At this point we did receive a packet. */
4609 /* Supply the sender address if valid pointer is supplied. */
4610 if(fromAddr && (*fromAddrLen != 0))
4611 {
4612
4613 #ifndef NX_DISABLE_IPV4
4614 /* Handle the IPv4 socket type. */
4615 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
4616 {
4617 /* Update the Client address with socket family, remote host IPv4 address and port. */
4618 peer4_address.sin_family = AF_INET;
4619 if(bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
4620 {
4621 peer4_address.sin_addr.s_addr = htonl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v4);
4622 peer4_address.sin_port = htons(bsd_socket_ptr -> nx_bsd_socket_peer_port);
4623 }
4624 else
4625 {
4626 peer4_address.sin_addr.s_addr = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v4);
4627
4628 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4629 if(!(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET))
4630 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
4631 peer4_address.sin_port = ntohs((USHORT)bsd_socket_ptr -> nx_bsd_socket_source_port);
4632 }
4633 /* Copy the peer address/port info to the ClientAddress. Truncate if
4634 addressLength is smaller than the size of struct sockaddr_in */
4635 if(*fromAddrLen > (INT)sizeof(struct nx_bsd_sockaddr_in))
4636 {
4637 *fromAddrLen = sizeof(struct nx_bsd_sockaddr_in);
4638 }
4639 memcpy(fromAddr, &peer4_address, (UINT)(*fromAddrLen)); /* Use case of memcpy is verified. */
4640 }
4641 else
4642 #endif /* NX_DISABLE_IPV4 */
4643
4644 #ifdef FEATURE_NX_IPV6
4645 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
4646 {
4647 /* Update the Client address with socket family, remote host IPv6 address and port. */
4648 peer6_address.sin6_family = AF_INET6;
4649
4650 if(bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
4651 {
4652 peer6_address.sin6_addr._S6_un._S6_u32[0] = ntohl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[0]);
4653 peer6_address.sin6_addr._S6_un._S6_u32[1] = ntohl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[1]);
4654 peer6_address.sin6_addr._S6_un._S6_u32[2] = ntohl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[2]);
4655 peer6_address.sin6_addr._S6_un._S6_u32[3] = ntohl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[3]);
4656 peer6_address.sin6_port = ntohs(bsd_socket_ptr -> nx_bsd_socket_peer_port);
4657 }
4658 else
4659 {
4660 peer6_address.sin6_addr._S6_un._S6_u32[0] = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[0]);
4661 peer6_address.sin6_addr._S6_un._S6_u32[1] = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[1]);
4662 peer6_address.sin6_addr._S6_un._S6_u32[2] = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[2]);
4663 peer6_address.sin6_addr._S6_un._S6_u32[3] = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[3]);
4664
4665 /* Skip the port data for raw sockets. They do not use them. */
4666 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4667 if(!(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET))
4668 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
4669 peer6_address.sin6_port = ntohs((USHORT)bsd_socket_ptr -> nx_bsd_socket_source_port);
4670 }
4671
4672 if((*fromAddrLen) > (INT)sizeof(peer6_address))
4673 {
4674 *fromAddrLen = sizeof(peer6_address);
4675 }
4676 memcpy(fromAddr, &peer6_address, (UINT)(*fromAddrLen)); /* Use case of memcpy is verified. */
4677
4678 }
4679 else
4680 #endif /* !FEATURE_NX_IPV6 */
4681 #if defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT)
4682 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
4683 {
4684 if(*fromAddrLen >= (INT)sizeof(struct nx_bsd_sockaddr_ll))
4685 {
4686 struct nx_bsd_sockaddr_ll *sockaddr = (struct nx_bsd_sockaddr_ll*)fromAddr;
4687 INT i;
4688 sockaddr -> sll_family = AF_PACKET;
4689 sockaddr -> sll_protocol = bsd_socket_ptr -> nx_bsd_socket_sll_protocol;
4690 sockaddr -> sll_ifindex = bsd_socket_ptr -> nx_bsd_socket_sll_ifindex;
4691 sockaddr -> sll_hatype = 0;
4692 sockaddr -> sll_pkttype = 0;
4693 sockaddr -> sll_halen = 6;
4694 for(i = 0; i < 6; i++)
4695 sockaddr -> sll_addr[i] = bsd_socket_ptr -> nx_bsd_socket_sll_addr[i];
4696 *fromAddrLen = sizeof(struct nx_bsd_sockaddr_ll);
4697 }
4698
4699 }
4700 else
4701 #endif
4702 {
4703
4704 /* Release the protection mutex. */
4705 tx_mutex_put(nx_bsd_protection_ptr);
4706
4707 /* Set the socket error if extended socket options enabled. */
4708 nx_bsd_set_errno(EINVAL);
4709
4710 /* Error, IPv6 support is not enabled. */
4711 NX_BSD_ERROR(ERROR, __LINE__);
4712 return(ERROR);
4713 }
4714 }
4715
4716 /* Successfully received a packet. Return bytes received. */
4717 return (INT)(bytes_received);
4718 }
4719
4720
4721 /**************************************************************************/
4722 /* */
4723 /* FUNCTION RELEASE */
4724 /* */
4725 /* soc_close PORTABLE C */
4726 /* 6.3.0 */
4727 /* AUTHOR */
4728 /* */
4729 /* Yuxin Zhou, Microsoft Corporation */
4730 /* */
4731 /* DESCRIPTION */
4732 /* */
4733 /* This function terminates communications on the supplied BSD socket. */
4734 /* The socket is disallowed for further sends and receives. Socket */
4735 /* resources such as socket memory are returned to the system. */
4736 /* */
4737 /* If a socket is enabled with the linger option, that will be used in */
4738 /* place of the default NX_BSD TIMEOUT for blocking sockets. Sockets */
4739 /* enabled for non blocking have their timeout set for zero. Note that */
4740 /* a zero wait option results in an immediate shutdown (e.g. send RST) */
4741 /* unless the NX_DISABLE_RESET_DISCONNECT is not enabled. */
4742 /* */
4743 /* For BSD applications enabled for disconnect complete notification */
4744 /* for TCP sockets, the socket will remain open until NetX notifies us */
4745 /* that the disconnect is complete. This allows the host BSD */
4746 /* application to perform asynchronous disconnects without having to */
4747 /* wait for the disconnect to complete. */
4748 /* */
4749 /* INPUT */
4750 /* */
4751 /* socketID */
4752 /* */
4753 /* OUTPUT */
4754 /* */
4755 /* NX_SOC_OK (0) On success */
4756 /* NX_SOC_ERROR (-1) On failure */
4757 /* */
4758 /* CALLS */
4759 /* */
4760 /* memset Clear memory */
4761 /* nx_tcp_socket_disconnect Disconnect a TCP Socket */
4762 /* nx_tcp_client_socket_unbind Unbind the socket */
4763 /* nx_tcp_server_socket_unaccept Unaccept the socket */
4764 /* nx_tcp_server_socket_unlisten Unlisten on a port */
4765 /* nx_tcp_socket_delete Deletes a TCP Socket */
4766 /* nx_udp_socket_unbind Unbind a UDP Socket */
4767 /* nx_udp_socket_delete Deletes a UDP Socket */
4768 /* tx_block_release Release block for socket */
4769 /* tx_mutex_get Get protection */
4770 /* tx_mutex_put Release protection */
4771 /* */
4772 /* CALLED BY */
4773 /* */
4774 /* Application Code */
4775 /* */
4776 /* RELEASE HISTORY */
4777 /* */
4778 /* DATE NAME DESCRIPTION */
4779 /* */
4780 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4781 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4782 /* resulting in version 6.1 */
4783 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
4784 /* used new API/structs naming,*/
4785 /* resulting in version 6.3.0 */
4786 /* */
4787 /**************************************************************************/
nx_bsd_soc_close(INT sockID)4788 INT nx_bsd_soc_close(INT sockID)
4789 {
4790
4791 NX_BSD_SOCKET *bsd_socket_ptr;
4792 NX_TCP_SOCKET *tcp_socket_ptr;
4793 NX_UDP_SOCKET *udp_socket_ptr;
4794 NX_PACKET *packet_ptr;
4795 NX_PACKET *next_packet_ptr;
4796 ULONG timeout;
4797 INT i;
4798 UINT counter;
4799 INT delete_socket;
4800 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4801 INT protocol;
4802 UINT index;
4803 #endif
4804
4805 /* Check for a valid socket ID. */
4806 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
4807 {
4808
4809 /* Set the socket error. */
4810 nx_bsd_set_errno(EBADF);
4811
4812 /* Error, invalid socket ID. */
4813 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4814 return(NX_SOC_ERROR);
4815 }
4816
4817 /* Normalize the socket ID. */
4818 sockID = sockID - NX_BSD_SOCKFD_START;
4819
4820 /* Set up a pointer to the BSD socket. */
4821 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
4822
4823 /* Get the protection mutex. */
4824 tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
4825
4826 /* Is the socket already in use? */
4827 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
4828 {
4829
4830 /* No; If the NetX socket associated with this BSD socket been deleted, this is ok. */
4831 if (!bsd_socket_ptr -> nx_bsd_socket_tcp_socket && !bsd_socket_ptr -> nx_bsd_socket_udp_socket)
4832 {
4833
4834 /* Yes, no further action possible. Release the protection mutex. */
4835 tx_mutex_put(nx_bsd_protection_ptr);
4836
4837 return NX_SOC_OK;
4838 }
4839
4840 /* Otherwise, it is an error if socket not in use anymore. */
4841
4842 /* Release the protection mutex. */
4843 tx_mutex_put(nx_bsd_protection_ptr);
4844
4845 /* Set the socket error if extended socket options enabled. */
4846 nx_bsd_set_errno(EACCES);
4847
4848 /* Return error. */
4849 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4850 return(NX_SOC_ERROR);
4851 }
4852
4853 /* Set NetX socket pointers. */
4854 tcp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
4855 udp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_udp_socket;
4856
4857 /* There is. Flush the queue of all packets. */
4858 packet_ptr = bsd_socket_ptr -> nx_bsd_socket_received_packet;
4859 /* Setup packet pointer to the beginning of the queue. */
4860 while(packet_ptr)
4861 {
4862 next_packet_ptr = packet_ptr -> nx_packet_queue_next;
4863
4864 /* Mark it as allocated so it will be released. */
4865 packet_ptr -> nx_packet_queue_next = (NX_PACKET *) NX_PACKET_ALLOCATED;
4866
4867 nx_packet_release(packet_ptr);
4868
4869 /* Move to the next packet */
4870 packet_ptr = next_packet_ptr;
4871 }
4872
4873 bsd_socket_ptr -> nx_bsd_socket_received_packet = NX_NULL;
4874 bsd_socket_ptr -> nx_bsd_socket_received_packet_tail = NX_NULL;
4875 bsd_socket_ptr -> nx_bsd_socket_received_byte_count = 0;
4876 bsd_socket_ptr -> nx_bsd_socket_received_packet_count = 0;
4877 bsd_socket_ptr -> nx_bsd_socket_received_packet_count_max = 0;
4878
4879 /* Now delete the underlying TCP or UDP socket. */
4880
4881 /* Is this a TCP socket? */
4882 if (tcp_socket_ptr)
4883 {
4884
4885 /* If the socket has not been closed, disconnect it. This would be the case
4886 if NetX already closed the socket e.g. a RST packet received before the
4887 host application called this function. */
4888 if (tcp_socket_ptr -> nx_tcp_socket_state != NX_TCP_CLOSED)
4889 {
4890
4891 /* Disconnect the socket. */
4892
4893 /* If the disconnect takes more than the timeout option, NetX marks the socket as "closed"
4894 or puts it back to "listen" state. The default value is 1 to emulate an immediate
4895 socket closure without sending a RST packet. */
4896 timeout = NX_BSD_TCP_SOCKET_DISCONNECT_TIMEOUT;
4897
4898 /* Release the mutex while disconnecting. */
4899 tx_mutex_put(nx_bsd_protection_ptr);
4900
4901 nx_tcp_socket_disconnect(tcp_socket_ptr, timeout);
4902
4903 tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
4904
4905 /* Verify that the socket is still valid. */
4906 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
4907 {
4908 /* The socket is no longer in use. */
4909
4910 /* Set the socket error code. */
4911 nx_bsd_set_errno(EBADF);
4912
4913 /* Release the protection mutex. */
4914 tx_mutex_put(nx_bsd_protection_ptr);
4915
4916 /* Return error code. */
4917 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4918 return(NX_SOC_ERROR);
4919 }
4920 }
4921 /* Make sure the socket is unbound, not accepting connections and not bound to a listening port. */
4922 if(tcp_socket_ptr -> nx_tcp_socket_port)
4923 {
4924
4925 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CLIENT)
4926 {
4927 nx_tcp_client_socket_unbind(tcp_socket_ptr);
4928 }
4929 else
4930 {
4931 nx_tcp_server_socket_unaccept(tcp_socket_ptr);
4932 }
4933
4934 }
4935
4936 /* Now we can delete the NetX TCP socket. */
4937 nx_tcp_socket_delete(tcp_socket_ptr);
4938
4939 /* Clear the TCP socket structure. */
4940 memset((VOID *) tcp_socket_ptr, 0, sizeof(NX_TCP_SOCKET));
4941
4942 /* Release the NetX TCP socket. */
4943 tx_block_release((VOID *) tcp_socket_ptr);
4944
4945 /* If this is the master server socket, we need to unaccept the
4946 associated secondary socket. */
4947 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET)
4948 {
4949
4950 INT sec_soc_id = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id;
4951
4952 if(sec_soc_id < NX_BSD_MAX_SOCKETS)
4953 {
4954
4955 /* Find whether or not this is the only master socket that is connected to this
4956 secondary socket. */
4957 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
4958 {
4959
4960 if(i == sockID)
4961 continue;
4962
4963 if((nx_bsd_socket_array[i].nx_bsd_socket_protocol == NX_PROTOCOL_TCP) &&
4964 (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) &&
4965 (nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id == sec_soc_id))
4966 {
4967 break;
4968 }
4969 }
4970
4971 if(i == NX_BSD_MAX_SOCKETS)
4972 {
4973
4974 /* Unaccept and unlisten on the socket/port */
4975 /* nx_tcp_server_socket_unaccept(tcp_socket_ptr); */
4976 /* nx_tcp_server_socket_unlisten(nx_bsd_default_ip, tcp_socket_ptr -> nx_tcp_socket_port); */
4977
4978 /* Release the secondary socket if there are no more master sockets associated
4979 with this secondary socket. */
4980
4981 tcp_socket_ptr = nx_bsd_socket_array[sec_soc_id].nx_bsd_socket_tcp_socket;
4982
4983 /* If the secondary socket has not been closed, disconnect it. This would be the case
4984 if NetX already closed the master socket. */
4985 if (tcp_socket_ptr -> nx_tcp_socket_state != NX_TCP_CLOSED)
4986 {
4987
4988 /* Disconnect the socket. */
4989
4990 /* If the disconnect takes more than the timeout option, NetX marks the socket as "closed"
4991 or puts it back to "listen" state. The default value is 1 to emulate an immediate
4992 socket closure without sending a RST packet. */
4993 timeout = NX_BSD_TCP_SOCKET_DISCONNECT_TIMEOUT;
4994
4995 /* Release the mutex while disconnecting. */
4996 tx_mutex_put(nx_bsd_protection_ptr);
4997
4998 nx_tcp_socket_disconnect(tcp_socket_ptr, timeout);
4999
5000 tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
5001
5002 /* Verify that the socket is still valid. */
5003 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
5004 {
5005 /* The socket is no longer in use. */
5006
5007 /* Set the socket error code. */
5008 nx_bsd_set_errno(EBADF);
5009
5010 /* Release the protection mutex. */
5011 tx_mutex_put(nx_bsd_protection_ptr);
5012
5013 /* Return error code. */
5014 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5015 return(NX_SOC_ERROR);
5016 }
5017 }
5018
5019 /* Unaccept on the secondary socket. */
5020 nx_tcp_server_socket_unaccept(tcp_socket_ptr);
5021 nx_tcp_server_socket_unlisten(nx_bsd_default_ip, tcp_socket_ptr -> nx_tcp_socket_port);
5022 nx_tcp_socket_delete(tcp_socket_ptr);
5023
5024 memset((VOID*)tcp_socket_ptr, 0, sizeof(NX_TCP_SOCKET));
5025 tx_block_release((VOID*)tcp_socket_ptr);
5026 memset((VOID*)&(nx_bsd_socket_array[sec_soc_id]), 0, sizeof(NX_BSD_SOCKET));
5027 }
5028 }
5029 }
5030
5031 /* Finally Clear the BSD socket structure. */
5032 memset((VOID *) bsd_socket_ptr, 0, sizeof(NX_BSD_SOCKET));
5033
5034 tx_mutex_put(nx_bsd_protection_ptr);
5035
5036 /* Return */
5037 return(NX_SOC_OK);
5038
5039 }
5040 else if (udp_socket_ptr)
5041 {
5042
5043 /* A UDP socket needs to be closed. */
5044
5045 /* Check whether this is the last BSD socket attached to the NX_UDP_SOCKET */
5046 counter = (UINT)udp_socket_ptr -> nx_udp_socket_reserved_ptr;
5047
5048 delete_socket = NX_TRUE;
5049 /* Decrease the counter value. */
5050 if(counter & 0xFFFF0000)
5051 {
5052
5053 counter = ((counter & 0xFFFF0000) - 0x00010000 + (counter & 0x0000FFFF)) & 0xFFFFFFFF;
5054
5055 udp_socket_ptr -> nx_udp_socket_reserved_ptr = (VOID*)counter;
5056
5057 if(counter & 0xFFFF0000)
5058 {
5059
5060 /* Do not delete this socket. */
5061 delete_socket = NX_FALSE;
5062
5063 /* If the underlying NX_UDP_SOCKET points to this UDP socket, we need to
5064 reassign a BSD socket to the NX UDP socket. */
5065 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
5066 {
5067
5068 if((nx_bsd_socket_array[i].nx_bsd_socket_udp_socket == udp_socket_ptr) &&
5069 (i != sockID))
5070 {
5071
5072 counter = (counter & 0xFFFF0000) + (UINT)i;
5073 udp_socket_ptr -> nx_udp_socket_reserved_ptr = (VOID*)counter;
5074 break;
5075 }
5076 }
5077
5078 if(i == NX_BSD_MAX_SOCKETS)
5079 {
5080 delete_socket = NX_TRUE;
5081 }
5082 }
5083 }
5084
5085 if(delete_socket == NX_TRUE)
5086 {
5087
5088 if(udp_socket_ptr -> nx_udp_socket_bound_next)
5089 {
5090 nx_udp_socket_unbind(udp_socket_ptr);
5091 }
5092
5093 /* Socket successfully unbound. Now delete the UDP socket. */
5094 nx_udp_socket_delete(udp_socket_ptr);
5095
5096 /* Clear the UDP socket block. */
5097 memset((VOID *) udp_socket_ptr, 0, sizeof(NX_UDP_SOCKET));
5098
5099 /* Release the NetX UDP socket memory. */
5100 tx_block_release((VOID *) udp_socket_ptr);
5101 }
5102 else
5103 {
5104 /* Remove this bsd udp socket from the list. */
5105 (bsd_socket_ptr -> nx_bsd_socket_next) -> nx_bsd_socket_previous = bsd_socket_ptr -> nx_bsd_socket_previous;
5106 (bsd_socket_ptr -> nx_bsd_socket_previous) -> nx_bsd_socket_next = bsd_socket_ptr -> nx_bsd_socket_next;
5107 }
5108
5109 /* Clear the BSD socket block. */
5110 memset((VOID *) bsd_socket_ptr, 0, sizeof(NX_BSD_SOCKET));
5111
5112 /* Release the protection mutex. */
5113 tx_mutex_put(nx_bsd_protection_ptr);
5114
5115 return(NX_SOC_OK);
5116 }
5117
5118 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
5119 else if (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET)
5120 {
5121
5122 /* There is no native NetX Duo raw socket to delete or
5123 port to unbind. So just release the BSD socket memory. */
5124
5125 /* Remove this socket from the list. */
5126 protocol = bsd_socket_ptr -> nx_bsd_socket_protocol;
5127
5128 /* Calculate the hash index in the raw socket protocol table. */
5129 index = (UINT) ((protocol + (protocol >> 8)) & NX_BSD_SOCKET_RAW_PROTOCOL_TABLE_MASK);
5130
5131 /* Determine if this is the only socket on this list. */
5132 if(bsd_socket_ptr -> nx_bsd_socket_next == bsd_socket_ptr)
5133 {
5134 /* Yes, this is the only socket on the list. */
5135
5136 /* Clear the list head pointer. */
5137 nx_bsd_socket_raw_protocol_table[index] = NX_NULL;
5138 }
5139 else
5140 {
5141 /* Remove this bsd udp socket from the list. */
5142 (bsd_socket_ptr -> nx_bsd_socket_next) -> nx_bsd_socket_previous = bsd_socket_ptr -> nx_bsd_socket_previous;
5143 (bsd_socket_ptr -> nx_bsd_socket_previous) -> nx_bsd_socket_next = bsd_socket_ptr -> nx_bsd_socket_next;
5144
5145 /* Determine if the head of the list points to the socket being removed.
5146 If so, we need to move the head pointer. */
5147 if(nx_bsd_socket_raw_protocol_table[index] == bsd_socket_ptr)
5148 {
5149 /* Yes, we need to move the list head pointer. */
5150 nx_bsd_socket_raw_protocol_table[index] = bsd_socket_ptr -> nx_bsd_socket_next;
5151 }
5152 }
5153
5154 /* Clear the BSD socket block. */
5155 memset((VOID *) bsd_socket_ptr, 0, sizeof(NX_BSD_SOCKET));
5156
5157 /* Release the protection mutex. */
5158 tx_mutex_put(nx_bsd_protection_ptr);
5159
5160 return(NX_SOC_OK);
5161
5162 }
5163 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
5164 #if defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT)
5165 else if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
5166 {
5167 /* There is no native NetX Duo raw socket to delete or
5168 port to unbind. So just release the BSD socket memory. */
5169
5170 /* Clear the BSD socket block. */
5171 memset((VOID *) bsd_socket_ptr, 0, sizeof(NX_BSD_SOCKET));
5172
5173 /* Release the protection mutex. */
5174 tx_mutex_put(nx_bsd_protection_ptr);
5175
5176 return(NX_SOC_OK);
5177 }
5178
5179 #endif /* defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT) */
5180
5181
5182
5183
5184 /* Unknown socket type or invalid socket. */
5185
5186 /* Release the protection mutex. */
5187 tx_mutex_put(nx_bsd_protection_ptr);
5188
5189 /* Set the socket error if extended socket options enabled. */
5190 nx_bsd_set_errno(EINVAL);
5191
5192 /* Return error. */
5193 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5194 return(NX_SOC_ERROR);
5195
5196
5197
5198 }
5199
5200 /**************************************************************************/
5201 /* */
5202 /* FUNCTION RELEASE */
5203 /* */
5204 /* fcntl PORTABLE C */
5205 /* 6.3.0 */
5206 /* AUTHOR */
5207 /* */
5208 /* Yuxin Zhou, Microsoft Corporation */
5209 /* */
5210 /* DESCRIPTION */
5211 /* */
5212 /* This function performs the requested operation on the file (e.g. */
5213 /* socket) descriptor set. This implementation supports only the set */
5214 /* or get flag, and only sets (or clears) the non blocking option. */
5215 /* */
5216 /* INPUT */
5217 /* */
5218 /* sockID socket descriptor */
5219 /* flag_type File description request */
5220 /* f_options Option(s) to set on the */
5221 /* specified file (socket) */
5222 /* */
5223 /* OUTPUT */
5224 /* */
5225 /* NX_SOC_ERROR Errors with request */
5226 /* (file descriptor flags) File descriptor flags */
5227 /* */
5228 /* CALLS */
5229 /* */
5230 /* tx_mutex_get Get protection */
5231 /* tx_mutex_put Release protection */
5232 /* */
5233 /* CALLED BY */
5234 /* */
5235 /* Application Code */
5236 /* */
5237 /* RELEASE HISTORY */
5238 /* */
5239 /* DATE NAME DESCRIPTION */
5240 /* */
5241 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5242 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5243 /* resulting in version 6.1 */
5244 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
5245 /* used new API/structs naming,*/
5246 /* resulting in version 6.3.0 */
5247 /* */
5248 /**************************************************************************/
nx_bsd_fcntl(INT sockID,UINT flag_type,UINT f_options)5249 INT nx_bsd_fcntl(INT sockID, UINT flag_type, UINT f_options)
5250 {
5251
5252 NX_BSD_SOCKET *bsd_socket_ptr;
5253
5254 /* Check for invalid socket ID. */
5255 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
5256 {
5257
5258 /* Set the socket error if extended options enabled. */
5259 nx_bsd_set_errno(EBADF);
5260
5261 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5262
5263 /* Return error status. */
5264 return NX_SOC_ERROR;
5265 }
5266
5267 /* Normalize the socket ID to our array. */
5268 sockID = sockID - NX_BSD_SOCKFD_START;
5269
5270 /* Build pointer to BSD socket structure. */
5271 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
5272
5273 if(flag_type == F_SETFL)
5274 {
5275 /* Set the FD flag. */
5276 bsd_socket_ptr -> nx_bsd_file_descriptor_flags = (INT)f_options;
5277
5278
5279 /* Are there flags to clear? */
5280 if ((f_options & O_NONBLOCK) == 0)
5281 {
5282 /* Disable the socket for non blocking. */
5283 bsd_socket_ptr -> nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING);
5284 }
5285 else
5286 {
5287 /* Enable the socket for non blocking. */
5288 bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING;
5289 }
5290
5291 /* All done. Return 0 */
5292 return(0);
5293 }
5294 else if(flag_type == F_GETFL)
5295 {
5296 return(bsd_socket_ptr -> nx_bsd_file_descriptor_flags);
5297 }
5298 /* Flag_type is not the one we support */
5299
5300 /* Set the socket error if extended socket options enabled. */
5301 nx_bsd_set_errno(EINVAL);
5302
5303 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5304
5305 /* Return error status. */
5306 return NX_SOC_ERROR;
5307
5308
5309
5310 }
5311
5312
5313 /**************************************************************************/
5314 /* */
5315 /* FUNCTION RELEASE */
5316 /* */
5317 /* ioctl PORTABLE C */
5318 /* 6.3.0 */
5319 /* AUTHOR */
5320 /* */
5321 /* Yuxin Zhou, Microsoft Corporation */
5322 /* */
5323 /* DESCRIPTION */
5324 /* */
5325 /* This function carries out a socket IO service specified by the */
5326 /* command. */
5327 /* */
5328 /* INPUT */
5329 /* */
5330 /* sockID Socket (must be connected). */
5331 /* command IO command for ioctl function */
5332 /* result data returned (value) */
5333 /* */
5334 /* OUTPUT */
5335 /* */
5336 /* Number of bytes received If success */
5337 /* NX_SOC_ERROR (-1) Error during socket opration */
5338 /* NX_SOC_OK (0) Successful completion */
5339 /* */
5340 /* CALLS */
5341 /* */
5342 /* nx_tcp_socket_bytes_available Retreive number of bytes on */
5343 /* the specified TCP socket */
5344 /* nx_udp_socket_bytes_available Retreive number of bytes on */
5345 /* the specified UDP socket */
5346 /* tx_mutex_get Get protection */
5347 /* tx_mutex_put Release protection */
5348 /* */
5349 /* CALLED BY */
5350 /* */
5351 /* Application Code */
5352 /* */
5353 /* RELEASE HISTORY */
5354 /* */
5355 /* DATE NAME DESCRIPTION */
5356 /* */
5357 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5358 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5359 /* resulting in version 6.1 */
5360 /* 03-08-2023 Wenhui Xie Modified comment(s), corrected*/
5361 /* the result of FIONREAD, */
5362 /* resulting in version 6.2.1 */
5363 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
5364 /* used new API/structs naming,*/
5365 /* resulting in version 6.3.0 */
5366 /* */
5367 /**************************************************************************/
nx_bsd_ioctl(INT sockID,INT command,INT * result)5368 INT nx_bsd_ioctl(INT sockID, INT command, INT *result)
5369 {
5370
5371 NX_BSD_SOCKET *bsd_socket_ptr;
5372 NX_TCP_SOCKET *tcp_socket_ptr;
5373 NX_UDP_SOCKET *udp_socket_ptr;
5374 UINT status;
5375
5376
5377 /* Check that the supplied socket ID is valid. */
5378 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
5379 {
5380
5381 /* Error, invalid socket ID. */
5382 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5383 return(NX_SOC_ERROR);
5384 }
5385
5386 /* Normalize the socket ID. */
5387 sockID = sockID - NX_BSD_SOCKFD_START;
5388
5389 /* Get the protection mutex. */
5390 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
5391
5392 /* Check the status. */
5393 if (status)
5394 {
5395
5396 /* Error getting the protection mutex. */
5397 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
5398 return(NX_SOC_ERROR);
5399 }
5400
5401 /* Set a pointer to the BSD socket. */
5402 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
5403
5404 /* Pick up the associated NetX socket pointers. */
5405 tcp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
5406 udp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_udp_socket;
5407
5408 /* Handle the command. */
5409 switch (command)
5410 {
5411
5412 case FIONREAD:
5413 {
5414
5415 /* Check NULL pointer. */
5416 if(result == NX_NULL)
5417 {
5418 tx_mutex_put(nx_bsd_protection_ptr);
5419
5420 nx_bsd_set_errno(EFAULT);
5421
5422 /* Error, invalid address. */
5423 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5424
5425 return(NX_SOC_ERROR);
5426 }
5427
5428 /* Determine which socket pointer to use. */
5429 if (tcp_socket_ptr)
5430 {
5431
5432 /* Extract the number of bytes on the TCP receive queue. */
5433 status = nx_tcp_socket_bytes_available(tcp_socket_ptr, (ULONG *)result);
5434
5435 if (status != NX_SUCCESS)
5436 {
5437
5438 tx_mutex_put(nx_bsd_protection_ptr);
5439
5440 /* Error in the native NetX call. */
5441 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
5442 return(NX_SOC_ERROR);
5443 }
5444 else
5445 {
5446 *result += (INT)(bsd_socket_ptr -> nx_bsd_socket_received_byte_count);
5447 }
5448 }
5449 else if (udp_socket_ptr)
5450 {
5451
5452 /* Extract the number of bytes on the UDP receive queue. */
5453 *result = (INT)(bsd_socket_ptr -> nx_bsd_socket_received_byte_count);
5454 }
5455
5456 break;
5457 }
5458
5459 case FIONBIO:
5460 {
5461
5462 /* Check NULL pointer. */
5463 if(result == NX_NULL)
5464 {
5465 tx_mutex_put(nx_bsd_protection_ptr);
5466
5467 nx_bsd_set_errno(EFAULT);
5468
5469 /* Error, invalid address. */
5470 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5471
5472 return(NX_SOC_ERROR);
5473 }
5474
5475 if(*result == NX_FALSE)
5476 {
5477
5478 /* Disable the socket for non blocking. */
5479 bsd_socket_ptr -> nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING);
5480
5481 /* Update the file descriptor with the non blocking bit. */
5482 bsd_socket_ptr -> nx_bsd_file_descriptor_flags &= ~O_NONBLOCK;
5483 }
5484 else
5485 {
5486
5487 /* Enable the socket for non blocking. */
5488 bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING;
5489
5490 /* Update the file descriptor with the non blocking bit. */
5491 bsd_socket_ptr -> nx_bsd_file_descriptor_flags |= O_NONBLOCK;
5492 }
5493
5494 break;
5495 }
5496
5497 default:
5498
5499 /* Unhandled command; ignore */
5500 break;
5501 }
5502
5503 tx_mutex_put(nx_bsd_protection_ptr);
5504
5505 return NX_SOC_OK;
5506 }
5507
5508 /**************************************************************************/
5509 /* */
5510 /* FUNCTION RELEASE */
5511 /* */
5512 /* inet_ntoa PORTABLE C */
5513 /* 6.3.0 */
5514 /* AUTHOR */
5515 /* */
5516 /* Yuxin Zhou, Microsoft Corporation */
5517 /* */
5518 /* DESCRIPTION */
5519 /* */
5520 /* This function converts an IP address to a string and returns a */
5521 /* pointer to the string. The caller is recommended to copy the */
5522 /* contents of the buffer to local memory since this function and */
5523 /* internal buffer can be reused. */
5524 /* */
5525 /* INPUT */
5526 /* */
5527 /* address_to_convert Struct holding IP address. */
5528 /* */
5529 /* OUTPUT */
5530 /* */
5531 /* char * Pointer to converted string */
5532 /* 0x0 Error during conversion */
5533 /* */
5534 /* CALLS */
5535 /* */
5536 /* tx_mutex_get Get mutex protection */
5537 /* bsd_number_convert Convert integer to ascii */
5538 /* */
5539 /* CALLED BY */
5540 /* */
5541 /* Application Code */
5542 /* */
5543 /* RELEASE HISTORY */
5544 /* */
5545 /* DATE NAME DESCRIPTION */
5546 /* */
5547 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5548 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5549 /* resulting in version 6.1 */
5550 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
5551 /* used new API/structs naming,*/
5552 /* resulting in version 6.3.0 */
5553 /* */
5554 /**************************************************************************/
nx_bsd_inet_ntoa(struct nx_bsd_in_addr address_to_convert)5555 CHAR *nx_bsd_inet_ntoa(struct nx_bsd_in_addr address_to_convert)
5556 {
5557 UINT status;
5558
5559 /* Because we are using global buffer space to write out the string, get the protection mutex. */
5560 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
5561
5562 if (status != NX_SUCCESS)
5563 {
5564 return NX_NULL;
5565 }
5566
5567 inet_ntoa_internal(&address_to_convert, nx_bsd_url_buffer, NX_BSD_URL_BUFSIZE);
5568
5569 tx_mutex_put(nx_bsd_protection_ptr);
5570
5571 /* Return the start of the string buffer. */
5572 return nx_bsd_url_buffer;
5573
5574 }
5575
5576 /**************************************************************************/
5577 /* */
5578 /* FUNCTION RELEASE */
5579 /* */
5580 /* bsd_number_convert PORTABLE C */
5581 /* 6.1 */
5582 /* AUTHOR */
5583 /* */
5584 /* Yuxin Zhou, Microsoft Corporation */
5585 /* */
5586 /* DESCRIPTION */
5587 /* */
5588 /* This function converts an integer to a string. */
5589 /* */
5590 /* INPUT */
5591 /* */
5592 /* number Number to convert */
5593 /* string Pointer to string buffer */
5594 /* buffer_len Size of the string buffer */
5595 /* base the base of the number, */
5596 /* 2,8,10,16 */
5597 /* */
5598 /* OUTPUT */
5599 /* */
5600 /* size Size of string buffer */
5601 /* */
5602 /* CALLS */
5603 /* */
5604 /* None */
5605 /* */
5606 /* CALLED BY */
5607 /* */
5608 /* Application Code */
5609 /* */
5610 /* RELEASE HISTORY */
5611 /* */
5612 /* DATE NAME DESCRIPTION */
5613 /* */
5614 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5615 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5616 /* resulting in version 6.1 */
5617 /* */
5618 /**************************************************************************/
bsd_number_convert(UINT number,CHAR * string,ULONG buffer_len,UINT base)5619 UINT bsd_number_convert(UINT number, CHAR *string, ULONG buffer_len, UINT base)
5620 {
5621
5622 UINT j;
5623 UINT digit;
5624 UINT size;
5625
5626
5627 /* Initialize counters. */
5628 size = 0;
5629
5630 /* Loop to convert the number to ASCII. */
5631 while (size < buffer_len)
5632 {
5633
5634 /* Shift the current digits over one. */
5635 for (j = size; j != 0; j--)
5636 {
5637
5638 /* Move each digit over one place. */
5639 string[j] = string[j-1];
5640 }
5641
5642 /* Compute the next decimal digit. */
5643 digit = number % base;
5644
5645 /* Update the input number. */
5646 number = number / base;
5647
5648 /* Store the new digit in ASCII form. */
5649 if(digit < 10)
5650 string[0] = (CHAR) (digit + 0x30);
5651 else
5652 string[0] = (CHAR) (digit + 0x57);
5653
5654 /* Increment the size. */
5655 size++;
5656
5657 /* Determine if the number is now zero. */
5658 if (number == 0)
5659 break;
5660 }
5661
5662 /* Make the string NULL terminated. */
5663 string[size] = (CHAR) NX_NULL;
5664
5665 /* Determine if there is an overflow error. */
5666 if (number)
5667 {
5668
5669 /* Error, return bad values to user. */
5670 size = 0;
5671 string[0] = '0';
5672 }
5673
5674 /* Return size to caller. */
5675 return(size);
5676 }
5677
5678 /**************************************************************************/
5679 /* */
5680 /* FUNCTION RELEASE */
5681 /* */
5682 /* inet_aton PORTABLE C */
5683 /* 6.3.0 */
5684 /* AUTHOR */
5685 /* */
5686 /* Yuxin Zhou, Microsoft Corporation */
5687 /* */
5688 /* DESCRIPTION */
5689 /* */
5690 /* This function converts hexadecimal characters into an ASCII IP */
5691 /* address representation. */
5692 /* */
5693 /* INPUT */
5694 /* */
5695 /* address_buffer_ptr String holding the IP address */
5696 /* addr Struct to store the IP address*/
5697 /* */
5698 /* OUTPUT */
5699 /* */
5700 /* NX_SUCCESS Successful conversion */
5701 /* NX_SOC_ERROR Error during conversion */
5702 /* */
5703 /* CALLS */
5704 /* */
5705 /* nx_bsd_isdigit Indicate char is a number */
5706 /* isspace Indicate char is a space */
5707 /* islower Indicate char is lowercase */
5708 /* htonl Convert to network byte order */
5709 /* */
5710 /* CALLED BY */
5711 /* */
5712 /* Application Code */
5713 /* */
5714 /* RELEASE HISTORY */
5715 /* */
5716 /* DATE NAME DESCRIPTION */
5717 /* */
5718 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5719 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5720 /* resulting in version 6.1 */
5721 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
5722 /* used new API/structs naming,*/
5723 /* resulting in version 6.3.0 */
5724 /* */
5725 /**************************************************************************/
nx_bsd_inet_aton(const CHAR * address_buffer_ptr,struct nx_bsd_in_addr * addr)5726 INT nx_bsd_inet_aton(const CHAR *address_buffer_ptr, struct nx_bsd_in_addr *addr)
5727 {
5728 ULONG value;
5729 INT base = 10, ip_address_index;
5730 UCHAR tempchar;
5731 const UCHAR *buffer_ptr;
5732 UINT ip_address_number[4]; /* Four discreet numbers in IP address representation. */
5733 UINT *ip_number_ptr; /* IP address as equivalent ULONG value. */
5734 UINT dot_flag;
5735
5736 /* Set local variables. */
5737 buffer_ptr = (const UCHAR *) address_buffer_ptr;
5738 ip_number_ptr = ip_address_number;
5739
5740 tempchar = *buffer_ptr;
5741
5742 /* Check for an invalid first character. */
5743 if (nx_bsd_isdigit(tempchar)== NX_FALSE)
5744 {
5745 return (0);
5746 }
5747
5748 dot_flag = 1;
5749
5750 /* Parse the rest of the characters from the input number. */
5751 do
5752 {
5753
5754 /* Initialize the (next) extracted IP address number to zero. */
5755 value = 0;
5756
5757 if(dot_flag== 1)
5758 {
5759 /* Initialize the numeric base to decimal unless we determine hex or octal. */
5760 base = 10;
5761
5762 /* Determine which number base the input number buffer is. */
5763 if (*buffer_ptr == '0')
5764 {
5765 /* Get the next character. */
5766 buffer_ptr++;
5767
5768 /* A leading 0 followed by an 'x' indicates this is hexidecimal. */
5769 if ((*buffer_ptr== 'x') || (*buffer_ptr == 'X'))
5770 {
5771 base = 16;
5772
5773 /* Move ahead one character past the leading '0x' */
5774 buffer_ptr++;
5775 }
5776 else
5777 {
5778 /* This is octal. */
5779 base = 8;
5780 buffer_ptr--;
5781 }
5782 }
5783 }
5784
5785 tempchar = *buffer_ptr;
5786
5787 /* Parse characters making up the next word. */
5788 while (*buffer_ptr != '\0')
5789 {
5790 /* Check if the next character is a decimal or octal digit. */
5791 if (nx_bsd_isdigit(tempchar))
5792 {
5793
5794 dot_flag = 0;
5795
5796 /* Convert the tempchar character to a number. Multiply the existing
5797 number by the base (8 or 10) and this digit to the sum. */
5798 value = (value * (ULONG)base) + (ULONG)(tempchar - '0');
5799
5800 /* Advance the IP address pointer to the next character. */
5801 buffer_ptr++;
5802
5803 /* Get the next character. */
5804 tempchar = *buffer_ptr;
5805 }
5806 /* Else check if we are expecting a hexidecimal number. */
5807 else if (nx_bsd_isxdigit(tempchar))
5808 {
5809 /* We are; Verify the base is 16. */
5810 if(base == 16)
5811 {
5812
5813 /* It is. handle upper or lower case hex digit. */
5814 CHAR c = (CHAR)(nx_bsd_islower(tempchar) ? 'a' : 'A');
5815
5816 dot_flag = 0;
5817
5818 /* Convert the hex character to a hex digit, multiply the existing word by shifting the bits,
5819 and add this hex digit to the sum. */
5820 value = (value << 4) + (ULONG)(tempchar + 10 - c);
5821
5822 buffer_ptr++;
5823
5824 /* Get the next character. */
5825 tempchar = *buffer_ptr;
5826 }
5827 else
5828 {
5829 /* Not a valid hex character. */
5830 return (0);
5831 }
5832 }
5833 else
5834 {
5835 /* We have reached a number separator or possibly end of the string. */
5836 break;
5837 }
5838 }
5839
5840 /* At the end of the current word. Is this a separator character? */
5841 if (*buffer_ptr == '.')
5842 {
5843
5844 dot_flag = 1;
5845
5846 /* Yes, check for an invalid number (cannot exceed 255 or 0xFF. */
5847 if (value > 0xff)
5848 {
5849 return (0);
5850 }
5851
5852 /* Check that the pointer to the last extracted number does not exceed the array holding the IP address numbers. */
5853 if (ip_number_ptr >= (ip_address_number + 3))
5854 {
5855 return (0);
5856 }
5857
5858 /* Copy the computed value into the IP address number buffer. */
5859 *ip_number_ptr = value;
5860
5861 /* Move the pointer to where we will store the next number extracted. */
5862 ip_number_ptr++;
5863
5864 /* Move to the next character in the IP address string. */
5865 buffer_ptr++;
5866 }
5867 /* Check for non digit or seperator character indicating (maybe) end of the buffer. */
5868 else
5869 break;
5870
5871 } while (1);
5872
5873 /* If this is not a null terminating character, check for invalid trailing characters. */
5874 if (*buffer_ptr)
5875 {
5876
5877 if((*buffer_ptr != '\0') && (!nx_bsd_isspace(*buffer_ptr)))
5878 {
5879
5880 return (0);
5881 }
5882 }
5883
5884 /* IP addresses are grouped as A, B, C, or D types. Determine which
5885 type address we have by comparing the IP address value against...*/
5886
5887 /* Determine this by substracting the pointer to beginning of the whole
5888 IP address number ip_number_ptr[4] against the pointer to the last extracted word, ip_address_number. */
5889 ip_address_index = ip_number_ptr - ip_address_number + 1;
5890
5891 /* Check for an invalid array index (assume 'the array' is indexed 1-4). */
5892 if ((ip_address_index == 0) || (ip_address_index > 4))
5893 {
5894 return (0);
5895 }
5896
5897 /* Sum each of the individual IP address numbers depending how many there were extracted. */
5898
5899 /* Most common input... */
5900 if (ip_address_index == 4)
5901 {
5902 INT i;
5903
5904 /* Three separators parsed, so the format is a.b.c.d where c is 8 bits */
5905
5906 /* Check for a computed sum greater than can be contained in 8 bits. */
5907 if (value > 0xff)
5908 return (0);
5909
5910 /* 'Add' the last extracted number by prepending the three other bytes onto the total value. */
5911 for (i = 0; i<=2; i++)
5912 {
5913 value |= ip_address_number[i] << (24 - (i*8));
5914 }
5915 }
5916 /* Most common input... */
5917 else if (ip_address_index == 1)
5918 {
5919
5920 /* We are done, this address contained one 32 bit word (no separators). */
5921 }
5922 /* Less common input... */
5923 else if (ip_address_index == 2)
5924 {
5925 /* One separator, so the format is a.b where b is 24 bits */
5926
5927 /* Check for a computed sum greater than can be contained in 24 bits. */
5928 if (value > 0xffffff)
5929 return (0);
5930
5931 /* 'Add' the last extracted number by prepending the most significant byte onto the total value. */
5932 value |= (ip_address_number[0] << 24);
5933 }
5934 else if (ip_address_index == 3)
5935 {
5936 /* Two separators parsed, so the format is a.b.c where c is 16 bits */
5937 INT i;
5938
5939 /* Check for a computed sum greater than can be contained in 16 bits. */
5940 if (value > 0xffff)
5941 return (0);
5942
5943 /* 'Add' the last extracted number by prepending the two most significant bytes onto the total value. */
5944 for (i = 0; i<=1; i++)
5945 {
5946 value |= ip_address_number[i] << (24 - (i*8));
5947 }
5948 }
5949
5950 /* Check if a return pointer for the address data is supplied. */
5951 if (addr)
5952 {
5953
5954 /* Convert the IP address data to network byte order and return the data. */
5955 addr->s_addr = htonl(value);
5956 }
5957
5958 return (1);
5959 }
5960
5961
5962 /**************************************************************************/
5963 /* */
5964 /* FUNCTION RELEASE */
5965 /* */
5966 /* inet_addr PORTABLE C */
5967 /* 6.3.0 */
5968 /* AUTHOR */
5969 /* */
5970 /* Yuxin Zhou, Microsoft Corporation */
5971 /* */
5972 /* DESCRIPTION */
5973 /* */
5974 /* This function converts an IP address string to a number. If it */
5975 /* detects an error in the conversion it returns a zero address. */
5976 /* */
5977 /* INPUT */
5978 /* */
5979 /* buffer IP address text buffer */
5980 /* address Converted address number */
5981 /* */
5982 /* OUTPUT */
5983 /* */
5984 /* NX_SUCCESS Successful conversion */
5985 /* NX_SOC_ERROR Error during conversion */
5986 /* */
5987 /* CALLS */
5988 /* */
5989 /* inet_aton Indicate char is a space */
5990 /* */
5991 /* CALLED BY */
5992 /* */
5993 /* Application Code */
5994 /* */
5995 /* RELEASE HISTORY */
5996 /* */
5997 /* DATE NAME DESCRIPTION */
5998 /* */
5999 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6000 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6001 /* resulting in version 6.1 */
6002 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
6003 /* used new API/structs naming,*/
6004 /* resulting in version 6.3.0 */
6005 /* */
6006 /**************************************************************************/
nx_bsd_inet_addr(const CHAR * buffer)6007 nx_bsd_in_addr_t nx_bsd_inet_addr(const CHAR *buffer)
6008 {
6009
6010 struct nx_bsd_in_addr ip_address;
6011 UINT status;
6012
6013 status = (UINT)nx_bsd_inet_aton(buffer, &ip_address);
6014
6015 if (status == 0)
6016 {
6017 return (0xFFFFFFFF);
6018 }
6019
6020 return(ip_address.s_addr);
6021 }
6022
6023
6024 /**************************************************************************/
6025 /* */
6026 /* FUNCTION RELEASE */
6027 /* */
6028 /* getsockopt PORTABLE C */
6029 /* 6.3.0 */
6030 /* AUTHOR */
6031 /* */
6032 /* Yuxin Zhou, Microsoft Corporation */
6033 /* */
6034 /* DESCRIPTION */
6035 /* */
6036 /* This function returns the status of the specified socket option in */
6037 /* the current BSD socket session. */
6038 /* */
6039 /* INPUT */
6040 /* */
6041 /* sockID socket descriptor */
6042 /* option_level Category of option (SOCKET) */
6043 /* option_name Socket option ID */
6044 /* option_value Pointer to option value */
6045 /* option_value Pointer to size of value */
6046 /* */
6047 /* OUTPUT */
6048 /* */
6049 /* tx_mutex_get Get protection */
6050 /* tx_mutex_put Release protection */
6051 /* */
6052 /* CALLS */
6053 /* */
6054 /* NX_SOC_OK Request processed successfully*/
6055 /* NX_SOC_ERROR Errors with request */
6056 /* (option data) Pointer to requested data */
6057 /* */
6058 /* CALLED BY */
6059 /* */
6060 /* Application Code */
6061 /* */
6062 /* RELEASE HISTORY */
6063 /* */
6064 /* DATE NAME DESCRIPTION */
6065 /* */
6066 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6067 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6068 /* resulting in version 6.1 */
6069 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
6070 /* used new API/structs naming,*/
6071 /* resulting in version 6.3.0 */
6072 /* */
6073 /**************************************************************************/
nx_bsd_getsockopt(INT sockID,INT option_level,INT option_name,VOID * option_value,INT * option_length)6074 INT nx_bsd_getsockopt(INT sockID, INT option_level, INT option_name, VOID *option_value, INT *option_length)
6075 {
6076
6077 TX_INTERRUPT_SAVE_AREA
6078
6079 INT status;
6080 NX_BSD_SOCKET *bsd_socket_ptr;
6081 struct nx_bsd_sock_errno *so_errno;
6082 struct nx_bsd_sock_keepalive *so_keepalive;
6083 struct nx_bsd_sock_reuseaddr *so_reuseaddr;
6084 struct nx_bsd_timeval *so_rcvtimeval;
6085 struct nx_bsd_sock_winsize *soc_window_size;
6086 ULONG ticks;
6087
6088
6089 /* Check for valid socket ID/descriptor. */
6090 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
6091 {
6092
6093 /* Set the socket error if extended options enabled. */
6094 nx_bsd_set_errno(EBADF);
6095
6096 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6097 return(NX_SOC_ERROR);
6098 }
6099
6100 /* Check for invalid input. */
6101 if((option_value == NX_NULL) || (option_length == NX_NULL))
6102 {
6103
6104 /* Set the socket error if extended socket options enabled. */
6105 nx_bsd_set_errno(EINVAL);
6106
6107 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6108 return NX_SOC_ERROR;
6109 }
6110
6111 if (option_level == IPPROTO_IP)
6112 {
6113
6114 if((option_name <= SO_MAX) || (option_name > IP_OPTION_MAX))
6115 {
6116
6117 /* Error, one or more invalid arguments. */
6118
6119 /* Set the socket error if extended socket options enabled. */
6120 nx_bsd_set_errno(ENOPROTOOPT);
6121
6122 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6123 return NX_SOC_ERROR;
6124 }
6125 }
6126 else if(option_level == SOL_SOCKET)
6127 {
6128
6129 if((option_name > SO_MAX) || (option_name < SO_MIN))
6130 {
6131
6132 /* Error, one or more invalid arguments. */
6133
6134 /* Set the socket error if extended socket options enabled. */
6135 nx_bsd_set_errno(ENOPROTOOPT);
6136
6137 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6138 return NX_SOC_ERROR;
6139 }
6140 }
6141 else
6142 {
6143
6144 /* Error, one or more invalid arguments. */
6145
6146 /* Set the socket error if extended socket options enabled. */
6147 nx_bsd_set_errno(EINVAL);
6148
6149 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6150 return NX_SOC_ERROR;
6151 }
6152
6153 /* Normalize the socket ID. */
6154 sockID = sockID - NX_BSD_SOCKFD_START;
6155
6156 /* Get the protection mutex. */
6157 status = (INT)tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
6158
6159 /* Check the status. */
6160 if (status)
6161 {
6162
6163 /* Set the socket error if extended socket options enabled. */
6164 nx_bsd_set_errno(EACCES);
6165
6166 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
6167 return(NX_SOC_ERROR);
6168 }
6169
6170 /* Setup pointer to socket. */
6171 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
6172
6173 status = NX_SOC_OK;
6174 switch (option_name)
6175 {
6176
6177 case SO_ERROR:
6178 {
6179
6180 /* If a valid option pointer was supplied, verify it points to a valid data size. */
6181 if (*option_length < (INT)sizeof(so_errno -> error))
6182 {
6183
6184 tx_mutex_put(nx_bsd_protection_ptr);
6185
6186 /* Set the socket error if extended socket options enabled. */
6187 nx_bsd_set_errno(EINVAL);
6188
6189 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6190 return(NX_SOC_ERROR);
6191 }
6192
6193 so_errno = (struct nx_bsd_sock_errno *)option_value;
6194
6195 TX_DISABLE
6196 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
6197 {
6198 so_errno -> error = bsd_socket_ptr -> nx_bsd_socket_error_code;
6199
6200 /* Now clear the error code. */
6201 bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
6202
6203 /* Clear the error flag. The application is expected to close the socket at this point.*/
6204 bsd_socket_ptr -> nx_bsd_socket_status_flags = bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
6205 }
6206 else
6207 so_errno -> error = 0;
6208 TX_RESTORE
6209
6210 /* Set the actual size of the data returned. */
6211 *option_length = sizeof(struct nx_bsd_sock_errno);
6212
6213 }
6214
6215 break;
6216
6217 case SO_KEEPALIVE:
6218
6219 /* Determine if NetX Duo supports keepalive. */
6220
6221 /* Check to make sure the size arguement is sufficient if supplied. */
6222 if (*option_length < (INT)sizeof(so_keepalive -> keepalive_enabled))
6223 {
6224
6225 tx_mutex_put(nx_bsd_protection_ptr);
6226
6227 /* Set the socket error if extended socket options enabled. */
6228 nx_bsd_set_errno(EINVAL);
6229
6230 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6231 return(NX_SOC_ERROR);
6232 }
6233
6234 so_keepalive = (struct nx_bsd_sock_keepalive *)option_value;
6235 #ifndef NX_ENABLE_TCP_KEEPALIVE
6236 so_keepalive -> keepalive_enabled = NX_FALSE;
6237 #else
6238 so_keepalive -> keepalive_enabled = (INT)(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled);
6239 #endif /* NX_ENABLE_TCP_KEEPALIVE */
6240 *option_length = sizeof(struct nx_bsd_sock_keepalive);
6241
6242 break;
6243
6244 case SO_RCVTIMEO:
6245
6246 /* Check if the receive time out is set. */
6247 if (bsd_socket_ptr -> nx_bsd_option_receive_timeout == 0)
6248 {
6249 tx_mutex_put(nx_bsd_protection_ptr);
6250
6251 /* Set the socket error if extended socket options enabled. */
6252 nx_bsd_set_errno(EINVAL);
6253
6254 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6255 return(NX_SOC_ERROR);
6256
6257 }
6258
6259 so_rcvtimeval = (struct nx_bsd_timeval *)option_value;
6260
6261 ticks = bsd_socket_ptr -> nx_bsd_option_receive_timeout;
6262
6263
6264 so_rcvtimeval -> tv_usec = (nx_bsd_suseconds_t)(ticks * NX_MICROSECOND_PER_CPU_TICK) % 1000000;
6265 so_rcvtimeval -> tv_sec = (nx_bsd_time_t)((ticks * NX_MICROSECOND_PER_CPU_TICK) / 1000000);
6266 *option_length = sizeof(so_rcvtimeval);
6267
6268 break;
6269
6270 case SO_RCVBUF:
6271
6272 soc_window_size = (struct nx_bsd_sock_winsize *)option_value;
6273 soc_window_size -> winsize = (INT)(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_default);
6274 *option_length = sizeof(soc_window_size);
6275
6276 break;
6277
6278 case SO_REUSEADDR:
6279
6280 /* Check to make sure the size arguement is sufficient if supplied. */
6281 if (*option_length < (INT)sizeof(so_reuseaddr -> reuseaddr_enabled))
6282 {
6283
6284 tx_mutex_put(nx_bsd_protection_ptr);
6285
6286 /* Set the socket error if extended socket options enabled. */
6287 nx_bsd_set_errno(EINVAL);
6288
6289 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6290 return(NX_SOC_ERROR);
6291 }
6292
6293 so_reuseaddr= (struct nx_bsd_sock_reuseaddr *)option_value;
6294 so_reuseaddr -> reuseaddr_enabled = bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR;
6295 *option_length = sizeof(struct nx_bsd_sock_reuseaddr);
6296
6297 break;
6298
6299 case IP_MULTICAST_TTL:
6300
6301 /* Validate the option length. */
6302 if(*option_length != sizeof(UCHAR))
6303 {
6304
6305 tx_mutex_put(nx_bsd_protection_ptr);
6306
6307 /* Set the socket error if extended socket options enabled. */
6308 nx_bsd_set_errno(EINVAL);
6309
6310 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6311 return NX_SOC_ERROR;
6312 }
6313
6314 /* Verify that the socket is still valid. */
6315 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
6316 {
6317
6318 tx_mutex_put(nx_bsd_protection_ptr);
6319
6320 /* Set the socket error if extended socket options enabled. */
6321 nx_bsd_set_errno(EBADF);
6322
6323 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6324 return NX_SOC_ERROR;
6325 }
6326
6327 /* Make sure socket is UDP type. */
6328 if(bsd_socket_ptr -> nx_bsd_socket_udp_socket == NX_NULL)
6329 {
6330
6331 tx_mutex_put(nx_bsd_protection_ptr);
6332
6333 /* Set the socket error if extended socket options enabled. */
6334 nx_bsd_set_errno(ENOPROTOOPT);
6335
6336 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6337 return NX_SOC_ERROR;
6338 }
6339
6340 /* Set the TTL value. */
6341 *(UCHAR*)option_value = (UCHAR)(bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_time_to_live);
6342 break;
6343
6344 default:
6345
6346 tx_mutex_put(nx_bsd_protection_ptr);
6347
6348 /* Set the socket error if extended socket options enabled. */
6349 nx_bsd_set_errno(ENOPROTOOPT);
6350
6351 /* Unsupported or unknown option. */
6352 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6353 return(NX_SOC_ERROR);
6354 }
6355
6356 /* Release the protection mutex. */
6357 tx_mutex_put(nx_bsd_protection_ptr);
6358
6359 return status;
6360 }
6361
6362 /**************************************************************************/
6363 /* */
6364 /* FUNCTION RELEASE */
6365 /* */
6366 /* setsockopt PORTABLE C */
6367 /* 6.3.0 */
6368 /* AUTHOR */
6369 /* */
6370 /* Yuxin Zhou, Microsoft Corporation */
6371 /* */
6372 /* DESCRIPTION */
6373 /* */
6374 /* This function enables the specified socket option in the current BSD*/
6375 /* socket session to the specified setting. */
6376 /* */
6377 /* INPUT */
6378 /* */
6379 /* sockID socket descriptor */
6380 /* option_level Category of option (SOCKET) */
6381 /* option_name Socket option ID */
6382 /* option_value Pointer to option value */
6383 /* option_length Size of option value data */
6384 /* */
6385 /* OUTPUT */
6386 /* */
6387 /* NX_SOC_OK Request processed successfully*/
6388 /* NX_SOC_ERROR Errors with request */
6389 /* */
6390 /* CALLS */
6391 /* */
6392 /* tx_mutex_get Get protection */
6393 /* tx_mutex_put Release protection */
6394 /* */
6395 /* CALLED BY */
6396 /* */
6397 /* Application Code */
6398 /* */
6399 /* RELEASE HISTORY */
6400 /* */
6401 /* DATE NAME DESCRIPTION */
6402 /* */
6403 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6404 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6405 /* resulting in version 6.1 */
6406 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
6407 /* used new API/structs naming,*/
6408 /* resulting in version 6.3.0 */
6409 /* */
6410 /**************************************************************************/
nx_bsd_setsockopt(INT sockID,INT option_level,INT option_name,const VOID * option_value,INT option_length)6411 INT nx_bsd_setsockopt(INT sockID, INT option_level, INT option_name, const VOID *option_value, INT option_length)
6412 {
6413 UINT reuse_enabled;
6414 NX_BSD_SOCKET *bsd_socket_ptr;
6415 ULONG window_size;
6416 ULONG timer_ticks;
6417 struct nx_bsd_timeval *time_val;
6418 #if defined(NX_ENABLE_IP_RAW_PACKET_FILTER) || !defined(NX_DISABLE_IPV4)
6419 INT i;
6420 #endif /* defined(NX_ENABLE_IP_RAW_PACKET_FILTER) || !defined(NX_DISABLE_IPV4) */
6421 #ifndef NX_DISABLE_IPV4
6422 struct nx_bsd_ip_mreq
6423 *mreq;
6424 UINT mcast_interface;
6425 UINT status;
6426 #endif /* NX_DISABLE_IPV4 */
6427
6428
6429 /* Check for valid socket ID. */
6430 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
6431 {
6432
6433 /* Error, invalid socket ID. */
6434
6435 /* Set the socket error if extended options enabled. */
6436 nx_bsd_set_errno(EBADF);
6437
6438 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6439 return(NX_SOC_ERROR);
6440 }
6441
6442 /* Check for invalid paremters. */
6443 if((option_value == NX_NULL) || (option_length == 0))
6444 {
6445
6446 /* Error, one or more invalid arguments. */
6447
6448 /* Set the socket error if extended socket options enabled. */
6449 nx_bsd_set_errno(EINVAL);
6450
6451 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6452 return NX_SOC_ERROR;
6453 }
6454
6455 if (option_level == IPPROTO_IP)
6456 {
6457
6458 if((option_name <= SO_MAX) || (option_name > IP_OPTION_MAX))
6459 {
6460
6461 /* Error, one or more invalid arguments. */
6462
6463 /* Set the socket error if extended socket options enabled. */
6464 nx_bsd_set_errno(ENOPROTOOPT);
6465
6466 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6467 return NX_SOC_ERROR;
6468 }
6469 }
6470 else if(option_level == SOL_SOCKET)
6471 {
6472
6473 if((option_name > SO_MAX) ||
6474 (option_name < SO_MIN))
6475 {
6476 /* Error, one or more invalid arguments. */
6477
6478 /* Set the socket error if extended socket options enabled. */
6479 nx_bsd_set_errno(ENOPROTOOPT);
6480
6481 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6482 return NX_SOC_ERROR;
6483 }
6484 }
6485 else if (option_level == IPPROTO_TCP)
6486 {
6487
6488 if ((option_name > TCP_NOOPT) ||
6489 (option_name < TCP_NODELAY))
6490 {
6491 /* Error, one or more invalid arguments. */
6492
6493 /* Set the socket error if extended socket options enabled. */
6494 nx_bsd_set_errno(ENOPROTOOPT);
6495
6496 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6497 return NX_SOC_ERROR;
6498 }
6499 }
6500 else
6501 {
6502 /* Error, one or more invalid arguments. */
6503
6504 /* Set the socket error if extended socket options enabled. */
6505 nx_bsd_set_errno(EINVAL);
6506
6507 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6508 return NX_SOC_ERROR;
6509 }
6510 /* Normalize the socket ID. */
6511 sockID = sockID - NX_BSD_SOCKFD_START;
6512
6513 /* Set up pointer to the BSD socket. */
6514 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
6515
6516 /* Set the socket option status. */
6517 switch (option_name)
6518 {
6519
6520 case SO_BROADCAST:
6521
6522 /* This is the default behavior of NetX. All sockets have this capability. */
6523 break;
6524
6525 case SO_KEEPALIVE:
6526
6527 /* Only available to TCP BSD sockets. */
6528 if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
6529 {
6530
6531 /* Verify TCP keep alive is built into the NetX library or return an error. */
6532 #ifndef NX_ENABLE_TCP_KEEPALIVE
6533
6534 /* Set the socket error if extended socket options enabled. */
6535 nx_bsd_set_errno(ENOPROTOOPT);
6536
6537 /* Return an error status. */
6538 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6539 return NX_SOC_ERROR;
6540 #else
6541 /* Determine if NetX Duo supports keepalive. */
6542
6543 /* Update the BSD socket with this attribute. */
6544 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled =
6545 (UINT)(((struct nx_bsd_sock_keepalive *)option_value) -> keepalive_enabled);
6546
6547 if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled == NX_TRUE)
6548 {
6549
6550 /* Set the keep alive timeout for this socket with the NetX configurable keep alive timeout. */
6551 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_timeout = NX_TCP_KEEPALIVE_INITIAL;
6552 }
6553 else
6554 {
6555
6556 /* Clear the socket keep alive timeout. */
6557 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_timeout = 0;
6558 }
6559 #endif /* NX_ENABLE_TCP_KEEPALIVE */
6560 }
6561 else
6562 {
6563 /* Not a TCP socket. */
6564
6565 /* Set the socket error if extended socket options enabled. */
6566 nx_bsd_set_errno(ENOPROTOOPT);
6567
6568 /* Return an error status. */
6569 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6570 return NX_SOC_ERROR;
6571 }
6572
6573 break;
6574
6575 case SO_LINGER:
6576
6577 /* The Linger socket option is not supported in NetX Duo BSD. */
6578
6579 return NX_NOT_ENABLED;
6580
6581 case SO_SNDTIMEO:
6582
6583 time_val = (struct nx_bsd_timeval *)option_value;
6584
6585 /* Calculate ticks for the ThreadX Timer. */
6586 timer_ticks = (ULONG)(time_val -> tv_usec)/NX_MICROSECOND_PER_CPU_TICK + (ULONG)(time_val -> tv_sec) * NX_IP_PERIODIC_RATE;
6587
6588 bsd_socket_ptr -> nx_bsd_option_send_timeout = timer_ticks;
6589
6590 break;
6591
6592 case SO_RCVTIMEO:
6593
6594 time_val = (struct nx_bsd_timeval *)option_value;
6595
6596 /* Calculate ticks for the ThreadX Timer. */
6597 timer_ticks = (ULONG)(time_val -> tv_usec)/NX_MICROSECOND_PER_CPU_TICK + (ULONG)(time_val -> tv_sec) * NX_IP_PERIODIC_RATE;
6598
6599 bsd_socket_ptr -> nx_bsd_option_receive_timeout = timer_ticks;
6600
6601 break;
6602
6603 case SO_RCVBUF:
6604
6605 /* Only available to TCP sockets. */
6606 if (!bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
6607 {
6608
6609 /* Set the socket error if extended socket options enabled. */
6610 nx_bsd_set_errno(ENOPROTOOPT);
6611
6612 /* Return an error status. */
6613 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6614 return NX_SOC_ERROR;
6615 }
6616
6617
6618 window_size = (ULONG)(((struct nx_bsd_sock_winsize *)option_value) -> winsize);
6619
6620 #ifdef NX_ENABLE_TCP_WINDOW_SCALING
6621
6622
6623 /* If Window scaling feature is enabled, record this user-specified window size. */
6624 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_maximum = window_size;
6625 #else
6626 /* Otherwise the windows size limit is applied. */
6627 if(window_size > 65535)
6628 window_size = 65535;
6629
6630 #endif /* NX_ENABLE_TCP_WINDOW_SCALING */
6631
6632 /* Setup the sliding window information. */
6633 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_default = window_size;
6634 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_current = window_size;
6635
6636 break;
6637
6638 case SO_REUSEADDR:
6639
6640 reuse_enabled = (UINT)(((struct nx_bsd_sock_reuseaddr *)option_value) -> reuseaddr_enabled);
6641
6642 if(reuse_enabled)
6643 bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR;
6644 else
6645 bsd_socket_ptr -> nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR);
6646
6647 break;
6648
6649
6650 case TCP_NODELAY:
6651
6652 /* This is the default behavior of NetX. All sockets have this attribute. */
6653
6654 break;
6655
6656 case IP_MULTICAST_TTL:
6657
6658 /* Validate the option length. */
6659 if(option_length != sizeof(UCHAR) && option_length != sizeof(INT))
6660 {
6661
6662 /* Set the socket error if extended socket options enabled. */
6663 nx_bsd_set_errno(EINVAL);
6664
6665 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6666 return NX_SOC_ERROR;
6667 }
6668
6669 /* Verify that the socket is still valid. */
6670 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
6671 {
6672
6673 /* Set the socket error if extended socket options enabled. */
6674 nx_bsd_set_errno(EBADF);
6675
6676 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6677 return NX_SOC_ERROR;
6678 }
6679
6680 /* Make sure socket is UDP type. */
6681 if(bsd_socket_ptr -> nx_bsd_socket_udp_socket == NX_NULL)
6682 {
6683 /* Set the socket error if extended socket options enabled. */
6684 nx_bsd_set_errno(ENOPROTOOPT);
6685
6686 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6687 return NX_SOC_ERROR;
6688 }
6689
6690 /* Set the TTL value. */
6691 if (option_length == sizeof(UCHAR))
6692 {
6693 bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_time_to_live = *(UCHAR*)option_value;
6694 }
6695 else
6696 {
6697 bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_time_to_live = (UCHAR)(*(INT*)option_value);
6698 }
6699 break;
6700
6701 case IP_MULTICAST_LOOP:
6702
6703 /* This is not supported yet. */
6704
6705 break;
6706
6707 case IP_MULTICAST_IF:
6708
6709 /* This is not supported yet. */
6710
6711 break;
6712
6713
6714 case IP_RAW_RX_NO_HEADER:
6715
6716 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
6717 i = *(INT*)option_value;
6718
6719 if((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET) &&
6720 ((bsd_socket_ptr -> nx_bsd_socket_family == AF_INET) || (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)))
6721 {
6722
6723 if(i)
6724 {
6725
6726 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_RX_NO_HDR;
6727 }
6728 else
6729 {
6730
6731 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_RX_NO_HDR);
6732 }
6733 }
6734 else
6735 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
6736 {
6737
6738 nx_bsd_set_errno(EINVAL);
6739
6740 /* Return an error status. */
6741 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6742
6743 return NX_SOC_ERROR;
6744 }
6745 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
6746 break;
6747 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
6748
6749 case IP_RAW_IPV6_HDRINCL:
6750
6751 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
6752 i = *(INT*)option_value;
6753
6754 /* Is this an IPv6 socket? */
6755 if((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET) &&
6756 (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6))
6757 {
6758
6759 /* Should the No Header feature be enabled (NX_TRUE)? */
6760 if(i)
6761 {
6762
6763 /* Yes, set the flag for no header. */
6764 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_TX_HDR_INCLUDE;
6765 }
6766 else
6767 {
6768
6769 /* No, clear the flag for no header. */
6770 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_TX_HDR_INCLUDE);
6771 }
6772 }
6773 else
6774 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
6775 {
6776
6777 nx_bsd_set_errno(EINVAL);
6778
6779 /* Return an error status. */
6780 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6781
6782 return NX_SOC_ERROR;
6783 }
6784 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
6785 break;
6786 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
6787
6788
6789 #ifndef NX_DISABLE_IPV4
6790 case IP_ADD_MEMBERSHIP:
6791 case IP_DROP_MEMBERSHIP:
6792
6793 /* Validate the option length */
6794 if(option_length != sizeof(struct nx_bsd_ip_mreq))
6795 {
6796
6797 /* Set the socket error if extended socket options enabled. */
6798 nx_bsd_set_errno(EINVAL);
6799
6800 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6801 return NX_SOC_ERROR;
6802 }
6803
6804 mreq = (struct nx_bsd_ip_mreq*)option_value;
6805
6806 /* Make sure the multicast group address is valid. */
6807 if((mreq -> imr_multiaddr.s_addr & ntohl(NX_IP_CLASS_D_TYPE)) != ntohl(NX_IP_CLASS_D_TYPE))
6808 {
6809 /* Set the socket error if extended socket options enabled. */
6810 nx_bsd_set_errno(EINVAL);
6811
6812 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6813 return NX_SOC_ERROR;
6814 }
6815
6816 /* Verify that the socket is still valid. */
6817 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
6818 {
6819 /* Set the socket error if extended socket options enabled. */
6820 nx_bsd_set_errno(EBADF);
6821
6822 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6823 return NX_SOC_ERROR;
6824 }
6825
6826 /* Make sure socket is UDP type. */
6827 if(bsd_socket_ptr -> nx_bsd_socket_udp_socket == NX_NULL)
6828 {
6829 /* Set the socket error if extended socket options enabled. */
6830 nx_bsd_set_errno(ENOPROTOOPT);
6831
6832 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6833 return NX_SOC_ERROR;
6834 }
6835
6836 /* Validate that the interface is one of the local IPv4 interfaces. */
6837 /* We allow imr_interface being zero to indicate the primary interface. */
6838 mcast_interface = NX_MAX_IP_INTERFACES;
6839
6840 if(mreq -> imr_interface.s_addr == INADDR_ANY)
6841 {
6842 mcast_interface = 0;
6843 }
6844 else
6845 {
6846
6847 /* Set the socket error if extended socket options enabled. */
6848 UINT addr;
6849
6850 /* Convert the local interface value to host byte order. */
6851 addr = ntohl(mreq -> imr_interface.s_addr);
6852
6853 /* Search through the interface table for a matching one. */
6854 for(i = 0; i < NX_MAX_IP_INTERFACES; i++)
6855 {
6856
6857 if(addr == nx_bsd_default_ip -> nx_ip_interface[i].nx_interface_ip_address)
6858 {
6859
6860 mcast_interface = (UINT)i;
6861 break;
6862 }
6863 }
6864 }
6865
6866 if(mcast_interface == NX_MAX_IP_INTERFACES)
6867 {
6868
6869 /* Did not find a matching interface. */
6870 nx_bsd_set_errno(EINVAL);
6871
6872 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6873 return NX_SOC_ERROR;
6874 }
6875
6876 if(option_name == IP_ADD_MEMBERSHIP)
6877 {
6878
6879 /* Make sure the IGMP feature is enabled. */
6880 if(nx_bsd_default_ip -> nx_ip_igmp_packet_receive == NX_NULL)
6881 {
6882 nx_igmp_enable(nx_bsd_default_ip);
6883 }
6884
6885 /* Join the group. */
6886 status = nx_igmp_multicast_interface_join(nx_bsd_default_ip, ntohl(mreq -> imr_multiaddr.s_addr), mcast_interface);
6887 }
6888 else
6889 {
6890
6891 /* Leave group */
6892 status = nx_igmp_multicast_leave(nx_bsd_default_ip, ntohl(mreq -> imr_multiaddr.s_addr));
6893 }
6894
6895 if(status != NX_SUCCESS)
6896 {
6897
6898 nx_bsd_set_errno(EINVAL);
6899
6900 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6901 return NX_SOC_ERROR;
6902 }
6903
6904 break;
6905 #endif /* NX_DISABLE_IPV4 */
6906
6907 case IP_HDRINCL:
6908
6909 #if defined(NX_ENABLE_IP_RAW_PACKET_FILTER) && !defined(NX_DISABLE_IPV4)
6910 i = *(INT*)option_value;
6911 /* First verify that raw socket processing is enabled on the IP instance and that this is
6912 an IPv4 thread. */
6913 if((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET) &&
6914 (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET))
6915 {
6916
6917 /* Is the option being enabled (NX_TRUE)? */
6918 if(i)
6919 {
6920
6921 /* Yes, set the flag bit indicating BSD will append the IP header. */
6922 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_TX_HDR_INCLUDE;
6923 }
6924 else
6925 {
6926
6927 /* No, clear the flag bit indicating IP task will append the IP header. */
6928 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_TX_HDR_INCLUDE);
6929 }
6930 }
6931 else
6932 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
6933 {
6934
6935 nx_bsd_set_errno(EINVAL);
6936
6937 /* Return an error status. */
6938 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6939
6940 return NX_SOC_ERROR;
6941 }
6942
6943 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
6944 break;
6945 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
6946
6947 default:
6948
6949 /* Set the socket error if extended socket options enabled. */
6950 nx_bsd_set_errno(EINVAL);
6951
6952 /* Return an error status. */
6953 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6954 return NX_SOC_ERROR;
6955 }
6956
6957 /* Socket option successfully updated. */
6958 return NX_SUCCESS;
6959 }
6960
6961
6962 /**************************************************************************/
6963 /* */
6964 /* FUNCTION RELEASE */
6965 /* */
6966 /* getsockname PORTABLE C */
6967 /* 6.3.0 */
6968 /* AUTHOR */
6969 /* */
6970 /* Yuxin Zhou, Microsoft Corporation */
6971 /* */
6972 /* DESCRIPTION */
6973 /* */
6974 /* This function returns the socket's primary interface address and */
6975 /* port. For NetX Duo environments, it returns the address at address */
6976 /* index 1 into the IP address table; this is where the primary */
6977 /* interface global IP address is normally located. */
6978 /* */
6979 /* INPUT */
6980 /* */
6981 /* sockID socket descriptor */
6982 /* localAddress sockaddr struct to return */
6983 /* the local address */
6984 /* addressLength Number of bytes in sockAddr */
6985 /* */
6986 /* OUTPUT */
6987 /* */
6988 /* NX_SOC_OK (0) On success */
6989 /* NX_SOC_ERROR (-1) On failure */
6990 /* */
6991 /* CALLS */
6992 /* */
6993 /* tx_mutex_get Get protection */
6994 /* tx_mutex_put Release protection */
6995 /* */
6996 /* CALLED BY */
6997 /* */
6998 /* Application Code */
6999 /* */
7000 /* RELEASE HISTORY */
7001 /* */
7002 /* DATE NAME DESCRIPTION */
7003 /* */
7004 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7005 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
7006 /* verified memcpy use cases, */
7007 /* resulting in version 6.1 */
7008 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
7009 /* used new API/structs naming,*/
7010 /* resulting in version 6.3.0 */
7011 /* */
7012 /**************************************************************************/
nx_bsd_getsockname(INT sockID,struct nx_bsd_sockaddr * localAddress,INT * addressLength)7013 INT nx_bsd_getsockname(INT sockID, struct nx_bsd_sockaddr *localAddress, INT *addressLength)
7014 {
7015
7016 #ifndef NX_DISABLE_IPV4
7017 struct nx_bsd_sockaddr_in soc_struct;
7018 #endif /* NX_DISABLE_IPV4 */
7019 #ifdef FEATURE_NX_IPV6
7020 struct nx_bsd_sockaddr_in6 soc6_struct;
7021 #endif
7022 UINT status;
7023 NX_BSD_SOCKET *bsd_socket_ptr;
7024
7025
7026 /* Check whether supplied socket ID is valid. */
7027 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
7028 {
7029
7030 /* Set the socket error if extended options enabled. */
7031 nx_bsd_set_errno(EBADF);
7032
7033 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7034 return(NX_SOC_ERROR);
7035 }
7036
7037 if((localAddress == NX_NULL) || (addressLength == NX_NULL) || (*addressLength == 0))
7038 {
7039
7040 /* Set the socket error if extended socket options enabled. */
7041 nx_bsd_set_errno(EINVAL);
7042
7043 /* Return error. */
7044 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7045 return(NX_SOC_ERROR);
7046 }
7047
7048 /* Normalize the socket ID. */
7049 sockID = sockID - NX_BSD_SOCKFD_START;
7050
7051 /* Setup pointer to socket. */
7052 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
7053
7054 /* Get the protection mutex. */
7055 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
7056
7057 /* Check the status. */
7058 if (status)
7059 {
7060
7061 /* Set the socket error if extended socket options enabled. */
7062 nx_bsd_set_errno(EACCES);
7063
7064 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
7065 return(NX_SOC_ERROR);
7066 }
7067
7068 /* Is the socket still in use? */
7069 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
7070 {
7071
7072 /* Set the socket error if extended options enabled. */
7073 nx_bsd_set_errno(EBADF);
7074 /* Release the protection mutex. */
7075 tx_mutex_put(nx_bsd_protection_ptr);
7076
7077 /* Return error. */
7078 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7079 return(NX_SOC_ERROR);
7080 }
7081
7082 if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND))
7083 {
7084 /* This socket is not bound yet. Just return.
7085 According to the spec, if the socket is not bound, the value stored in
7086 localAddress is unspecified. */
7087 /* Release the protection mutex. */
7088 tx_mutex_put(nx_bsd_protection_ptr);
7089
7090 /* Success! */
7091 return(NX_SOC_OK);
7092 }
7093
7094 #ifndef NX_DISABLE_IPV4
7095 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
7096 {
7097 if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
7098 {
7099 soc_struct.sin_addr.s_addr = INADDR_ANY;
7100 }
7101 else if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == 0)
7102 {
7103
7104 nx_bsd_set_errno(EINVAL);
7105
7106 /* Release the protection mutex. */
7107 tx_mutex_put(nx_bsd_protection_ptr);
7108
7109 /* Return error. */
7110 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7111 return(NX_SOC_ERROR);
7112 }
7113 else
7114 {
7115 NX_INTERFACE* local_if = (NX_INTERFACE*)(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface);
7116 soc_struct.sin_addr.s_addr = htonl(local_if -> nx_interface_ip_address);
7117 }
7118 soc_struct.sin_port = htons((USHORT)bsd_socket_ptr -> nx_bsd_socket_local_port);
7119
7120 soc_struct.sin_family = AF_INET;
7121
7122 if((*addressLength) > (INT)sizeof(struct nx_bsd_sockaddr_in))
7123 {
7124 *addressLength = sizeof(struct nx_bsd_sockaddr_in);
7125 }
7126 memcpy(localAddress, &soc_struct, (UINT)(*addressLength)); /* Use case of memcpy is verified. */
7127 }
7128 else
7129 #endif /* NX_DISABLE_IPV4 */
7130 #ifdef FEATURE_NX_IPV6
7131 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
7132 {
7133
7134
7135 if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
7136 {
7137 soc6_struct.sin6_addr._S6_un._S6_u32[0] = 0;
7138 soc6_struct.sin6_addr._S6_un._S6_u32[1] = 0;
7139 soc6_struct.sin6_addr._S6_un._S6_u32[2] = 0;
7140 soc6_struct.sin6_addr._S6_un._S6_u32[3] = 0;
7141 }
7142 else if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == 0)
7143 {
7144
7145 nx_bsd_set_errno(EINVAL);
7146
7147 /* Release the protection mutex. */
7148 tx_mutex_put(nx_bsd_protection_ptr);
7149
7150 /* Return error. */
7151 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7152 return(NX_SOC_ERROR);
7153 }
7154 else
7155 {
7156 NXD_IPV6_ADDRESS* local_v6if = (NXD_IPV6_ADDRESS*)(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface);
7157
7158 soc6_struct.sin6_addr._S6_un._S6_u32[0] = htonl(local_v6if -> nxd_ipv6_address[0]);
7159 soc6_struct.sin6_addr._S6_un._S6_u32[1] = htonl(local_v6if -> nxd_ipv6_address[1]);
7160 soc6_struct.sin6_addr._S6_un._S6_u32[2] = htonl(local_v6if -> nxd_ipv6_address[2]);
7161 soc6_struct.sin6_addr._S6_un._S6_u32[3] = htonl(local_v6if -> nxd_ipv6_address[3]);
7162 }
7163
7164 soc6_struct.sin6_port = htons((USHORT)bsd_socket_ptr -> nx_bsd_socket_local_port);
7165
7166 soc6_struct.sin6_family = AF_INET6;
7167
7168 if((*addressLength) > (INT)sizeof(struct nx_bsd_sockaddr_in6))
7169 {
7170 *addressLength = sizeof(struct nx_bsd_sockaddr_in6);
7171 }
7172 memcpy(localAddress, &soc6_struct, (UINT)(*addressLength)); /* Use case of memcpy is verified. */
7173
7174 }
7175 else
7176 #endif /* FEATURE_NX_IPV6 */
7177 {
7178
7179 /* Release the protection mutex. */
7180 tx_mutex_put(nx_bsd_protection_ptr);
7181
7182 nx_bsd_set_errno(EPROTONOSUPPORT);
7183
7184 /* Return error. */
7185 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7186 return(NX_SOC_ERROR);
7187 }
7188
7189
7190
7191 /* Release the protection mutex. */
7192 tx_mutex_put(nx_bsd_protection_ptr);
7193
7194 /* Success! */
7195 return(NX_SOC_OK);
7196 }
7197
7198
7199 /**************************************************************************/
7200 /* */
7201 /* FUNCTION RELEASE */
7202 /* */
7203 /* getpeername PORTABLE C */
7204 /* 6.3.0 */
7205 /* AUTHOR */
7206 /* */
7207 /* Yuxin Zhou, Microsoft Corporation */
7208 /* */
7209 /* DESCRIPTION */
7210 /* */
7211 /* This function returns the socket's remote address and port. */
7212 /* */
7213 /* INPUT */
7214 /* */
7215 /* sockID socket descriptor */
7216 /* localAddress sockaddr struct to return */
7217 /* the remote address */
7218 /* addressLength Number of bytes in sockAddr */
7219 /* */
7220 /* OUTPUT */
7221 /* */
7222 /* NX_SOC_OK (0) On success */
7223 /* NX_SOC_ERROR (-1) On failure */
7224 /* */
7225 /* CALLS */
7226 /* */
7227 /* tx_mutex_get Get protection */
7228 /* tx_mutex_put Release protection */
7229 /* */
7230 /* CALLED BY */
7231 /* */
7232 /* Application Code */
7233 /* */
7234 /* RELEASE HISTORY */
7235 /* */
7236 /* DATE NAME DESCRIPTION */
7237 /* */
7238 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7239 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7240 /* resulting in version 6.1 */
7241 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
7242 /* used new API/structs naming,*/
7243 /* resulting in version 6.3.0 */
7244 /* */
7245 /**************************************************************************/
nx_bsd_getpeername(INT sockID,struct nx_bsd_sockaddr * remoteAddress,INT * addressLength)7246 INT nx_bsd_getpeername(INT sockID, struct nx_bsd_sockaddr *remoteAddress, INT *addressLength)
7247 {
7248
7249 UINT status;
7250 NX_BSD_SOCKET *bsd_socket_ptr;
7251 #ifndef NX_DISABLE_IPV4
7252 struct nx_bsd_sockaddr_in *soc_struct_ptr = NX_NULL;
7253 #endif /* NX_DISABLE_IPV4 */
7254 #ifdef FEATURE_NX_IPV6
7255 struct nx_bsd_sockaddr_in6 *soc6_struct_ptr = NX_NULL;
7256 #endif
7257
7258
7259 /* Check whether supplied socket ID is valid. */
7260 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
7261 {
7262
7263 /* Set the socket error if extended socket options enabled. */
7264 nx_bsd_set_errno(EINVAL);
7265
7266 /* Error, invalid socket ID. */
7267 NX_BSD_ERROR(ERROR, __LINE__);
7268 return(ERROR);
7269 }
7270
7271 /* Normalize the socket ID. */
7272 sockID = sockID - NX_BSD_SOCKFD_START;
7273
7274 /* Check the remote address and length pointers. */
7275 if((remoteAddress == NX_NULL) ||(addressLength == NX_NULL))
7276 {
7277
7278 /* Set the socket error if extended socket options enabled. */
7279 nx_bsd_set_errno(EINVAL);
7280
7281 /* Return error. */
7282 NX_BSD_ERROR(ERROR, __LINE__);
7283 return(ERROR);
7284 }
7285
7286
7287 /* Get the protection mutex. */
7288 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
7289
7290 /* Check the status. */
7291 if (status)
7292 {
7293
7294 /* Set the socket error if extended socket options enabled. */
7295 nx_bsd_set_errno(EACCES);
7296
7297 /* Error getting the protection mutex. */
7298 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
7299 return(ERROR);
7300 }
7301
7302 /* Setup pointer to socket. */
7303 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
7304
7305 #ifndef NX_DISABLE_IPV4
7306 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
7307 {
7308
7309 /* This is an IPv4 only socket. */
7310
7311 /* Now validate the size of remoteAddress structure. */
7312 if(*addressLength < (INT)sizeof(struct nx_bsd_sockaddr_in))
7313 {
7314
7315 /* User supplied buffer is too small .*/
7316
7317 /* Release the protection mutex. */
7318 tx_mutex_put(nx_bsd_protection_ptr);
7319
7320 /* Set the socket error, if socket enabled with extended BSD features. */
7321 nx_bsd_set_errno(ESOCKTNOSUPPORT);
7322
7323 /* Return error. */
7324 NX_BSD_ERROR(ERROR, __LINE__);
7325 return(ERROR);
7326 }
7327
7328 soc_struct_ptr = (struct nx_bsd_sockaddr_in*)remoteAddress;
7329 *addressLength = sizeof(struct nx_bsd_sockaddr_in);
7330 }
7331 else
7332 #endif /* NX_DISABLE_IPV4 */
7333 #ifdef FEATURE_NX_IPV6
7334 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
7335 {
7336
7337 /* IPv6 socket */
7338
7339 /* Now validate the size of remoteAddress structure. */
7340 if(*addressLength < (INT)sizeof(struct nx_bsd_sockaddr_in6))
7341 {
7342
7343 /* User supplied buffer is too small .*/
7344
7345 /* Release the protection mutex. */
7346 tx_mutex_put(nx_bsd_protection_ptr);
7347
7348 /* Set the socket error, if socket enabled with extended BSD features. */
7349 nx_bsd_set_errno(ESOCKTNOSUPPORT);
7350
7351 /* Return error. */
7352 NX_BSD_ERROR(ERROR, __LINE__);
7353 return(ERROR);
7354 }
7355
7356 soc6_struct_ptr = (struct nx_bsd_sockaddr_in6*)remoteAddress;
7357 *addressLength = sizeof(struct nx_bsd_sockaddr_in6);
7358 }
7359 else
7360 #endif /* FEATURE_NX_IPV6 */
7361 {
7362
7363 /* Not a valid address family. */
7364 /* Release the protection mutex. */
7365 tx_mutex_put(nx_bsd_protection_ptr);
7366
7367 /* Set the socket error, if socket enabled with extended BSD features. */
7368 nx_bsd_set_errno(ESOCKTNOSUPPORT);
7369
7370 /* Return error. */
7371 NX_BSD_ERROR(ERROR, __LINE__);
7372 return(ERROR);
7373 }
7374
7375 /* Is the socket still in use? */
7376 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
7377 {
7378
7379 /* Error, socket not in use anymore. */
7380
7381 /* Release the protection mutex. */
7382 tx_mutex_put(nx_bsd_protection_ptr);
7383
7384 /* Set the socket error if extended options enabled. */
7385 nx_bsd_set_errno(EBADF);
7386
7387 /* Return error. */
7388 NX_BSD_ERROR(ERROR, __LINE__);
7389 return(ERROR);
7390 }
7391
7392 /* Check whether TCP or UDP */
7393 if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
7394 {
7395
7396 #ifndef NX_DISABLE_IPV4
7397 /* TCP Socket. Determine socket family type. */
7398 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
7399 {
7400
7401 soc_struct_ptr -> sin_family = AF_INET;
7402 soc_struct_ptr -> sin_port = htons((USHORT)bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_port);
7403 soc_struct_ptr -> sin_addr.s_addr = htonl(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v4);
7404 }
7405 else
7406 #endif /* NX_DISABLE_IPV4 */
7407 #ifdef FEATURE_NX_IPV6
7408 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
7409 {
7410
7411 soc6_struct_ptr -> sin6_family = AF_INET6;
7412 soc6_struct_ptr -> sin6_port = htons((USHORT)bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_port);
7413 soc6_struct_ptr -> sin6_addr._S6_un._S6_u32[0] = htonl(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[0]);
7414 soc6_struct_ptr -> sin6_addr._S6_un._S6_u32[1] = htonl(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[1]);
7415 soc6_struct_ptr -> sin6_addr._S6_un._S6_u32[2] = htonl(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[2]);
7416 soc6_struct_ptr -> sin6_addr._S6_un._S6_u32[3] = htonl(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[3]);
7417 }
7418 else
7419 #endif /* FEATURE_NX_IPV6 */
7420 {
7421
7422 /* Release the protection mutex. */
7423 tx_mutex_put(nx_bsd_protection_ptr);
7424
7425 /* Set the socket error if extended options enabled. */
7426 nx_bsd_set_errno(EBADF);
7427
7428 /* Return error. */
7429 NX_BSD_ERROR(ERROR, __LINE__);
7430 return(ERROR);
7431
7432 }
7433 }
7434 else if (bsd_socket_ptr -> nx_bsd_socket_udp_socket)
7435 {
7436
7437 #ifndef NX_DISABLE_IPV4
7438 /* UDP Socket. Get Peer Name doesn't apply to UDP sockets. Only fill in AF family information.*/
7439 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
7440 {
7441 soc_struct_ptr -> sin_family = AF_INET;
7442 soc_struct_ptr -> sin_port = 0;
7443 soc_struct_ptr -> sin_addr.s_addr = 0;
7444 }
7445 else
7446 #endif /* NX_DISABLE_IPV4 */
7447 #ifdef FEATURE_NX_IPV6
7448 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
7449 {
7450 soc6_struct_ptr -> sin6_family = AF_INET6;
7451 soc6_struct_ptr -> sin6_port = 0;
7452 }
7453 else
7454 #endif /* FEATURE_NX_IPV6 */
7455 {
7456
7457 /* Release the protection mutex. */
7458 tx_mutex_put(nx_bsd_protection_ptr);
7459
7460 /* Set the socket error, if socket enabled with extended BSD features. */
7461 nx_bsd_set_errno(ESOCKTNOSUPPORT);
7462
7463 /* Return error. */
7464 NX_BSD_ERROR(ERROR, __LINE__);
7465 return(ERROR);
7466
7467 }
7468 }
7469 else
7470 {
7471
7472 /* Release the protection mutex. */
7473 tx_mutex_put(nx_bsd_protection_ptr);
7474
7475 /* Set the socket error, if socket enabled with extended BSD features. */
7476 nx_bsd_set_errno(ESOCKTNOSUPPORT);
7477
7478 /* Return error. */
7479 NX_BSD_ERROR(ERROR, __LINE__);
7480 return(ERROR);
7481 }
7482
7483
7484 /* Release the protection mutex. */
7485 tx_mutex_put(nx_bsd_protection_ptr);
7486
7487 /* Success! */
7488 return(NX_SOC_OK);
7489 }
7490
7491 /**************************************************************************/
7492 /* */
7493 /* FUNCTION RELEASE */
7494 /* */
7495 /* select PORTABLE C */
7496 /* 6.3.0 */
7497 /* AUTHOR */
7498 /* */
7499 /* Yuxin Zhou, Microsoft Corporation */
7500 /* */
7501 /* DESCRIPTION */
7502 /* */
7503 /* This function allows for sockets to be checked for incoming packets.*/
7504 /* nfds should be one greater than value of the largest valued socket */
7505 /* descriptor in any of the lists. If you don't wish to calculate this,*/
7506 /* use FD_SETSIZE instead.For small numbers of sockets,select() will be*/
7507 /* less efficient if FD_SETSIZE is passed.If the bit corresponding to */
7508 /* a socket in an fd_set is set,that socket will be checked for the */
7509 /* condition the fd_set corresponds to.If the condition they are */
7510 /* checked for is true, they will still be set to true when select() */
7511 /* returns (otherwise they will be set to false). */
7512 /* Note that the sets are modified by select():thus they must be reset */
7513 /* between each call to the function. */
7514 /* */
7515 /* fd_sets can be manipulated using the following macros or functions: */
7516 /* */
7517 /* FD_SET(fd, fdset) Sets socket fd in fdset to true. */
7518 /* FD_CLR(fd, fdset) Sets socket fd in fdset to false. */
7519 /* FD_ISSET(fd, fdset)Returns true if socket fd is set to true in fdset*/
7520 /* FD_ZERO(fdset) Sets all the sockets in fdset to false. */
7521 /* */
7522 /* If the input timeout is NULL, select() blocks until one of the */
7523 /* sockets receives a packet. If the timeout is non-NULL, select waits */
7524 /* for the specified time and returns regardless if any socket has */
7525 /* received a packet. Otherwise as soon as a socket receives a packet */
7526 /* this function will return immediately. */
7527 /* */
7528 /* To use select() in non-blocking mode call it with a non-null timeout*/
7529 /* input but set tv_sec and tv_usec to zero, in Unix fashion. */
7530 /* */
7531 /* select() returns the number of sockets for which the specified */
7532 /* conditions are true. If it encounters an error, it will return -1. */
7533 /* */
7534 /* NOTE: ****** When select returns NX_SOC_ERROR it won't update */
7535 /* the readfds descriptor. */
7536 /* */
7537 /* INPUT */
7538 /* */
7539 /* nfds Maximum socket descriptor # */
7540 /* fd_set *readFDs List of read ready sockets */
7541 /* fd_set *writeFDs List of write ready sockets */
7542 /* fd_set *exceptFDs List of exceptions */
7543 /* struct timeval *timeOut */
7544 /* */
7545 /* OUTPUT */
7546 /* */
7547 /* NX_SUCCESS No descriptors read */
7548 /* (successful completion) */
7549 /* status Number of descriptors read */
7550 /* (< 0 if error occurred) */
7551 /* */
7552 /* CALLS */
7553 /* */
7554 /* FD_ZERO Clear a socket ready list */
7555 /* FD_ISSET Check a socket is ready */
7556 /* FD_SET Set a socket to check */
7557 /* nx_tcp_socket_receive Receive TCP packet */
7558 /* nx_udp_source_extract Extract source IP and port */
7559 /* tx_event_flags_get Get events */
7560 /* tx_mutex_get Get protection */
7561 /* tx_mutex_put Release protection */
7562 /* tx_thread_identify Get current thread pointer */
7563 /* tx_thread_preemption_change Disable/restore preemption */
7564 /* */
7565 /* CALLED BY */
7566 /* */
7567 /* Application Code */
7568 /* */
7569 /* RELEASE HISTORY */
7570 /* */
7571 /* DATE NAME DESCRIPTION */
7572 /* */
7573 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7574 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7575 /* resulting in version 6.1 */
7576 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
7577 /* used new API/structs naming,*/
7578 /* resulting in version 6.3.0 */
7579 /* */
7580 /**************************************************************************/
nx_bsd_select(INT nfds,nx_bsd_fd_set * readfds,nx_bsd_fd_set * writefds,nx_bsd_fd_set * exceptfds,struct nx_bsd_timeval * timeout)7581 INT nx_bsd_select(INT nfds, nx_bsd_fd_set *readfds, nx_bsd_fd_set *writefds, nx_bsd_fd_set *exceptfds, struct nx_bsd_timeval *timeout)
7582 {
7583
7584 INT i;
7585 UINT status;
7586 NX_BSD_SOCKET_SUSPEND suspend_request;
7587 NX_PACKET *packet_ptr;
7588 nx_bsd_fd_set readfds_found;
7589 nx_bsd_fd_set writefds_found;
7590 nx_bsd_fd_set exceptfds_found;
7591 INT readfds_left;
7592 INT writefds_left;
7593 INT exceptfds_left;
7594 ULONG ticks;
7595 UINT original_threshold;
7596 TX_THREAD *current_thread_ptr;
7597 INT ret;
7598
7599
7600 /* Check for valid input parameters. */
7601 if ((readfds == NX_NULL) && (writefds == NX_NULL) && (exceptfds == NX_NULL) && (timeout == NX_NULL))
7602 {
7603
7604 /* Set the socket error if extended socket options enabled. */
7605 nx_bsd_set_errno(EINVAL);
7606
7607 /* Return an error. */
7608 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7609 return(NX_SOC_ERROR);
7610 }
7611
7612 /* Check the maximum number of file descriptors. */
7613 if((nfds < (NX_BSD_SOCKFD_START + 1)) || (nfds >= (NX_BSD_MAX_SOCKETS + NX_BSD_SOCKFD_START + 1)))
7614 {
7615
7616 /* Set the socket error */
7617 nx_bsd_set_errno(EBADF);
7618
7619 /* Return an error. */
7620 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7621 return(NX_SOC_ERROR);
7622 }
7623
7624 /* Clear the read and the write selector set. */
7625 NX_BSD_FD_ZERO(&readfds_found);
7626 NX_BSD_FD_ZERO(&writefds_found);
7627 NX_BSD_FD_ZERO(&exceptfds_found);
7628
7629 if(readfds)
7630 readfds_left = readfds -> fd_count;
7631 else
7632 readfds_left = 0;
7633
7634 if(writefds)
7635 {
7636
7637 writefds_left = writefds -> fd_count;
7638 }
7639 else
7640 {
7641
7642 writefds_left = 0;
7643 }
7644
7645 if(exceptfds)
7646 {
7647
7648 exceptfds_left = exceptfds -> fd_count;
7649 }
7650 else
7651 {
7652
7653 exceptfds_left = 0;
7654 }
7655
7656 /* Compute the timeout for the suspension if a timeout value was supplied. */
7657 if (timeout != NX_NULL)
7658 {
7659
7660 /* Calculate ticks for the ThreadX Timer. */
7661 ticks = (ULONG)(timeout -> tv_usec)/NX_MICROSECOND_PER_CPU_TICK + (ULONG)(timeout -> tv_sec) * NX_IP_PERIODIC_RATE;
7662 }
7663 else
7664 {
7665
7666 /* If no timeout input, set the wait to 'forever.' */
7667 ticks = TX_WAIT_FOREVER;
7668 }
7669
7670 /* Get the protection mutex. */
7671 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
7672
7673 /* Check the status. */
7674 if (status != NX_SUCCESS)
7675 {
7676
7677 /* Set the socket error if extended socket options enabled. */
7678 nx_bsd_set_errno(EACCES);
7679
7680 /* Set the socket error. */
7681 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
7682 return(NX_SOC_ERROR);
7683 }
7684
7685 /* Loop through the BSD sockets to see if the read ready request can be satisfied. */
7686 for (i = 0; i < (nfds - NX_BSD_SOCKFD_START); i++)
7687 {
7688
7689 if((readfds == NX_NULL) || (readfds_left == 0))
7690 break;
7691
7692 /* Is this socket selected for read? */
7693 if (NX_BSD_FD_ISSET((i + NX_BSD_SOCKFD_START), readfds))
7694 {
7695
7696 /* Yes, decrement the number of read selectors left to search for. */
7697 readfds_left--;
7698
7699 /* Is this BSD socket in use? */
7700 if (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
7701 {
7702
7703 /* There is; add this socket to the read ready list. */
7704 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
7705 }
7706
7707 /* Check to see if there is a disconnection request pending. */
7708 else if (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_DISCONNECTION_REQUEST)
7709 {
7710
7711 /* There is; add this socket to the read ready list. */
7712 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
7713 }
7714
7715 /* Check to see if there is a receive packet pending. */
7716 else if (nx_bsd_socket_array[i].nx_bsd_socket_received_packet)
7717 {
7718
7719 /* Therer is; add this socket to the read ready list. */
7720 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
7721 }
7722 /* Is this a TCP socket? */
7723 else if (nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket)
7724 {
7725 /* Check if this is a master socket and if its associated secondary socket
7726 is connected. If it is, the master socket should be considered readable. */
7727 if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET)
7728 {
7729
7730 if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN)
7731 {
7732
7733 /* If the secondary socket does not exist, try to allocate one. */
7734 if(nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id >= NX_BSD_MAX_SOCKETS)
7735 {
7736
7737 /* This secondary socket is not avaialble yet. This could happen if the
7738 previous accept call fails to allocate a new secondary socket. */
7739 ret = nx_bsd_tcp_create_listen_socket(i, 0);
7740
7741 if(ret < 0)
7742 {
7743
7744 /* Mark the FD set so the application could be notified. */
7745 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
7746 }
7747 }
7748
7749 if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
7750 {
7751 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
7752 }
7753 }
7754 }
7755 else if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
7756 {
7757
7758 /* Yes; attempt to perform a non-blocking read. */
7759 status = nx_tcp_socket_receive(nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket, &packet_ptr, TX_NO_WAIT);
7760
7761 /* Check for success. */
7762 if (status == NX_SUCCESS)
7763 {
7764
7765 /* Save the received packet in the TCP BSD socket packet pointer. */
7766 nx_bsd_socket_array[i].nx_bsd_socket_received_packet = packet_ptr;
7767
7768 /* Reset the packet offset. */
7769 nx_bsd_socket_array[i].nx_bsd_socket_received_packet_offset = 0;
7770
7771 /* Increase the received count. */
7772 nx_bsd_socket_array[i].nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
7773 nx_bsd_socket_array[i].nx_bsd_socket_received_packet_count++;
7774
7775 /* Add this socket to the read ready list. */
7776 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
7777 }
7778 }
7779 }
7780 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
7781 /* Is this a raw socket? */
7782 else if (nx_bsd_socket_array[i].nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET)
7783 {
7784
7785 /* Check the raw receive queue (by definition has a zero wait option (no suspension)). */
7786 status = nx_bsd_raw_packet_receive(&nx_bsd_socket_array[i], &packet_ptr);
7787
7788 /* Determine if we have a packet. */
7789 if ((status == NX_SUCCESS) && (packet_ptr))
7790 {
7791
7792 /* Get the sender IP address from the raw packet. */
7793 status = nx_bsd_raw_packet_info_extract(packet_ptr, &(nx_bsd_socket_array[i].nx_bsd_socket_source_ip_address), NX_NULL);
7794
7795 /* Save the received packet in the BSD socket packet pointer. */
7796 nx_bsd_socket_array[i].nx_bsd_socket_received_packet = packet_ptr;
7797
7798 /* Reset the packet offset. */
7799 nx_bsd_socket_array[i].nx_bsd_socket_received_packet_offset = 0;
7800
7801 /* Add this socket to the read ready list. */
7802 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
7803 }
7804 }
7805 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
7806
7807 }
7808 }
7809 /* Loop through the BSD sockets to see if the write ready request can be satisfied. */
7810 for(i = 0; i < (nfds - NX_BSD_SOCKFD_START); i++)
7811 {
7812
7813 if((writefds == NX_NULL) || (writefds_left == 0))
7814 break;
7815
7816 /* Is this socket selected for write? */
7817 if (NX_BSD_FD_ISSET(i + NX_BSD_SOCKFD_START, writefds))
7818 {
7819
7820 /* Yes, decrement the number of read selectors left to search for. */
7821 writefds_left--;
7822
7823 /* Is this BSD socket in use? */
7824 if (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
7825 {
7826
7827 /* Yes, add this socket to the write ready list. */
7828 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &writefds_found);
7829 }
7830
7831 /* Check to see if there is a connection request pending. */
7832 else if (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_REQUEST)
7833 {
7834
7835 /* Yes, add this socket to the write ready list. */
7836 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &writefds_found);
7837 }
7838
7839 /* Check to see if there is an error.*/
7840 else if (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
7841 {
7842
7843 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &writefds_found);
7844 }
7845 }
7846 }
7847
7848 /* Loop through the BSD sockets to see if the exception request can be satisfied. */
7849 for(i = 0; i < (nfds - NX_BSD_SOCKFD_START); i++)
7850 {
7851
7852 if((exceptfds == NX_NULL) || (exceptfds_left == 0))
7853 break;
7854
7855 /* Is this socket selected for exceptions? */
7856 if (NX_BSD_FD_ISSET(i + NX_BSD_SOCKFD_START, exceptfds))
7857 {
7858
7859 /* Yes, decrement the number of read selectors left to search for. */
7860 exceptfds_left--;
7861
7862 /* Is this BSD socket in use? */
7863 if (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
7864 {
7865
7866 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &exceptfds_found);
7867 }
7868
7869 /* Check to see if there is an error.*/
7870 else if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
7871 {
7872
7873 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &exceptfds_found);
7874 }
7875 }
7876 }
7877
7878 /* Now determine if we have found anything that satisfies the select request. */
7879 if (readfds_found.fd_count || writefds_found.fd_count || exceptfds_found.fd_count)
7880 {
7881
7882 /* Yes, return what we have and we're done. */
7883
7884 /* Copy over the requested read ready fds. */
7885 if(readfds)
7886 *readfds = readfds_found;
7887
7888 if(writefds)
7889 *writefds = writefds_found;
7890
7891 if(exceptfds)
7892 *exceptfds = exceptfds_found;
7893
7894 /* Release the protection mutex. */
7895 tx_mutex_put(nx_bsd_protection_ptr);
7896
7897 /* Return the number of fds found. */
7898 return(readfds_found.fd_count + writefds_found.fd_count + exceptfds_found.fd_count);
7899 }
7900
7901 /* Otherwise, nothing is ready to be read at this point. */
7902
7903 /* Pickup the current thread. */
7904 current_thread_ptr = tx_thread_identify();
7905
7906 /* Save the fd requests in the local suspension structure. This will be used by the receive notify routines to
7907 wakeup threads on the select. */
7908 suspend_request.nx_bsd_socket_suspend_actual_flags = 0;
7909
7910 if(readfds)
7911 suspend_request.nx_bsd_socket_suspend_read_fd_set = *readfds;
7912 else
7913 NX_BSD_FD_ZERO(&suspend_request.nx_bsd_socket_suspend_read_fd_set);
7914
7915 if(writefds)
7916 suspend_request.nx_bsd_socket_suspend_write_fd_set = *writefds;
7917 else
7918 NX_BSD_FD_ZERO(&suspend_request.nx_bsd_socket_suspend_write_fd_set);
7919
7920 if(exceptfds)
7921 suspend_request.nx_bsd_socket_suspend_exception_fd_set = *exceptfds;
7922 else
7923 NX_BSD_FD_ZERO(&suspend_request.nx_bsd_socket_suspend_exception_fd_set);
7924
7925 /* Temporarily disable preemption. */
7926 tx_thread_preemption_change(current_thread_ptr, 0, &original_threshold);
7927
7928 /* Release the protection mutex. */
7929 tx_mutex_put(nx_bsd_protection_ptr);
7930
7931 status = tx_event_flags_get(&nx_bsd_events, NX_BSD_SELECT_EVENT, TX_OR_CLEAR, (ULONG *) &suspend_request, ticks);
7932
7933 /* Restore original preemption threshold. */
7934 tx_thread_preemption_change(current_thread_ptr, original_threshold, &original_threshold);
7935
7936 /* Check for an error. */
7937 if (status != NX_SUCCESS)
7938 {
7939
7940 /* If we got here, we received no packets. */
7941
7942 /* TX_NO_EVENT implies an immediate return from the flag get call.
7943 This happens if the wait option is set to zero. */
7944 if (status == TX_NO_EVENTS)
7945 {
7946
7947 /* Determine if the effected sockets are non blocking (zero ticks for the wait option). */
7948 if (ticks == 0)
7949 nx_bsd_set_errno(EWOULDBLOCK);
7950 else
7951 nx_bsd_set_errno(ETIMEDOUT);
7952
7953 /* Do not handle as an error; just a timeout so return 0. */
7954 return(0);
7955 }
7956 else
7957 {
7958
7959 /* Actual error. */
7960 /* Set the socket error if extended socket options enabled. */
7961 nx_bsd_set_errno(EINVAL);
7962
7963 /* Error getting the protection mutex. */
7964 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7965 return(NX_SOC_ERROR);
7966 }
7967 }
7968 else
7969 {
7970
7971 /* Otherwise, a receive event has been found. Simply copy the receive events. */
7972 if(readfds)
7973 *readfds = suspend_request.nx_bsd_socket_suspend_read_fd_set;
7974 if(writefds)
7975 *writefds = suspend_request.nx_bsd_socket_suspend_write_fd_set;
7976 if(exceptfds)
7977 *exceptfds = suspend_request.nx_bsd_socket_suspend_exception_fd_set;
7978
7979 /* Return the number of fds. */
7980 return(suspend_request.nx_bsd_socket_suspend_read_fd_set.fd_count +
7981 suspend_request.nx_bsd_socket_suspend_write_fd_set.fd_count +
7982 suspend_request.nx_bsd_socket_suspend_exception_fd_set.fd_count);
7983 }
7984
7985
7986 }
7987
7988
7989
7990 /**************************************************************************/
7991 /* */
7992 /* FUNCTION RELEASE */
7993 /* */
7994 /* nx_bsd_tcp_receive_notify PORTABLE C */
7995 /* 6.1 */
7996 /* AUTHOR */
7997 /* */
7998 /* Yuxin Zhou, Microsoft Corporation */
7999 /* */
8000 /* DESCRIPTION */
8001 /* */
8002 /* This is the NetX callback function for TCP Socket receive operation */
8003 /* This function resumes all the threads suspended on the socket. */
8004 /* */
8005 /* INPUT */
8006 /* */
8007 /* *socket_ptr Pointer to the socket which */
8008 /* received the data packet */
8009 /* */
8010 /* OUTPUT */
8011 /* */
8012 /* None */
8013 /* */
8014 /* CALLS */
8015 /* */
8016 /* FD_ZERO Clear a socket ready list */
8017 /* FD_ISSET Check a socket is ready */
8018 /* FD_SET Set a socket to check */
8019 /* tx_event_flags_get Get events */
8020 /* tx_mutex_get Get protection */
8021 /* tx_mutex_put Release protection */
8022 /* tx_thread_identify Get current thread pointer */
8023 /* */
8024 /* CALLED BY */
8025 /* */
8026 /* NetX */
8027 /* */
8028 /* RELEASE HISTORY */
8029 /* */
8030 /* DATE NAME DESCRIPTION */
8031 /* */
8032 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8033 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8034 /* resulting in version 6.1 */
8035 /* */
8036 /**************************************************************************/
nx_bsd_tcp_receive_notify(NX_TCP_SOCKET * socket_ptr)8037 static VOID nx_bsd_tcp_receive_notify(NX_TCP_SOCKET *socket_ptr)
8038 {
8039 UINT bsd_socket_index;
8040
8041 /* Figure out what BSD socket this is. */
8042 bsd_socket_index = (UINT) socket_ptr -> nx_tcp_socket_reserved_ptr;
8043
8044 /* Determine if this is a good index into the BSD socket array. */
8045 if (bsd_socket_index >= NX_BSD_MAX_SOCKETS)
8046 {
8047
8048 /* Bad socket index... simply return! */
8049 return;
8050 }
8051
8052 /* Now check if the socket may have been released (e.g. socket closed) while
8053 waiting for the mutex. */
8054 if( socket_ptr -> nx_tcp_socket_id == 0 )
8055 {
8056
8057 return;
8058 }
8059
8060 /* Check the suspended socket list for one ready to receive or send packets. */
8061 nx_bsd_select_wakeup(bsd_socket_index, FDSET_READ);
8062
8063
8064 return;
8065 }
8066
8067
8068 /**************************************************************************/
8069 /* */
8070 /* FUNCTION RELEASE */
8071 /* */
8072 /* nx_bsd_tcp_establish_notify PORTABLE C */
8073 /* 6.1 */
8074 /* AUTHOR */
8075 /* */
8076 /* Yuxin Zhou, Microsoft Corporation */
8077 /* */
8078 /* DESCRIPTION */
8079 /* */
8080 /* This is the NetX callback function for TCP Server Socket listen. */
8081 /* This function resumes all the threads suspended on the socket. */
8082 /* */
8083 /* INPUT */
8084 /* */
8085 /* *socket_ptr Pointer to the socket which */
8086 /* Received the data packet */
8087 /* */
8088 /* OUTPUT */
8089 /* */
8090 /* None */
8091 /* */
8092 /* CALLS */
8093 /* */
8094 /* FD_ZERO Clear a socket ready list */
8095 /* FD_ISSET Check a socket is ready */
8096 /* FD_SET Set a socket to check */
8097 /* tx_event_flags_get Get events */
8098 /* tx_mutex_get Get protection */
8099 /* tx_mutex_put Release protection */
8100 /* tx_thread_identify Get current thread pointer */
8101 /* */
8102 /* CALLED BY */
8103 /* */
8104 /* NetX */
8105 /* */
8106 /* RELEASE HISTORY */
8107 /* */
8108 /* DATE NAME DESCRIPTION */
8109 /* */
8110 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8111 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8112 /* resulting in version 6.1 */
8113 /* */
8114 /**************************************************************************/
8115 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
nx_bsd_tcp_establish_notify(NX_TCP_SOCKET * socket_ptr)8116 static VOID nx_bsd_tcp_establish_notify(NX_TCP_SOCKET *socket_ptr)
8117 {
8118 UINT bsd_socket_index;
8119 UINT master_socket_index;
8120
8121 /* Figure out what BSD socket this is. */
8122 bsd_socket_index = (UINT) socket_ptr -> nx_tcp_socket_reserved_ptr;
8123
8124 /* Determine if this is a good index into the BSD socket array. */
8125 if (bsd_socket_index >= NX_BSD_MAX_SOCKETS)
8126 {
8127
8128 /* Bad socket index... simply return! */
8129 return;
8130 }
8131
8132 /* Initialize the master socket index to an invalid value so we can check if it was actually used
8133 later. */
8134 master_socket_index = NX_BSD_MAX_SOCKETS;
8135
8136 /* Mark the socket as connected, and also clear the EINPROGRESS flag */
8137 nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
8138
8139 nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_REQUEST;
8140
8141 /* Reset the listen-enabled flag. */
8142 nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_LISTEN);
8143
8144 /* Mark the socket is bound. */
8145 nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
8146
8147 #ifndef NX_DISABLE_IPV4
8148 /* Find out the local address this socket is connected on. */
8149 if(nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_family == AF_INET)
8150 {
8151 /* IPv4 case */
8152 nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_local_bind_interface = (ULONG)socket_ptr -> nx_tcp_socket_connect_interface;
8153 }
8154 #endif /* NX_DISABLE_IPV4 */
8155 #ifdef FEATURE_NX_IPV6
8156 if(nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_family == AF_INET6)
8157 {
8158 /* IPv6 */
8159 nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_local_bind_interface = (ULONG)socket_ptr -> nx_tcp_socket_ipv6_addr;
8160 }
8161 #endif
8162 /* Determine if the BSD socket is server socket. */
8163
8164
8165 /* Is this a secondary socket? */
8166 if (nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET)
8167 {
8168
8169 /* Yes, get the master socket. */
8170 master_socket_index = (UINT)(nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_union_id.nx_bsd_socket_master_socket_id);
8171
8172 /* Mark the server socket as also connected. */
8173 nx_bsd_socket_array[master_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
8174
8175 nx_bsd_socket_array[master_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_REQUEST;
8176
8177 /* Check on connect requests for all server sockets for this master socket. */
8178 nx_bsd_select_wakeup(master_socket_index, FDSET_READ);
8179 }
8180 else
8181 {
8182 /* This is a client socket. */
8183 nx_bsd_select_wakeup(bsd_socket_index, FDSET_WRITE);
8184 }
8185 }
8186 #endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */
8187
8188 /**************************************************************************/
8189 /* */
8190 /* FUNCTION RELEASE */
8191 /* */
8192 /* nx_bsd_tcp_socket_disconnect_notify PORTABLE C */
8193 /* 6.1 */
8194 /* AUTHOR */
8195 /* */
8196 /* Yuxin Zhou, Microsoft Corporation */
8197 /* */
8198 /* DESCRIPTION */
8199 /* */
8200 /* This is the NetX callback function for TCP Socket disconnect. */
8201 /* This function resumes all the BSD threads suspended on the socket. */
8202 /* */
8203 /* INPUT */
8204 /* */
8205 /* *socket_ptr Pointer to the socket which */
8206 /* received the data packet */
8207 /* */
8208 /* OUTPUT */
8209 /* */
8210 /* None */
8211 /* */
8212 /* CALLS */
8213 /* */
8214 /* FD_ZERO Clear a socket ready list */
8215 /* FD_ISSET Check a socket is ready */
8216 /* FD_SET Set a socket to check */
8217 /* tx_event_flags_get Get events */
8218 /* tx_mutex_get Get protection */
8219 /* tx_mutex_put Release protection */
8220 /* tx_thread_identify Get current thread pointer */
8221 /* */
8222 /* CALLED BY */
8223 /* */
8224 /* NetX */
8225 /* */
8226 /* RELEASE HISTORY */
8227 /* */
8228 /* DATE NAME DESCRIPTION */
8229 /* */
8230 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8231 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8232 /* resulting in version 6.1 */
8233 /* */
8234 /**************************************************************************/
nx_bsd_tcp_socket_disconnect_notify(NX_TCP_SOCKET * socket_ptr)8235 static VOID nx_bsd_tcp_socket_disconnect_notify(NX_TCP_SOCKET *socket_ptr)
8236 {
8237
8238 UINT bsd_socket_index;
8239 UINT master_socket_index;
8240 NX_BSD_SOCKET *bsd_socket_ptr;
8241 UINT status;
8242
8243
8244 /* Figure out what BSD socket this is. */
8245 bsd_socket_index = (UINT) socket_ptr -> nx_tcp_socket_reserved_ptr;
8246
8247 /* Determine if this is a good index into the BSD socket array. */
8248 if (bsd_socket_index >= NX_BSD_MAX_SOCKETS)
8249 {
8250 /* No good! */
8251 return;
8252 }
8253
8254 bsd_socket_ptr = &nx_bsd_socket_array[bsd_socket_index];
8255
8256 /* If the socket already received a disconnect request, no need to do anything here. */
8257 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_DISCONNECTION_REQUEST)
8258 {
8259 return;
8260 }
8261
8262 /* Mark this socket as having a disconnect request pending. */
8263 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_DISCONNECTION_REQUEST;
8264
8265 /* Is the socket trying to make a connection? */
8266 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_INPROGRESS)
8267 {
8268
8269 /* Yes, clear the INPROGRESS flag. */
8270 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
8271
8272 /* If this is secondary server socket, there is no need to wake up the select call. */
8273 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET)
8274 {
8275
8276
8277 /* Instead the socket needs to be cleaned up and to perform a relisten. */
8278 if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED))
8279 {
8280
8281 /* Turn off the disconnection_request flag. */
8282 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_DISCONNECTION_REQUEST);
8283
8284 nx_tcp_server_socket_unaccept(bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
8285
8286 /* Check if a listen request is queued up for this socket. */
8287 nx_bsd_tcp_pending_connection(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port,
8288 bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
8289
8290 status = nx_tcp_server_socket_relisten(nx_bsd_default_ip,
8291 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port,
8292 bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
8293
8294 /* Force the socket into SYN_RECEIVED state */
8295 nx_tcp_server_socket_accept(bsd_socket_ptr -> nx_bsd_socket_tcp_socket, NX_NO_WAIT);
8296
8297 if(status == NX_CONNECTION_PENDING)
8298 {
8299
8300 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
8301 }
8302 else if(status != NX_SUCCESS)
8303 {
8304
8305 /* Failed the relisten on the secondary socket. Set the error code on the
8306 master socket, and wake it up. */
8307
8308 master_socket_index = (UINT)(bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id;
8309
8310 nx_bsd_socket_array[master_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
8311 nx_bsd_set_error_code(&nx_bsd_socket_array[master_socket_index], status);
8312
8313 nx_bsd_select_wakeup(master_socket_index, (FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION));
8314 }
8315 }
8316
8317 }
8318 else
8319 {
8320
8321 /* Set error code. */
8322 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
8323 bsd_socket_ptr -> nx_bsd_socket_error_code = ECONNREFUSED;
8324
8325 /* Wake up the select on both read and write FDsets. */
8326 nx_bsd_select_wakeup(bsd_socket_index, (FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION));
8327 }
8328 }
8329 else if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
8330 {
8331
8332 /* Wake up the select on both read and write FDsets. */
8333 nx_bsd_select_wakeup(bsd_socket_index, (FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION));
8334 }
8335 else
8336 {
8337
8338 /* In this case, connection reaches maximum retries or is refused by peer. */
8339 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
8340 bsd_socket_ptr -> nx_bsd_socket_error_code = ENOTCONN;
8341 }
8342
8343 }
8344
8345
8346
8347 /**************************************************************************/
8348 /* */
8349 /* FUNCTION RELEASE */
8350 /* */
8351 /* nx_bsd_udp_receive_notify PORTABLE C */
8352 /* 6.1 */
8353 /* AUTHOR */
8354 /* */
8355 /* Yuxin Zhou, Microsoft Corporation */
8356 /* */
8357 /* DESCRIPTION */
8358 /* */
8359 /* This is the NetX callback function for UDP Socket receive */
8360 /* operation. */
8361 /* */
8362 /* INPUT */
8363 /* */
8364 /* *socket_ptr Pointer to the socket which */
8365 /* Received the data packet */
8366 /* */
8367 /* OUTPUT */
8368 /* */
8369 /* None */
8370 /* */
8371 /* CALLS */
8372 /* */
8373 /* FD_ZERO Clear a socket ready list */
8374 /* FD_ISSET Check a socket is ready */
8375 /* FD_SET Set a socket to check */
8376 /* tx_event_flags_get Get events */
8377 /* tx_mutex_get Get protection */
8378 /* tx_mutex_put Release protection */
8379 /* tx_thread_identify Get current thread pointer */
8380 /* nx_udp_socket_receive Receive UDP packet */
8381 /* */
8382 /* CALLED BY */
8383 /* */
8384 /* NetX */
8385 /* */
8386 /* RELEASE HISTORY */
8387 /* */
8388 /* DATE NAME DESCRIPTION */
8389 /* */
8390 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8391 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8392 /* resulting in version 6.1 */
8393 /* */
8394 /**************************************************************************/
nx_bsd_udp_receive_notify(NX_UDP_SOCKET * socket_ptr)8395 static VOID nx_bsd_udp_receive_notify(NX_UDP_SOCKET *socket_ptr)
8396 {
8397
8398 UINT bsd_socket_index;
8399 NX_PACKET *packet_ptr;
8400 NX_UDP_SOCKET *udp_socket_ptr;
8401
8402
8403 /* Figure out what BSD socket this is. */
8404 bsd_socket_index = ((UINT) socket_ptr -> nx_udp_socket_reserved_ptr) & 0x0000FFFF;
8405
8406 /* Determine if this is a good index into the BSD socket array. */
8407 if (bsd_socket_index >= NX_BSD_MAX_SOCKETS)
8408 {
8409 return;
8410 }
8411
8412 udp_socket_ptr = nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_udp_socket;
8413
8414 if (nx_udp_socket_receive(udp_socket_ptr, &packet_ptr, NX_NO_WAIT))
8415 {
8416 return;
8417 }
8418
8419 nx_bsd_udp_packet_received((INT)bsd_socket_index, packet_ptr);
8420
8421 }
8422
8423
8424 /**************************************************************************/
8425 /* */
8426 /* FUNCTION RELEASE */
8427 /* */
8428 /* FD_SET PORTABLE C */
8429 /* 6.3.0 */
8430 /* AUTHOR */
8431 /* */
8432 /* Yuxin Zhou, Microsoft Corporation */
8433 /* */
8434 /* DESCRIPTION */
8435 /* */
8436 /* This function adds a fd to the set. */
8437 /* */
8438 /* INPUT */
8439 /* */
8440 /* fd fd to add. */
8441 /* fd_set *fdset fd set. */
8442 /* */
8443 /* OUTPUT */
8444 /* */
8445 /* None */
8446 /* */
8447 /* CALLS */
8448 /* */
8449 /* None */
8450 /* */
8451 /* CALLED BY */
8452 /* */
8453 /* Application Code */
8454 /* */
8455 /* RELEASE HISTORY */
8456 /* */
8457 /* DATE NAME DESCRIPTION */
8458 /* */
8459 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8460 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8461 /* resulting in version 6.1 */
8462 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
8463 /* used new API/structs naming,*/
8464 /* resulting in version 6.3.0 */
8465 /* */
8466 /**************************************************************************/
NX_BSD_FD_SET(INT fd,nx_bsd_fd_set * fdset)8467 VOID NX_BSD_FD_SET(INT fd, nx_bsd_fd_set *fdset)
8468 {
8469
8470 UINT index;
8471
8472
8473 /* Check the FD size. */
8474 if (fd >= NX_BSD_SOCKFD_START)
8475 {
8476
8477 /* Normalize the fd. */
8478 fd = fd - NX_BSD_SOCKFD_START;
8479
8480 /* Now make sure it isn't too big. */
8481 if (fd < NX_BSD_MAX_SOCKETS)
8482 {
8483
8484 /* Calculate the index into the bit map. */
8485 index = (UINT)fd/32;
8486
8487 /* Now calculate the bit position. */
8488 fd = fd % 32;
8489
8490 /* Is the bit already set? */
8491 if ((fdset -> fd_array[index] & (((ULONG) 1) << fd)) == 0)
8492 {
8493
8494 /* No, set the bit. */
8495 fdset -> fd_array[index] = fdset -> fd_array[index] | (((ULONG) 1) << fd);
8496
8497 /* Increment the counter. */
8498 fdset -> fd_count++;
8499 }
8500 }
8501 }
8502 }
8503
8504 /**************************************************************************/
8505 /* */
8506 /* FUNCTION RELEASE */
8507 /* */
8508 /* FD_CLR PORTABLE C */
8509 /* 6.3.0 */
8510 /* AUTHOR */
8511 /* */
8512 /* Yuxin Zhou, Microsoft Corporation */
8513 /* */
8514 /* DESCRIPTION */
8515 /* */
8516 /* This function removes a fd from a fd set. */
8517 /* */
8518 /* INPUT */
8519 /* */
8520 /* fd fd to remove. */
8521 /* fd_set *fdset fd set. */
8522 /* */
8523 /* OUTPUT */
8524 /* */
8525 /* None */
8526 /* */
8527 /* CALLS */
8528 /* */
8529 /* None */
8530 /* */
8531 /* CALLED BY */
8532 /* */
8533 /* Application Code */
8534 /* */
8535 /* RELEASE HISTORY */
8536 /* */
8537 /* DATE NAME DESCRIPTION */
8538 /* */
8539 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8540 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8541 /* resulting in version 6.1 */
8542 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
8543 /* used new API/structs naming,*/
8544 /* resulting in version 6.3.0 */
8545 /* */
8546 /**************************************************************************/
NX_BSD_FD_CLR(INT fd,nx_bsd_fd_set * fdset)8547 VOID NX_BSD_FD_CLR(INT fd, nx_bsd_fd_set *fdset)
8548 {
8549
8550 UINT index;
8551
8552
8553 /* Check the FD size. */
8554 if (fd >= NX_BSD_SOCKFD_START)
8555 {
8556
8557 /* Normalize the fd. */
8558 fd = fd - NX_BSD_SOCKFD_START;
8559
8560 /* Now make sure it isn't too big. */
8561 if ((fd < NX_BSD_MAX_SOCKETS) && (fdset -> fd_count))
8562 {
8563
8564 /* Calculate the index into the bit map. */
8565 index = (UINT)fd/32;
8566
8567 /* Now calculate the bit position. */
8568 fd = fd % 32;
8569
8570 /* Determine if the bit is set. */
8571 if (fdset -> fd_array[index] & (((ULONG) 1) << fd))
8572 {
8573
8574 /* Yes, clear the bit. */
8575 fdset -> fd_array[index] = fdset -> fd_array[index] & ~(((ULONG) 1) << fd);
8576
8577 /* Decrement the counter. */
8578 fdset -> fd_count--;
8579 }
8580 }
8581 }
8582 }
8583
8584
8585 /**************************************************************************/
8586 /* */
8587 /* FUNCTION RELEASE */
8588 /* */
8589 /* FD_ISSET PORTABLE C */
8590 /* 6.1 */
8591 /* AUTHOR */
8592 /* */
8593 /* Yuxin Zhou, Microsoft Corporation */
8594 /* */
8595 /* DESCRIPTION */
8596 /* */
8597 /* This function tests to see if a fd is in the set. */
8598 /* */
8599 /* INPUT */
8600 /* */
8601 /* fd fd to add. */
8602 /* fd_set *fdset fd set. */
8603 /* */
8604 /* OUTPUT */
8605 /* */
8606 /* NX_TRUE If fd is found in the set. */
8607 /* NX_FALSE If fd is not there in the set.*/
8608 /* */
8609 /* CALLS */
8610 /* */
8611 /* None */
8612 /* */
8613 /* CALLED BY */
8614 /* */
8615 /* Application Code */
8616 /* */
8617 /* RELEASE HISTORY */
8618 /* */
8619 /* DATE NAME DESCRIPTION */
8620 /* */
8621 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8622 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8623 /* resulting in version 6.1 */
8624 /* */
8625 /**************************************************************************/
NX_BSD_FD_ISSET(INT fd,nx_bsd_fd_set * fdset)8626 INT NX_BSD_FD_ISSET(INT fd, nx_bsd_fd_set *fdset)
8627 {
8628
8629 UINT index;
8630
8631
8632 /* Check the FD size. */
8633 if (fd >= NX_BSD_SOCKFD_START)
8634 {
8635
8636 /* Normalize the fd. */
8637 fd = fd - NX_BSD_SOCKFD_START;
8638
8639 /* Now make sure it isn't too big. */
8640 if (fd < NX_BSD_MAX_SOCKETS)
8641 {
8642
8643 /* Calculate the index into the bit map. */
8644 index = (UINT)fd/32;
8645
8646 /* Now calculate the bit position. */
8647 fd = fd % 32;
8648
8649 /* Finally, see if the bit is set. */
8650 if (fdset -> fd_array[index] & (((ULONG) 1) << fd))
8651 {
8652
8653 /* Yes, return true! */
8654 return(NX_TRUE);
8655 }
8656 }
8657 }
8658
8659 /* Otherwise, return false. */
8660 return(NX_FALSE);
8661 }
8662
8663
8664 /**************************************************************************/
8665 /* */
8666 /* FUNCTION RELEASE */
8667 /* */
8668 /* FD_ZERO PORTABLE C */
8669 /* 6.3.0 */
8670 /* AUTHOR */
8671 /* */
8672 /* Yuxin Zhou, Microsoft Corporation */
8673 /* */
8674 /* DESCRIPTION */
8675 /* */
8676 /* This function clears a fd set. */
8677 /* */
8678 /* INPUT */
8679 /* */
8680 /* fd_set *fdset fd set to clear. */
8681 /* */
8682 /* OUTPUT */
8683 /* */
8684 /* None */
8685 /* */
8686 /* CALLS */
8687 /* */
8688 /* None */
8689 /* */
8690 /* CALLED BY */
8691 /* */
8692 /* Application Code */
8693 /* */
8694 /* RELEASE HISTORY */
8695 /* */
8696 /* DATE NAME DESCRIPTION */
8697 /* */
8698 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8699 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8700 /* resulting in version 6.1 */
8701 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
8702 /* used new API/structs naming,*/
8703 /* resulting in version 6.3.0 */
8704 /* */
8705 /**************************************************************************/
NX_BSD_FD_ZERO(nx_bsd_fd_set * fdset)8706 VOID NX_BSD_FD_ZERO(nx_bsd_fd_set *fdset)
8707 {
8708
8709 INT i;
8710
8711
8712 /* Clear the count. */
8713 fdset -> fd_count = 0;
8714
8715 /* Loop to clear the fd set. */
8716 for (i = 0; i < (NX_BSD_MAX_SOCKETS+31)/32; i++)
8717 {
8718 /* Clear an entry in the array. */
8719 fdset -> fd_array[i] = 0;
8720 }
8721 }
8722
8723
8724 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
8725 /**************************************************************************/
8726 /* */
8727 /* FUNCTION RELEASE */
8728 /* */
8729 /* nx_bsd_raw_packet_filter PORTABLE C */
8730 /* 6.1.9 */
8731 /* AUTHOR */
8732 /* */
8733 /* Yuxin Zhou, Microsoft Corporation */
8734 /* */
8735 /* DESCRIPTION */
8736 /* */
8737 /* This function receives raw packets from NetX Duo and determines if */
8738 /* BSD will consume the packet (store on the BSD socket raw receive */
8739 /* queue) or if the packet is available to NetX Duo (not consumed). */
8740 /* */
8741 /* INPUT */
8742 /* */
8743 /* ip_ptr NetX Duo IP instance */
8744 /* protocol Received packet protocol */
8745 /* packet_ptr Pointer to the received packet */
8746 /* */
8747 /* OUTPUT */
8748 /* */
8749 /* 0 Raw filter consumed the packet*/
8750 /* 1 Raw filter did not consume */
8751 /* packet. Allow the caller to*/
8752 /* process this packet */
8753 /* */
8754 /* CALLS */
8755 /* */
8756 /* nx_bsd_raw_receive_notify Notify threads waiting to */
8757 /* receive a raw packet */
8758 /* */
8759 /* CALLED BY */
8760 /* */
8761 /* NetX Duo */
8762 /* */
8763 /* RELEASE HISTORY */
8764 /* */
8765 /* DATE NAME DESCRIPTION */
8766 /* */
8767 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8768 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8769 /* resulting in version 6.1 */
8770 /* 10-15-2021 Yuxin Zhou Modified comment(s), */
8771 /* fixed NULL pointer access */
8772 /* for raw socket, */
8773 /* resulting in version 6.1.9 */
8774 /* */
8775 /**************************************************************************/
nx_bsd_raw_packet_filter(NX_IP * ip_ptr,ULONG protocol,NX_PACKET * packet_ptr)8776 static UINT nx_bsd_raw_packet_filter(NX_IP *ip_ptr, ULONG protocol, NX_PACKET *packet_ptr)
8777 {
8778
8779 UINT index;
8780 NX_BSD_SOCKET * bsd_socket_ptr;
8781
8782 /* Calculate the hash index in the raw socket protocol table. */
8783 index = (UINT) ((protocol + (protocol >> 8)) & NX_BSD_SOCKET_RAW_PROTOCOL_TABLE_MASK);
8784
8785 /* Search the bound sockets in this index for particular protocol. */
8786 bsd_socket_ptr = nx_bsd_socket_raw_protocol_table[index];
8787
8788 /* Was a BSD socket with this protocol found? */
8789 if (bsd_socket_ptr == NX_NULL)
8790 {
8791 /* No, let NetX Duo continue processing the packet. */
8792 return 1;
8793 }
8794
8795 do
8796 {
8797 /* Determine if the protocol is matched. */
8798 if ((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE) &&
8799 (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET ) &&
8800 (bsd_socket_ptr -> nx_bsd_socket_protocol == protocol))
8801 {
8802
8803 /* This packet protocol matches the BSD socket. */
8804 /* Make sure the queue_next is zero'ed out. */
8805 packet_ptr -> nx_packet_queue_next = NX_NULL;
8806
8807 /* Add the packet to the BSD socket raw packet receive queue.
8808 Are there any packets on this queue yet? */
8809 if (bsd_socket_ptr -> nx_bsd_socket_received_packet == NX_NULL)
8810 {
8811
8812 /* No, this will be the only one. */
8813 bsd_socket_ptr -> nx_bsd_socket_received_packet = packet_ptr;
8814 bsd_socket_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
8815
8816
8817 /* Set the packet count. */
8818 bsd_socket_ptr -> nx_bsd_socket_received_byte_count = packet_ptr -> nx_packet_length;
8819 bsd_socket_ptr -> nx_bsd_socket_received_packet_count = 1;
8820 }
8821 else
8822 {
8823 /* Yes; add this packet to the end of the queue. */
8824
8825 /* Check if the queue is currently full. */
8826 if (bsd_socket_ptr -> nx_bsd_socket_received_byte_count_max &&
8827 (bsd_socket_ptr -> nx_bsd_socket_received_byte_count >=
8828 bsd_socket_ptr -> nx_bsd_socket_received_byte_count_max))
8829 {
8830
8831 /* Release the packet here, and tell NetX Duo the packet is 'consumed'. */
8832 nx_packet_release(packet_ptr);
8833
8834 return 0;
8835 }
8836
8837 /* Drop the packet if the receive queue exceeds max depth.*/
8838 if(bsd_socket_ptr -> nx_bsd_socket_received_packet_count >=
8839 bsd_socket_ptr -> nx_bsd_socket_received_packet_count_max)
8840 {
8841 /* Release the packet here, and tell NetX Duo the packet is 'consumed'. */
8842 nx_packet_release(packet_ptr);
8843
8844 return 0;
8845 }
8846
8847 /* Add this packet to the end of the BSD raw receive queue. */
8848 (bsd_socket_ptr -> nx_bsd_socket_received_packet_tail) -> nx_packet_queue_next = packet_ptr;
8849 bsd_socket_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
8850
8851
8852 /* Update our packet count. */
8853 bsd_socket_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
8854 bsd_socket_ptr -> nx_bsd_socket_received_packet_count++;
8855 }
8856
8857 /* Notify any suspended threads waiting on this receive event. */
8858 nx_bsd_raw_receive_notify(ip_ptr, (UINT)(bsd_socket_ptr -> nx_bsd_socket_id));
8859
8860 return 0;
8861 }
8862
8863 }while(bsd_socket_ptr != nx_bsd_socket_raw_protocol_table[index]);
8864
8865 /* Was a BSD socket with this protocol found? */
8866 if (bsd_socket_ptr == nx_bsd_socket_raw_protocol_table[index])
8867 {
8868 /* No, let NetX Duo continue processing the packet. */
8869 return 1;
8870 }
8871
8872 return(NX_SUCCESS);
8873 }
8874
8875 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
8876
8877
8878 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
8879 /**************************************************************************/
8880 /* */
8881 /* FUNCTION RELEASE */
8882 /* */
8883 /* nx_bsd_raw_receive_notify PORTABLE C */
8884 /* 6.1 */
8885 /* AUTHOR */
8886 /* */
8887 /* Yuxin Zhou, Microsoft Corporation */
8888 /* */
8889 /* DESCRIPTION */
8890 /* */
8891 /* This is the NetX Duo callback function for raw socket receive */
8892 /* operation. */
8893 /* */
8894 /* INPUT */
8895 /* */
8896 /* ip_ptr NetX Duo IP instance */
8897 /* bsd_socket_index Index of the raw socket which */
8898 /* received the data packet */
8899 /* */
8900 /* OUTPUT */
8901 /* */
8902 /* None */
8903 /* */
8904 /* CALLS */
8905 /* */
8906 /* FD_ZERO Clear a socket ready list */
8907 /* FD_ISSET Check a socket is ready */
8908 /* FD_SET Set a socket to check */
8909 /* tx_event_flags_get Get events */
8910 /* tx_mutex_get Get protection */
8911 /* tx_mutex_put Release protection */
8912 /* tx_thread_identify Get current thread pointer */
8913 /* */
8914 /* CALLED BY */
8915 /* */
8916 /* NetX */
8917 /* */
8918 /* RELEASE HISTORY */
8919 /* */
8920 /* DATE NAME DESCRIPTION */
8921 /* */
8922 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8923 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8924 /* resulting in version 6.1 */
8925 /* */
8926 /**************************************************************************/
nx_bsd_raw_receive_notify(NX_IP * ip_ptr,UINT bsd_socket_index)8927 VOID nx_bsd_raw_receive_notify(NX_IP *ip_ptr, UINT bsd_socket_index)
8928 {
8929 NX_PARAMETER_NOT_USED(ip_ptr);
8930
8931 nx_bsd_select_wakeup(bsd_socket_index, FDSET_READ);
8932
8933 }
8934
8935 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
8936
8937 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
8938
8939 /**************************************************************************/
8940 /* */
8941 /* FUNCTION RELEASE */
8942 /* */
8943 /* nx_bsd_raw_packet_receive PORTABLE C */
8944 /* 6.3.0 */
8945 /* AUTHOR */
8946 /* */
8947 /* Yuxin Zhou, Microsoft Corporation */
8948 /* */
8949 /* DESCRIPTION */
8950 /* */
8951 /* This function retrieves a packet from the BSD raw socket receive */
8952 /* queue. */
8953 /* */
8954 /* INPUT */
8955 /* */
8956 /* bsd_socket_ptr BSD raw socket */
8957 /* packet_ptr Pointer to retrieved packet */
8958 /* */
8959 /* OUTPUT */
8960 /* */
8961 /* NX_SUCCESS Packet successfully retrieved */
8962 /* NX_NO_PACKET No packet on receive queue */
8963 /* NX_NOT_ENABLED Not enabled for raw packets */
8964 /* */
8965 /* CALLS */
8966 /* */
8967 /* None */
8968 /* */
8969 /* CALLED BY */
8970 /* */
8971 /* select Checks for receive packets */
8972 /* recv Checks the specified socket for */
8973 /* received packets */
8974 /* */
8975 /* RELEASE HISTORY */
8976 /* */
8977 /* DATE NAME DESCRIPTION */
8978 /* */
8979 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8980 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8981 /* resulting in version 6.1 */
8982 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
8983 /* used new API/structs naming,*/
8984 /* resulting in version 6.3.0 */
8985 /* */
8986 /**************************************************************************/
nx_bsd_raw_packet_receive(NX_BSD_SOCKET * bsd_socket_ptr,NX_PACKET ** packet_ptr)8987 UINT nx_bsd_raw_packet_receive(NX_BSD_SOCKET *bsd_socket_ptr, NX_PACKET **packet_ptr)
8988 {
8989
8990
8991 /* Sanity check. Check this is indeed a raw socket. */
8992 if (!(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET))
8993 {
8994 /* Set the socket error. */
8995 nx_bsd_set_errno(EPROTOTYPE);
8996
8997 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
8998 return(NX_NOT_ENABLED);
8999 }
9000
9001 /* Verify this socket is enabled for raw packet processing. */
9002 if (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET)
9003 {
9004
9005 /* Are there any packets on the socket raw receive queue? */
9006 if (bsd_socket_ptr -> nx_bsd_socket_received_packet != NX_NULL)
9007 {
9008
9009 /* Yes, return a pointer to the packet at the top of the queue. */
9010 *packet_ptr = bsd_socket_ptr -> nx_bsd_socket_received_packet;
9011
9012 /* Update the packet count. */
9013 bsd_socket_ptr -> nx_bsd_socket_received_byte_count -= (*packet_ptr) -> nx_packet_length;
9014 bsd_socket_ptr -> nx_bsd_socket_received_packet_count--;
9015
9016
9017 /* Remove this packet from the receive queue and update queue packet pointers. */
9018 bsd_socket_ptr -> nx_bsd_socket_received_packet = (*packet_ptr) -> nx_packet_queue_next;
9019
9020 /* If this was the last packet, set the tail pointer to NULL. */
9021 if (bsd_socket_ptr -> nx_bsd_socket_received_packet == NX_NULL)
9022 {
9023 bsd_socket_ptr -> nx_bsd_socket_received_packet_tail = NX_NULL;
9024 bsd_socket_ptr -> nx_bsd_socket_received_byte_count = 0;
9025 bsd_socket_ptr -> nx_bsd_socket_received_packet_count = 0;
9026 }
9027 }
9028 else
9029 {
9030
9031 /* No packets on the queue. Return the NetX Duo status. This is an internal call, so no BSD socket error to report. */
9032 return NX_NO_PACKET;
9033 }
9034 }
9035 else
9036 {
9037 return NX_NOT_ENABLED;
9038 }
9039
9040 return NX_SUCCESS;
9041 }
9042
9043 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
9044
9045 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
9046 /**************************************************************************/
9047 /* */
9048 /* FUNCTION RELEASE */
9049 /* */
9050 /* nx_bsd_raw_packet_info_extract PORTABLE C */
9051 /* 6.1 */
9052 /* AUTHOR */
9053 /* */
9054 /* Yuxin Zhou, Microsoft Corporation */
9055 /* */
9056 /* DESCRIPTION */
9057 /* */
9058 /* This function extracts the source IP address and interface index */
9059 /* from the received packet. */
9060 /* */
9061 /* INPUT */
9062 /* */
9063 /* packet_ptr Pointer to received raw packet*/
9064 /* address Pointer to sender IP address */
9065 /* interface_index Pointer to network index */
9066 /* packet received on */
9067 /* */
9068 /* OUTPUT */
9069 /* */
9070 /* NX_SUCCESS Successful completion status */
9071 /* */
9072 /* CALLS */
9073 /* */
9074 /* COPY_IPV6_ADDRESS Copy IPv6 address */
9075 /* */
9076 /* CALLED BY */
9077 /* */
9078 /* Application Code */
9079 /* */
9080 /* RELEASE HISTORY */
9081 /* */
9082 /* DATE NAME DESCRIPTION */
9083 /* */
9084 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9085 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9086 /* resulting in version 6.1 */
9087 /* */
9088 /**************************************************************************/
nx_bsd_raw_packet_info_extract(NX_PACKET * packet_ptr,NXD_ADDRESS * address,UINT * interface_index)9089 UINT nx_bsd_raw_packet_info_extract(NX_PACKET *packet_ptr, NXD_ADDRESS *address, UINT *interface_index)
9090 {
9091
9092 NX_INTERFACE *if_ptr = NX_NULL;
9093
9094
9095 #ifndef NX_DISABLE_IPV4
9096 /* Determine what IP version the packet is. */
9097 if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
9098 {
9099
9100 NX_IPV4_HEADER *ip_header_ptr;
9101
9102 /* Set a pointer to the IPv4 header. */
9103 ip_header_ptr = (NX_IPV4_HEADER *)(packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_IPV4_HEADER));
9104
9105 /* Fill in the IP address information. */
9106 address -> nxd_ip_version = NX_IP_VERSION_V4;
9107 address -> nxd_ip_address.v4 = ip_header_ptr -> nx_ip_header_source_ip;
9108
9109 /* Pick up the packet interface. */
9110 if_ptr = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
9111 }
9112 #endif /* NX_DISABLE_IPV4 */
9113 #ifdef FEATURE_NX_IPV6
9114 if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
9115 {
9116
9117 NX_IPV6_HEADER *ipv6_header_ptr;
9118
9119 ipv6_header_ptr = (NX_IPV6_HEADER *)(packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_IPV6_HEADER));
9120
9121 /* Fill in the IPv6 address information. */
9122 address -> nxd_ip_version = NX_IP_VERSION_V6;
9123
9124 /* Copy the IPv6 address. */
9125 address -> nxd_ip_address.v6[0] = ipv6_header_ptr -> nx_ip_header_source_ip[0];
9126 address -> nxd_ip_address.v6[1] = ipv6_header_ptr -> nx_ip_header_source_ip[1];
9127 address -> nxd_ip_address.v6[2] = ipv6_header_ptr -> nx_ip_header_source_ip[2];
9128 address -> nxd_ip_address.v6[3] = ipv6_header_ptr -> nx_ip_header_source_ip[3];
9129
9130 /* Pick up the packet interface. */
9131 if_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
9132 }
9133 #endif
9134
9135 /* The last piece of information is the packet interface. If the return pointer is NULL we are done! */
9136 if(interface_index == NX_NULL)
9137 return(NX_SUCCESS);
9138
9139 /* Search for interface index number. Initialize interface value as
9140 invalid (0xFFFFFFFF). Once we find valid interface, we will update
9141 the returned value. */
9142 *interface_index = 0xFFFFFFFF;
9143
9144 if(if_ptr == NX_NULL)
9145 {
9146 /* No interface attached. Done here, and return success. */
9147 return(NX_SUCCESS);
9148 }
9149
9150 /* Compute the index by difference of the packet's interface from the primary interface, and dividing by the size. */
9151 *interface_index = if_ptr -> nx_interface_index;
9152
9153 return(NX_SUCCESS);
9154 }
9155
9156 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
9157
9158 /**************************************************************************/
9159 /* */
9160 /* FUNCTION RELEASE */
9161 /* */
9162 /* nx_bsd_set_socket_timed_wait_callback PORTABLE C */
9163 /* 6.1 */
9164 /* AUTHOR */
9165 /* */
9166 /* Yuxin Zhou, Microsoft Corporation */
9167 /* */
9168 /* DESCRIPTION */
9169 /* */
9170 /* This function is called when a BSD TCP socket has closed. If the */
9171 /* BSD socket associated with the TCP socket is not enabled for */
9172 /* REUSEADDR, this function will put the BSD socket in the TIMED WAIT */
9173 /* state. */
9174 /* */
9175 /* When this time out expires, the BSD socket is removed from the TIME */
9176 /* WAIT State and available to the host application. */
9177 /* */
9178 /* Note: only sockets not enabled with REUSEADDR are placed in the WAIT*/
9179 /* STATE. All other BSD sockets are immediately available upon closing.*/
9180 /* */
9181 /* INPUT */
9182 /* */
9183 /* tcp_socket_ptr TCP socket state being closed */
9184 /* */
9185 /* OUTPUT */
9186 /* */
9187 /* None */
9188 /* */
9189 /* CALLS */
9190 /* */
9191 /* tx_thread_identify Identify socket owning thread */
9192 /* tx_mutex_get Obtain BSD mutex protection */
9193 /* tx_mutex_put Release BSD mutex protection */
9194 /* */
9195 /* CALLED BY */
9196 /* */
9197 /* NetX */
9198 /* */
9199 /* RELEASE HISTORY */
9200 /* */
9201 /* DATE NAME DESCRIPTION */
9202 /* */
9203 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9204 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9205 /* resulting in version 6.1 */
9206 /* */
9207 /**************************************************************************/
nx_bsd_socket_timed_wait_callback(NX_TCP_SOCKET * tcp_socket_ptr)9208 VOID nx_bsd_socket_timed_wait_callback(NX_TCP_SOCKET *tcp_socket_ptr)
9209 {
9210 NX_PARAMETER_NOT_USED(tcp_socket_ptr);
9211
9212 /* Logic has been removed elsewhere but for compatibility with
9213 NetX we leave this function stub. */
9214
9215 return;
9216 }
9217
9218
9219
9220 /**************************************************************************/
9221 /* */
9222 /* FUNCTION RELEASE */
9223 /* */
9224 /* nx_packet_data_extract_offset PORTABLE C */
9225 /* 6.1 */
9226 /* AUTHOR */
9227 /* */
9228 /* Yuxin Zhou, Microsoft Corporation */
9229 /* */
9230 /* DESCRIPTION */
9231 /* */
9232 /* This function copies data from a NetX packet (or packet chain) into */
9233 /* the supplied user buffer. */
9234 /* */
9235 /* This basically defines the data extract service in the BSD source */
9236 /* code if it is not provided in the NetX or NetX Duo library already. */
9237 /* */
9238 /* INPUT */
9239 /* */
9240 /* packet_ptr Pointer to the source packet */
9241 /* buffer_start Pointer to destination data area */
9242 /* buffer_length Size in bytes */
9243 /* bytes_copied Number of bytes copied */
9244 /* */
9245 /* OUTPUT */
9246 /* */
9247 /* status Completion status */
9248 /* */
9249 /* CALLS */
9250 /* */
9251 /* None */
9252 /* */
9253 /* CALLED BY */
9254 /* */
9255 /* Application Code */
9256 /* */
9257 /* RELEASE HISTORY */
9258 /* */
9259 /* DATE NAME DESCRIPTION */
9260 /* */
9261 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9262 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
9263 /* verified memcpy use cases, */
9264 /* resulting in version 6.1 */
9265 /* */
9266 /**************************************************************************/
9267 #ifdef NX_BSD_INCLUDE_DATA_EXTRACT_OFFSET
nx_packet_data_extract_offset(NX_PACKET * packet_ptr,ULONG offset,VOID * buffer_start,ULONG buffer_length,ULONG * bytes_copied)9268 UINT nx_packet_data_extract_offset(NX_PACKET *packet_ptr, ULONG offset, VOID *buffer_start, ULONG buffer_length, ULONG *bytes_copied)
9269 {
9270
9271 ULONG remaining_bytes;
9272 UCHAR *source_ptr;
9273 UCHAR *destination_ptr;
9274 ULONG offset_bytes;
9275 #ifndef NX_DISABLE_PACKET_CHAIN
9276 ULONG packet_fragment_length;
9277 #endif
9278 ULONG bytes_to_copy;
9279 NX_PACKET *working_packet_ptr;
9280
9281 working_packet_ptr = packet_ptr;
9282
9283 /* Check for an invalid offset or packet length. */
9284 if(offset >= working_packet_ptr -> nx_packet_length)
9285 {
9286 /* Note: A zero offset with a packet of zero length is ok. */
9287 if ((offset == 0) && (working_packet_ptr -> nx_packet_length == 0))
9288 {
9289 *bytes_copied = 0;
9290 return(NX_SUCCESS);
9291 }
9292
9293 /* Otherwise, this is an invalid offset or packet length. */
9294 return(NX_PACKET_OFFSET_ERROR);
9295 }
9296
9297 /* Initialize the source pointer to NULL. */
9298 source_ptr = NX_NULL;
9299
9300 /* Traverse packet chain to offset. */
9301 offset_bytes = offset;
9302 #ifndef NX_DISABLE_PACKET_CHAIN
9303 while (working_packet_ptr)
9304 {
9305 packet_fragment_length = (working_packet_ptr -> nx_packet_append_ptr - working_packet_ptr -> nx_packet_prepend_ptr) ;
9306
9307 /* Determine if we are at the offset location fragment in the packet chain */
9308 if (packet_fragment_length > offset_bytes)
9309 {
9310 /* Setup loop to copy from this packet. */
9311 source_ptr = working_packet_ptr -> nx_packet_prepend_ptr + offset_bytes;
9312
9313 /* Yes, get out of this loop. */
9314 break;
9315 }
9316
9317 /* Decrement the remaining offset bytes*/
9318 offset_bytes = offset_bytes - packet_fragment_length ;
9319
9320 /* Move to next packet. */
9321 working_packet_ptr = working_packet_ptr -> nx_packet_next;
9322 }
9323 #else /* NX_DISABLE_PACKET_CHAIN */
9324
9325 /* Setup loop to copy from this packet. */
9326 source_ptr = working_packet_ptr -> nx_packet_prepend_ptr + offset_bytes;
9327
9328 #endif /* NX_DISABLE_PACKET_CHAIN */
9329
9330 /* Check for a valid source pointer. */
9331 if (source_ptr == NX_NULL)
9332 return(NX_PACKET_OFFSET_ERROR);
9333
9334 /* Setup the destination pointer. */
9335 destination_ptr = buffer_start;
9336 bytes_to_copy = (packet_ptr->nx_packet_length - offset);
9337
9338 /* Pickup the amount of bytes to copy. */
9339 if( bytes_to_copy < buffer_length)
9340 {
9341 *bytes_copied = bytes_to_copy; /* the amount of bytes returned to the caller */
9342 remaining_bytes = bytes_to_copy; /* for use in the copy loop */
9343 }
9344 else
9345 {
9346 *bytes_copied = buffer_length;
9347 remaining_bytes = buffer_length;
9348 }
9349
9350 #ifndef NX_DISABLE_PACKET_CHAIN
9351 /* Loop to copy bytes from packet(s). */
9352 while (working_packet_ptr && remaining_bytes)
9353 {
9354 #endif /* NX_DISABLE_PACKET_CHAIN */
9355
9356 /* Calculate bytes to copy. */
9357 bytes_to_copy = working_packet_ptr -> nx_packet_append_ptr - source_ptr;
9358 if(remaining_bytes < bytes_to_copy)
9359 bytes_to_copy = remaining_bytes;
9360
9361 /* Copy data from this packet. */
9362 memcpy(destination_ptr, source_ptr, bytes_to_copy); /* Use case of memcpy is verified. */
9363
9364 /* Update the pointers. */
9365 destination_ptr += bytes_to_copy;
9366 remaining_bytes -= bytes_to_copy;
9367
9368 #ifndef NX_DISABLE_PACKET_CHAIN
9369 /* Move to next packet. */
9370 working_packet_ptr = working_packet_ptr -> nx_packet_next;
9371
9372 /* Check for a next packet. */
9373 if (working_packet_ptr)
9374 {
9375
9376 /* Setup new source pointer. */
9377 source_ptr = working_packet_ptr -> nx_packet_prepend_ptr;
9378 }
9379 }
9380 #endif /* NX_DISABLE_PACKET_CHAIN */
9381
9382 /* Return successful completion. */
9383 return(NX_SUCCESS);
9384
9385 }
9386 #endif /* NX_BSD_INCLUDE_DATA_EXTRACT_OFFSET */
9387
9388 /**************************************************************************/
9389 /* */
9390 /* FUNCTION RELEASE */
9391 /* */
9392 /* nx_bsd_timer_entry PORTABLE C */
9393 /* 6.1 */
9394 /* AUTHOR */
9395 /* */
9396 /* Yuxin Zhou, Microsoft Corporation */
9397 /* */
9398 /* DESCRIPTION */
9399 /* */
9400 /* This function is called when the nx_bsd_socket_wait_timer expires. */
9401 /* It signals the BSD thread task to check and decrement the time */
9402 /* remaining on all sockets suspended in the wait state. */
9403 /* */
9404 /* INPUT */
9405 /* */
9406 /* info Timer thread data (not used) */
9407 /* */
9408 /* OUTPUT */
9409 /* */
9410 /* None */
9411 /* */
9412 /* CALLS */
9413 /* */
9414 /* tx_event_flags_set Sets the WAIT event in the BSD */
9415 /* event group */
9416 /* */
9417 /* CALLED BY */
9418 /* */
9419 /* ThreadX */
9420 /* */
9421 /* RELEASE HISTORY */
9422 /* */
9423 /* DATE NAME DESCRIPTION */
9424 /* */
9425 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9426 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9427 /* resulting in version 6.1 */
9428 /* */
9429 /**************************************************************************/
9430 #ifdef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
nx_bsd_timer_entry(ULONG info)9431 VOID nx_bsd_timer_entry(ULONG info)
9432 {
9433 nx_bsd_timeout_process();
9434 }
9435 #endif
9436
9437
9438 /**************************************************************************/
9439 /* */
9440 /* FUNCTION RELEASE */
9441 /* */
9442 /* nx_bsd_socket_set_inherited_settings PORTABLE C */
9443 /* 6.1 */
9444 /* AUTHOR */
9445 /* */
9446 /* Yuxin Zhou, Microsoft Corporation */
9447 /* */
9448 /* DESCRIPTION */
9449 /* */
9450 /* This function applies the socket options of the specified parent */
9451 /* (master) socket to the specified child (secondary) socket, if BSD */
9452 /* extended socket options are enabled. If they are not, this function */
9453 /* has no effect. */
9454 /* */
9455 /* INPUT */
9456 /* */
9457 /* master_sock_id Source of socket options */
9458 /* secondary_sock_id Socket inheriting options */
9459 /* */
9460 /* OUTPUT */
9461 /* */
9462 /* NX_SUCCESS Successful completion */
9463 /* */
9464 /* CALLS */
9465 /* */
9466 /* None */
9467 /* */
9468 /* CALLED BY */
9469 /* */
9470 /* ThreadX */
9471 /* */
9472 /* RELEASE HISTORY */
9473 /* */
9474 /* DATE NAME DESCRIPTION */
9475 /* */
9476 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9477 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9478 /* resulting in version 6.1 */
9479 /* */
9480 /**************************************************************************/
nx_bsd_socket_set_inherited_settings(UINT master_sock_id,UINT secondary_sock_id)9481 UINT nx_bsd_socket_set_inherited_settings(UINT master_sock_id, UINT secondary_sock_id)
9482 {
9483
9484 /* Update the secondary socket options from the master socket. */
9485 if(nx_bsd_socket_array[master_sock_id].nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING)
9486 nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING;
9487 else
9488 nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING);
9489
9490 if(nx_bsd_socket_array[master_sock_id].nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR)
9491 nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR;
9492 else
9493 nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR);
9494
9495 #ifdef NX_ENABLE_TCP_WINDOW_SCALING
9496 nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_maximum =
9497 nx_bsd_socket_array[master_sock_id].nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_maximum;
9498 #endif
9499
9500
9501 /* Does this version of NetX Duo support TCP keep alive? */
9502 /* Is NetX Duo currently enabled for TCP keep alive? */
9503 #ifdef NX_ENABLE_TCP_KEEPALIVE
9504
9505 nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled =
9506 nx_bsd_socket_array[master_sock_id].nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled;
9507
9508 #endif /* NX_ENABLE_TCP_KEEPALIVE */
9509
9510
9511 return NX_SUCCESS;
9512 }
9513
9514
9515 /**************************************************************************/
9516 /* */
9517 /* FUNCTION RELEASE */
9518 /* */
9519 /* nx_bsd_isspace PORTABLE C */
9520 /* 6.1 */
9521 /* AUTHOR */
9522 /* */
9523 /* Yuxin Zhou, Microsoft Corporation */
9524 /* */
9525 /* DESCRIPTION */
9526 /* */
9527 /* This function determines if the input character is white space */
9528 /* (ascii characters 0x09 - 0x0D or space (0x20). */
9529 /* */
9530 /* INPUT */
9531 /* */
9532 /* c Input character to examine */
9533 /* */
9534 /* OUTPUT */
9535 /* */
9536 /* NX_TRUE Input character is white space */
9537 /* NX_FALSE Input character not white space*/
9538 /* */
9539 /* CALLS */
9540 /* */
9541 /* None */
9542 /* */
9543 /* CALLED BY */
9544 /* */
9545 /* ThreadX */
9546 /* */
9547 /* RELEASE HISTORY */
9548 /* */
9549 /* DATE NAME DESCRIPTION */
9550 /* */
9551 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9552 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9553 /* resulting in version 6.1 */
9554 /* */
9555 /**************************************************************************/
nx_bsd_isspace(UCHAR c)9556 static UINT nx_bsd_isspace(UCHAR c)
9557 {
9558
9559 /* Check for horizontal, vertical tabs, carriage return or formfeed characters. */
9560 if ((c >= 0x09) && (c <= 0x0D))
9561 {
9562 return NX_TRUE;
9563 }
9564 /* Check for a single space character*/
9565 else if (c == 20)
9566 {
9567 return NX_TRUE;
9568 }
9569 else
9570 /* Not a white space character. */
9571 return NX_FALSE;
9572 }
9573
9574
9575 /**************************************************************************/
9576 /* */
9577 /* FUNCTION RELEASE */
9578 /* */
9579 /* nx_bsd_islower PORTABLE C */
9580 /* 6.1 */
9581 /* AUTHOR */
9582 /* */
9583 /* Yuxin Zhou, Microsoft Corporation */
9584 /* */
9585 /* DESCRIPTION */
9586 /* */
9587 /* This function determines if the input character is lower case */
9588 /* alphabetic character. */
9589 /* */
9590 /* INPUT */
9591 /* */
9592 /* c Input character to examine */
9593 /* */
9594 /* OUTPUT */
9595 /* */
9596 /* NX_TRUE Input character is lower case */
9597 /* NX_FALSE Input character not lower case */
9598 /* */
9599 /* CALLS */
9600 /* */
9601 /* None */
9602 /* */
9603 /* CALLED BY */
9604 /* */
9605 /* ThreadX */
9606 /* */
9607 /* RELEASE HISTORY */
9608 /* */
9609 /* DATE NAME DESCRIPTION */
9610 /* */
9611 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9612 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9613 /* resulting in version 6.1 */
9614 /* */
9615 /**************************************************************************/
nx_bsd_islower(UCHAR c)9616 static UINT nx_bsd_islower(UCHAR c)
9617 {
9618
9619 /* Check if characters is any character 'a' through 'z'. */
9620 if ((c >= 0x61) && (c <= 0x7A))
9621 {
9622
9623 return NX_TRUE;
9624 }
9625 else
9626 return NX_FALSE;
9627
9628 }
9629
9630 /**************************************************************************/
9631 /* */
9632 /* FUNCTION RELEASE */
9633 /* */
9634 /* nx_bsd_isdigit PORTABLE C */
9635 /* 6.1 */
9636 /* AUTHOR */
9637 /* */
9638 /* Yuxin Zhou, Microsoft Corporation */
9639 /* */
9640 /* DESCRIPTION */
9641 /* */
9642 /* This function determines if the input character is a digit (0-9) */
9643 /* Does not include hex digits, (see nx_bsd_isxdigit). */
9644 /* */
9645 /* INPUT */
9646 /* */
9647 /* c Input character to examine */
9648 /* */
9649 /* OUTPUT */
9650 /* */
9651 /* NX_TRUE Input character is a digit */
9652 /* NX_FALSE Input character not a digit */
9653 /* */
9654 /* CALLS */
9655 /* */
9656 /* None */
9657 /* */
9658 /* CALLED BY */
9659 /* */
9660 /* ThreadX */
9661 /* */
9662 /* RELEASE HISTORY */
9663 /* */
9664 /* DATE NAME DESCRIPTION */
9665 /* */
9666 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9667 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9668 /* resulting in version 6.1 */
9669 /* */
9670 /**************************************************************************/
nx_bsd_isdigit(UCHAR c)9671 static UINT nx_bsd_isdigit(UCHAR c)
9672 {
9673
9674 /* Is the character any digit between 0 and 9? */
9675 if ((c >= 0x30) && (c <= 0x39))
9676 {
9677 return NX_TRUE;
9678 }
9679 else
9680 return NX_FALSE;
9681 }
9682
9683
9684 /**************************************************************************/
9685 /* */
9686 /* FUNCTION RELEASE */
9687 /* */
9688 /* nx_bsd_isxdigit PORTABLE C */
9689 /* 6.1 */
9690 /* AUTHOR */
9691 /* */
9692 /* Yuxin Zhou, Microsoft Corporation */
9693 /* */
9694 /* DESCRIPTION */
9695 /* */
9696 /* This function determines if the input character is a digit (0-9) */
9697 /* or hex digit (A - F, or a-f). For decimal digits, see */
9698 /* nx_bsd_isdigit. */
9699 /* */
9700 /* INPUT */
9701 /* */
9702 /* c Input character to examine */
9703 /* */
9704 /* OUTPUT */
9705 /* */
9706 /* NX_TRUE Input character is hex digit */
9707 /* NX_FALSE Input character not hex digit */
9708 /* */
9709 /* CALLS */
9710 /* */
9711 /* None */
9712 /* */
9713 /* CALLED BY */
9714 /* */
9715 /* ThreadX */
9716 /* */
9717 /* RELEASE HISTORY */
9718 /* */
9719 /* DATE NAME DESCRIPTION */
9720 /* */
9721 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9722 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9723 /* resulting in version 6.1 */
9724 /* */
9725 /**************************************************************************/
nx_bsd_isxdigit(UCHAR c)9726 static UINT nx_bsd_isxdigit(UCHAR c)
9727 {
9728
9729 /* Is the character any digit between 0 - 9? */
9730 if ((c >= 0x30) && (c <= 0x39))
9731 {
9732 return NX_TRUE;
9733 }
9734
9735 /* Or is the character any base 16 digit A-F? */
9736 if ((c >= 0x41) && (c <= 0x46))
9737 {
9738 return NX_TRUE;
9739 }
9740
9741 /* Lastly, check if character is any base 16 digit a-f? */
9742 if ((c >= 0x61) && (c <= 0x66))
9743 {
9744 return NX_TRUE;
9745 }
9746 else
9747 return NX_FALSE;
9748 }
9749
9750 /**************************************************************************/
9751 /* */
9752 /* FUNCTION RELEASE */
9753 /* */
9754 /* set_errno PORTABLE C */
9755 /* 6.3.0 */
9756 /* AUTHOR */
9757 /* */
9758 /* Yuxin Zhou, Microsoft Corporation */
9759 /* */
9760 /* DESCRIPTION */
9761 /* */
9762 /* This function sets the error on the current socket (thread) for */
9763 /* sockets enabled with BSD extended socket options. For sockets not */
9764 /* enabled with extended features, this function has no effect. */
9765 /* */
9766 /* INPUT */
9767 /* */
9768 /* tx_errno Socket error status code */
9769 /* */
9770 /* OUTPUT */
9771 /* */
9772 /* None */
9773 /* */
9774 /* CALLS */
9775 /* */
9776 /* None */
9777 /* */
9778 /* CALLED BY */
9779 /* */
9780 /* ThreadX */
9781 /* */
9782 /* RELEASE HISTORY */
9783 /* */
9784 /* DATE NAME DESCRIPTION */
9785 /* */
9786 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9787 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9788 /* resulting in version 6.1 */
9789 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
9790 /* used new API/structs naming,*/
9791 /* resulting in version 6.3.0 */
9792 /* */
9793 /**************************************************************************/
nx_bsd_set_errno(INT tx_errno)9794 VOID nx_bsd_set_errno(INT tx_errno)
9795 {
9796
9797 TX_INTERRUPT_SAVE_AREA
9798 TX_THREAD *current_thread_ptr;
9799
9800
9801 TX_DISABLE
9802
9803 current_thread_ptr = tx_thread_identify();
9804 current_thread_ptr -> bsd_errno = tx_errno;
9805
9806 TX_RESTORE
9807
9808 return;
9809 }
9810
9811 /**************************************************************************/
9812 /* */
9813 /* FUNCTION RELEASE */
9814 /* */
9815 /* get_errno PORTABLE C */
9816 /* 6.1 */
9817 /* AUTHOR */
9818 /* */
9819 /* Yuxin Zhou, Microsoft Corporation */
9820 /* */
9821 /* DESCRIPTION */
9822 /* */
9823 /* This function retrieves the error on the current socket (thread) for*/
9824 /* sockets enabled with BSD extended socket options. For sockets not */
9825 /* enabled with extended features, this function has no effect. */
9826 /* */
9827 /* INPUT */
9828 /* */
9829 /* None */
9830 /* */
9831 /* OUTPUT */
9832 /* */
9833 /* Socket error status code */
9834 /* */
9835 /* CALLS */
9836 /* */
9837 /* None */
9838 /* */
9839 /* CALLED BY */
9840 /* */
9841 /* ThreadX */
9842 /* */
9843 /* RELEASE HISTORY */
9844 /* */
9845 /* DATE NAME DESCRIPTION */
9846 /* */
9847 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9848 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9849 /* resulting in version 6.1 */
9850 /* */
9851 /**************************************************************************/
_nxd_get_errno()9852 INT _nxd_get_errno()
9853 {
9854
9855 TX_INTERRUPT_SAVE_AREA
9856 INT val;
9857 TX_THREAD *current_thread_ptr;
9858
9859
9860 TX_DISABLE
9861
9862 current_thread_ptr = tx_thread_identify();
9863 val = current_thread_ptr -> bsd_errno;
9864
9865 TX_RESTORE
9866
9867 return (val);
9868 }
9869
9870
9871 /**************************************************************************/
9872 /* */
9873 /* FUNCTION RELEASE */
9874 /* */
9875 /* nx_bsd_select_wakeup PORTABLE C */
9876 /* 6.3.0 */
9877 /* AUTHOR */
9878 /* */
9879 /* Yuxin Zhou, Microsoft Corporation */
9880 /* */
9881 /* DESCRIPTION */
9882 /* */
9883 /* This function checks the suspend list for a given socket being */
9884 /* readable or writeable. */
9885 /* */
9886 /* INPUT */
9887 /* */
9888 /* sock_id BSD socket ID */
9889 /* fd_sets The FD set to check */
9890 /* */
9891 /* OUTPUT */
9892 /* */
9893 /* None */
9894 /* */
9895 /* CALLS */
9896 /* */
9897 /* FD_ZERO Zeros out an FD Set */
9898 /* FD_SET Set a socket in the FDSET */
9899 /* TX_DISABLE Disable Interrupt */
9900 /* TX_RESTORE Enable Interrupt */
9901 /* tx_event_flags_set Set an event flag */
9902 /* */
9903 /* CALLED BY */
9904 /* */
9905 /* nx_bsd_timeout_process */
9906 /* nx_bsd_tcp_receive_notify */
9907 /* nx_bsd_tcp_establish_notify */
9908 /* nx_bsd_tcp_socket_disconnect_notify */
9909 /* nx_bsd_raw_receive_notify */
9910 /* nx_bsd_udp_packet_received */
9911 /* */
9912 /* RELEASE HISTORY */
9913 /* */
9914 /* DATE NAME DESCRIPTION */
9915 /* */
9916 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9917 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9918 /* resulting in version 6.1 */
9919 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
9920 /* used new API/structs naming,*/
9921 /* resulting in version 6.3.0 */
9922 /* */
9923 /**************************************************************************/
nx_bsd_select_wakeup(UINT sock_id,UINT fd_sets)9924 static VOID nx_bsd_select_wakeup(UINT sock_id, UINT fd_sets)
9925 {
9926 TX_INTERRUPT_SAVE_AREA
9927 nx_bsd_fd_set local_fd;
9928 TX_THREAD *suspended_thread;
9929 ULONG suspended_count;
9930 ULONG original_suspended_count;
9931 NX_BSD_SOCKET_SUSPEND *suspend_info;
9932
9933
9934 /* At this point the thread should NOT own the IP mutex, and it must own the
9935 BSD mutex. */
9936
9937
9938 NX_BSD_FD_ZERO(&local_fd);
9939 NX_BSD_FD_SET((INT)sock_id + NX_BSD_SOCKFD_START, &local_fd);
9940
9941 /* Disable interrupts temporarily. */
9942 TX_DISABLE
9943
9944 /* Setup the head pointer and the count. */
9945 suspended_thread = nx_bsd_events.tx_event_flags_group_suspension_list;
9946 suspended_count = nx_bsd_events.tx_event_flags_group_suspended_count;
9947
9948 /* Save the original suspended count. */
9949 original_suspended_count = suspended_count;
9950
9951 /* Loop to examine all threads suspended on select via the BSD event flag group. */
9952 while (suspended_count--)
9953 {
9954
9955 /* Determine if this thread is suspended on select. */
9956 if (suspended_thread -> tx_thread_suspend_info == NX_BSD_SELECT_EVENT)
9957 {
9958
9959 /* Yes, this thread is suspended on select. */
9960
9961 /* Pickup a pointer to its select suspend structure. */
9962 suspend_info = (NX_BSD_SOCKET_SUSPEND *) suspended_thread -> tx_thread_additional_suspend_info;
9963
9964 /* Now determine if this thread was waiting for this socket. */
9965 if ((fd_sets & FDSET_READ) && (NX_BSD_FD_ISSET((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_read_fd_set)))
9966 {
9967
9968 /* Copy the local fd over so that the return shows the receive socket. */
9969 suspend_info -> nx_bsd_socket_suspend_read_fd_set = local_fd;
9970
9971 /* Adjust the suspension type so that the event flag set below will wakeup the thread
9972 selecting. */
9973 suspended_thread -> tx_thread_suspend_info = NX_BSD_RECEIVE_EVENT;
9974 }
9975
9976 /* Now determine if this thread was waiting for this socket. */
9977 if ((fd_sets & FDSET_WRITE) && (NX_BSD_FD_ISSET((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_write_fd_set)))
9978 {
9979
9980 /* Copy the local fd over so that the return shows the receive socket. */
9981 suspend_info -> nx_bsd_socket_suspend_write_fd_set = local_fd;
9982
9983 /* Adjust the suspension type so that the event flag set below will wakeup the thread
9984 selecting. */
9985 suspended_thread -> tx_thread_suspend_info = NX_BSD_RECEIVE_EVENT;
9986 }
9987
9988 /* Now determine if this thread was waiting for this socket. */
9989 if ((fd_sets & FDSET_EXCEPTION) && (NX_BSD_FD_ISSET((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_exception_fd_set)))
9990 {
9991
9992 /* Copy the local fd over so that the return shows the receive socket. */
9993 suspend_info -> nx_bsd_socket_suspend_exception_fd_set = local_fd;
9994
9995 /* Adjust the suspension type so that the event flag set below will wakeup the thread
9996 selecting. */
9997 suspended_thread -> tx_thread_suspend_info = NX_BSD_RECEIVE_EVENT;
9998 }
9999
10000 /* Clear FD that is not set. */
10001 if (suspended_thread -> tx_thread_suspend_info == NX_BSD_RECEIVE_EVENT)
10002 {
10003 if (!(fd_sets & FDSET_READ) && (NX_BSD_FD_ISSET((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_read_fd_set)))
10004 {
10005
10006 /* Clear read FD. */
10007 NX_BSD_FD_CLR((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_read_fd_set);
10008 }
10009
10010 if (!(fd_sets & FDSET_WRITE) && (NX_BSD_FD_ISSET((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_write_fd_set)))
10011 {
10012
10013 /* Clear write FD. */
10014 NX_BSD_FD_CLR((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_write_fd_set);
10015 }
10016
10017 if (!(fd_sets & FDSET_EXCEPTION) && (NX_BSD_FD_ISSET((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_exception_fd_set)))
10018 {
10019
10020 /* Clear exception FD. */
10021 NX_BSD_FD_CLR((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_exception_fd_set);
10022 }
10023 }
10024 }
10025
10026 /* Now move to the next event. */
10027 suspended_thread = suspended_thread -> tx_thread_suspended_next;
10028
10029 /* Restore interrupts. */
10030 TX_RESTORE
10031
10032 /* Disable interrupts again. */
10033 TX_DISABLE
10034
10035 /* Determine if something changes on the suspension list... this could have happened if there
10036 was a timeout or a wait abort on the thread. */
10037 if (original_suspended_count != nx_bsd_events.tx_event_flags_group_suspended_count)
10038 {
10039
10040 /* Something changed, so simply restart the search. */
10041
10042 /* Setup the head pointer and the count. */
10043 suspended_thread = nx_bsd_events.tx_event_flags_group_suspension_list;
10044 suspended_count = nx_bsd_events.tx_event_flags_group_suspended_count;
10045
10046 /* Save the original suspended count. */
10047 original_suspended_count = suspended_count;
10048 }
10049 }
10050
10051 /* Restore interrupts. */
10052 TX_RESTORE
10053
10054 /* Wakeup all threads that are attempting to perform a receive or that had their select satisfied. */
10055 tx_event_flags_set(&nx_bsd_events, NX_BSD_RECEIVE_EVENT, TX_OR);
10056
10057 return;
10058
10059 }
10060
10061 /**************************************************************************/
10062 /* */
10063 /* FUNCTION RELEASE */
10064 /* */
10065 /* nx_bsd_set_error_code PORTABLE C */
10066 /* 6.3.0 */
10067 /* AUTHOR */
10068 /* */
10069 /* Yuxin Zhou, Microsoft Corporation */
10070 /* */
10071 /* DESCRIPTION */
10072 /* */
10073 /* This is sets the BSD error code based on NetX Duo API return code */
10074 /* */
10075 /* INPUT */
10076 /* */
10077 /* bsd_socket_ptr Pointer to the BSD socket */
10078 /* status_code NetX Duo API return code */
10079 /* */
10080 /* OUTPUT */
10081 /* */
10082 /* None */
10083 /* */
10084 /* CALLS */
10085 /* */
10086 /* set_errno Sets the BSD errno */
10087 /* */
10088 /* CALLED BY */
10089 /* */
10090 /* connect */
10091 /* bind */
10092 /* */
10093 /* RELEASE HISTORY */
10094 /* */
10095 /* DATE NAME DESCRIPTION */
10096 /* */
10097 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10098 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10099 /* resulting in version 6.1 */
10100 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
10101 /* used new API/structs naming,*/
10102 /* resulting in version 6.3.0 */
10103 /* */
10104 /**************************************************************************/
nx_bsd_set_error_code(NX_BSD_SOCKET * bsd_socket_ptr,UINT status_code)10105 static VOID nx_bsd_set_error_code(NX_BSD_SOCKET *bsd_socket_ptr, UINT status_code)
10106 {
10107 switch(status_code)
10108 {
10109 case NX_NOT_CLOSED:
10110 /* TCP connection is not closed state. */
10111 nx_bsd_set_errno(EISCONN);
10112 break;
10113
10114 case NX_PTR_ERROR:
10115 case NX_INVALID_PORT:
10116 /* Invalid arguement. */
10117 nx_bsd_set_errno(EINVAL);
10118 break;
10119
10120 case NX_MAX_LISTEN:
10121 nx_bsd_set_errno(ENOBUFS);
10122 break;
10123
10124 case NX_PORT_UNAVAILABLE:
10125 case NX_NO_FREE_PORTS:
10126 nx_bsd_set_errno(EADDRNOTAVAIL);
10127 break;
10128
10129 case NX_ALREADY_BOUND:
10130 nx_bsd_set_errno(EINVAL);
10131 break;
10132
10133 case NX_WAIT_ABORTED:
10134 nx_bsd_set_errno(ETIMEDOUT);
10135 break;
10136
10137 case NX_NOT_CONNECTED:
10138 /* NX TCP connect service may return NX_NOT_CONNECTED if the timeout is WAIT_FOREVER. */
10139 nx_bsd_set_errno(ECONNREFUSED);
10140 break;
10141
10142 case NX_IN_PROGRESS:
10143 /* The NetX "in progress" status is the equivalent of the non blocking BSD socket waiting
10144 to connect. This can only happen if timeout is NX_NO_WAIT.*/
10145 if (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING)
10146 {
10147 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
10148 nx_bsd_set_errno(EINPROGRESS);
10149 }
10150 else
10151 nx_bsd_set_errno(EINTR);
10152 break;
10153
10154 case NX_INVALID_INTERFACE:
10155 case NX_IP_ADDRESS_ERROR:
10156 nx_bsd_set_errno(ENETUNREACH);
10157 break;
10158
10159 case NX_NOT_ENABLED:
10160 nx_bsd_set_errno(EPROTONOSUPPORT);
10161 break;
10162
10163 case NX_NOT_BOUND:
10164 case NX_DUPLICATE_LISTEN:
10165 default:
10166 nx_bsd_set_errno(EINVAL);
10167 break;
10168 }
10169
10170 return;
10171 }
10172
10173 /**************************************************************************/
10174 /* */
10175 /* FUNCTION RELEASE */
10176 /* */
10177 /* nx_bsd_udp_packet_received PORTABLE C */
10178 /* 6.1 */
10179 /* AUTHOR */
10180 /* */
10181 /* Yuxin Zhou, Microsoft Corporation */
10182 /* */
10183 /* DESCRIPTION */
10184 /* */
10185 /* This is executed as part of the UDP packet receive callback */
10186 /* function. */
10187 /* */
10188 /* This routine puts an incoming UDP packet into the appropriate */
10189 /* UDP BSD socket, taking into consideration that multiple BSD sockets */
10190 /* may be mapped to the same NetX Duo UDP socket. */
10191 /* */
10192 /* INPUT */
10193 /* */
10194 /* sockID The BSD socket descriptor */
10195 /* packet_ptr The incoming UDP packet */
10196 /* */
10197 /* OUTPUT */
10198 /* */
10199 /* None */
10200 /* */
10201 /* CALLS */
10202 /* */
10203 /* nx_packet_release Release a packet that is not */
10204 /* received by any sockets. */
10205 /* nx_bsd_select_wakeup Wake up any asychronous */
10206 /* receive call */
10207 /* */
10208 /* CALLED BY */
10209 /* */
10210 /* nx_bsd_udp_receive_notify */
10211 /* */
10212 /* RELEASE HISTORY */
10213 /* */
10214 /* DATE NAME DESCRIPTION */
10215 /* */
10216 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10217 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10218 /* resulting in version 6.1 */
10219 /* */
10220 /**************************************************************************/
nx_bsd_udp_packet_received(INT sockID,NX_PACKET * packet_ptr)10221 static VOID nx_bsd_udp_packet_received(INT sockID, NX_PACKET *packet_ptr)
10222 {
10223
10224 NX_BSD_SOCKET *bsd_ptr;
10225 ULONG addr_family;
10226 NX_BSD_SOCKET *exact_match = NX_NULL;
10227 NX_BSD_SOCKET *receiver_match = NX_NULL;
10228 NX_BSD_SOCKET *wildcard_match = NX_NULL;
10229 NX_INTERFACE *interface_ptr;
10230
10231
10232 bsd_ptr = &nx_bsd_socket_array[sockID];
10233
10234 #ifndef NX_DISABLE_IPV4
10235 if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
10236 {
10237 addr_family = AF_INET;
10238 interface_ptr = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
10239 }
10240 else
10241 #endif /* NX_DISABLE_IPV4 */
10242 #ifdef FEATURE_NX_IPV6
10243 if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
10244 {
10245 addr_family = AF_INET6;
10246 interface_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
10247 }
10248 else
10249 #endif /* FEATURE_NX_IPV6 */
10250 {
10251
10252 /* Invalid version. Release the packet and return. */
10253 nx_packet_release(packet_ptr);
10254
10255 return;
10256 }
10257
10258 /* Start the search for the BSD socket we received this packet on from current input socket ID. */
10259 bsd_ptr = &nx_bsd_socket_array[sockID];
10260
10261 do
10262 {
10263 /* Skip the sockets with different address family. */
10264 if(bsd_ptr -> nx_bsd_socket_family == addr_family)
10265 {
10266 /* bsd_ptr points to a related UDP socket. */
10267 if(bsd_ptr -> nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
10268 {
10269 wildcard_match = bsd_ptr;
10270 }
10271 else if(((ULONG)(interface_ptr) == bsd_ptr -> nx_bsd_socket_local_bind_interface) ||
10272 ((ULONG)(packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr) == bsd_ptr -> nx_bsd_socket_local_bind_interface))
10273 {
10274
10275 receiver_match = bsd_ptr;
10276 }
10277 else
10278 {
10279
10280 /* Does not match the local interface. Move to the next entry. */
10281 bsd_ptr = bsd_ptr -> nx_bsd_socket_next;
10282 continue;
10283 }
10284
10285 /* At this point this socket is either a wildcard match or a receiver match. */
10286
10287 /* If the socket is connected, we check for sender's address match. */
10288 if(bsd_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
10289 {
10290
10291 nxd_udp_source_extract(packet_ptr,
10292 &bsd_ptr -> nx_bsd_socket_source_ip_address,
10293 (UINT *)&bsd_ptr -> nx_bsd_socket_source_port);
10294
10295 #ifndef NX_DISABLE_IPV4
10296 if(bsd_ptr -> nx_bsd_socket_family == AF_INET)
10297 {
10298
10299 /* Now we can check for an exact match based on sender IP address and port. */
10300 if((bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v4 ==
10301 bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v4) &&
10302 (bsd_ptr -> nx_bsd_socket_source_port ==
10303 bsd_ptr -> nx_bsd_socket_peer_port))
10304 {
10305 exact_match = bsd_ptr;
10306 }
10307 }
10308 #endif /* NX_DISABLE_IPV4 */
10309 #ifdef FEATURE_NX_IPV6
10310 if(bsd_ptr -> nx_bsd_socket_family == AF_INET6)
10311 {
10312
10313 /* Now we can check for an exact match based on sender IP address and port. */
10314 if((bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[0] ==
10315 bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[0]) &&
10316 (bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[1] ==
10317 bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[1]) &&
10318 (bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[2] ==
10319 bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[2]) &&
10320 (bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[3] ==
10321 bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[3]) &&
10322 (bsd_ptr -> nx_bsd_socket_source_port ==
10323 bsd_ptr -> nx_bsd_socket_peer_port))
10324 {
10325
10326 exact_match = bsd_ptr;
10327 }
10328 }
10329 #endif
10330
10331 if(exact_match != NX_NULL)
10332 break;
10333
10334 if(receiver_match != NX_NULL)
10335 receiver_match = NX_NULL;
10336
10337 if(wildcard_match != NX_NULL)
10338 wildcard_match = NX_NULL;
10339 }
10340 }
10341
10342 /* Move to the next entry. */
10343 bsd_ptr = bsd_ptr -> nx_bsd_socket_next;
10344
10345 }while(bsd_ptr != &nx_bsd_socket_array[sockID]);
10346
10347 /* Let bsd_ptr point to the matched socket. */
10348 if(exact_match != NX_NULL)
10349 bsd_ptr = exact_match;
10350 else if(receiver_match != NX_NULL)
10351 bsd_ptr = receiver_match;
10352 else if(wildcard_match != NX_NULL)
10353 bsd_ptr = wildcard_match;
10354 else
10355 {
10356 /* This packet is not for any of the BSD sockets. Release the packet and we are done. */
10357 nx_packet_release(packet_ptr);
10358
10359 return;
10360 }
10361
10362 /* Move the packet to the socket internal receive queue. */
10363
10364 if(bsd_ptr -> nx_bsd_socket_received_byte_count_max &&
10365 (bsd_ptr -> nx_bsd_socket_received_byte_count >= bsd_ptr -> nx_bsd_socket_received_byte_count_max))
10366 {
10367
10368 /* Receive buffer is full. Release the packet and return. */
10369 nx_packet_release(packet_ptr);
10370
10371 return;
10372 }
10373
10374 /* Drop the packet if the receive queue exceeds max depth.*/
10375 if(bsd_ptr -> nx_bsd_socket_received_packet_count >=
10376 bsd_ptr -> nx_bsd_socket_received_packet_count_max)
10377 {
10378
10379 /* Receive buffer is full. Release the packet and return. */
10380 nx_packet_release(packet_ptr);
10381
10382 return;
10383 }
10384 if(bsd_ptr -> nx_bsd_socket_received_packet)
10385 {
10386 bsd_ptr -> nx_bsd_socket_received_packet_tail -> nx_packet_queue_next = packet_ptr;
10387 }
10388 else
10389 {
10390
10391 bsd_ptr -> nx_bsd_socket_received_packet = packet_ptr;
10392 bsd_ptr -> nx_bsd_socket_received_packet_offset = 0;
10393 }
10394
10395 bsd_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
10396 bsd_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
10397 bsd_ptr -> nx_bsd_socket_received_packet_count++;
10398
10399 nx_bsd_select_wakeup((UINT)(bsd_ptr -> nx_bsd_socket_id), FDSET_READ);
10400
10401 return;
10402 }
10403
10404 /**************************************************************************/
10405 /* */
10406 /* FUNCTION RELEASE */
10407 /* */
10408 /* nx_bsd_tcp_syn_received_notify PORTABLE C */
10409 /* 6.1 */
10410 /* AUTHOR */
10411 /* */
10412 /* Yuxin Zhou, Microsoft Corporation */
10413 /* */
10414 /* DESCRIPTION */
10415 /* */
10416 /* This function checks if the socket has a connection request. */
10417 /* */
10418 /* INPUT */
10419 /* */
10420 /* socket_ptr Socket receiving the packet */
10421 /* packet_ptr Pointer to the received packet */
10422 /* */
10423 /* OUTPUT */
10424 /* */
10425 /* 0 Not a valid match */
10426 /* 1 Valid match found */
10427 /* */
10428 /* CALLS */
10429 /* */
10430 /* None */
10431 /* */
10432 /* CALLED BY */
10433 /* */
10434 /* NetX Duo */
10435 /* */
10436 /* RELEASE HISTORY */
10437 /* */
10438 /* DATE NAME DESCRIPTION */
10439 /* */
10440 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10441 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10442 /* resulting in version 6.1 */
10443 /* */
10444 /**************************************************************************/
nx_bsd_tcp_syn_received_notify(NX_TCP_SOCKET * socket_ptr,NX_PACKET * packet_ptr)10445 static UINT nx_bsd_tcp_syn_received_notify(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr)
10446 {
10447
10448 UINT bsd_socket_index;
10449 INT i;
10450 INT sockID_find;
10451 ULONG addr_family;
10452 INT search_index;
10453 INT receiver_match = NX_BSD_MAX_SOCKETS;
10454 INT wildcard_match = NX_BSD_MAX_SOCKETS;
10455 NX_BSD_SOCKET *bsd_socket_ptr;
10456 NX_INTERFACE *interface_ptr;
10457
10458
10459 bsd_socket_index = (UINT)socket_ptr -> nx_tcp_socket_reserved_ptr;
10460
10461 if(bsd_socket_index >= NX_BSD_MAX_SOCKETS)
10462 {
10463
10464 /* Bad socket index... simply return! */
10465 return(NX_FALSE);
10466 }
10467
10468 nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
10469
10470 #ifndef NX_DISABLE_IPV4
10471 if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
10472 {
10473 addr_family = AF_INET;
10474 }
10475 else
10476 #endif /* NX_DISABLE_IPV4 */
10477 {
10478 addr_family = AF_INET6;
10479 }
10480
10481 /* Start the search at the position of the input socket. */
10482 search_index = (INT)bsd_socket_index;
10483
10484 /* Get the packet interface. */
10485 #ifdef FEATURE_NX_IPV6
10486 if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
10487 #endif /* FEATURE_NX_IPV6 */
10488 interface_ptr = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
10489 #ifdef FEATURE_NX_IPV6
10490 else if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
10491 interface_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
10492 else
10493 return (NX_FALSE);
10494 #endif /* FEATURE_NX_IPV6 */
10495
10496 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
10497 {
10498
10499 bsd_socket_ptr = &nx_bsd_socket_array[search_index];
10500
10501 /* Skip the unrelated sockets. */
10502 if((bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP) &&
10503 (bsd_socket_ptr -> nx_bsd_socket_family == addr_family) &&
10504 ((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED) == 0) &&
10505 (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) &&
10506 (bsd_socket_ptr -> nx_bsd_socket_local_port == socket_ptr -> nx_tcp_socket_port) &&
10507 (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
10508 {
10509
10510 if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
10511 {
10512
10513 wildcard_match = search_index;
10514 }
10515 else if(((ULONG)(interface_ptr) == bsd_socket_ptr -> nx_bsd_socket_local_bind_interface) ||
10516 ((ULONG)(packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr) == bsd_socket_ptr -> nx_bsd_socket_local_bind_interface))
10517 {
10518
10519 receiver_match = search_index;
10520
10521 /* Found a receiver match, which is a tighter match than the wildcard match.
10522 So we can get out of the loop. */
10523 break;
10524 }
10525 }
10526
10527 /* Move to the next entry. */
10528 search_index++;
10529
10530 if(search_index >= NX_BSD_MAX_SOCKETS)
10531 search_index = 0;
10532 }
10533
10534 if(receiver_match != NX_BSD_MAX_SOCKETS)
10535 sockID_find = receiver_match;
10536 else if(wildcard_match != NX_BSD_MAX_SOCKETS)
10537 sockID_find = wildcard_match;
10538 else
10539 {
10540
10541 /* No match found. Simply return .*/
10542 return(NX_FALSE);
10543 }
10544
10545 /* Found the listening master socket. Update the master socket ID of the input socket. */
10546 nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_union_id.nx_bsd_socket_master_socket_id = sockID_find;
10547
10548 return(NX_TRUE);
10549 }
10550
10551 /**************************************************************************/
10552 /* */
10553 /* FUNCTION RELEASE */
10554 /* */
10555 /* nx_bsd_tcp_create_listen_socket PORTABLE C */
10556 /* 6.3.0 */
10557 /* AUTHOR */
10558 /* */
10559 /* Yuxin Zhou, Microsoft Corporation */
10560 /* */
10561 /* DESCRIPTION */
10562 /* */
10563 /* This routine sets up the input socket as a listen socket. */
10564 /* */
10565 /* INPUT */
10566 /* */
10567 /* master_sockid Index to the master socket */
10568 /* backlog Size of the socket listen queue*/
10569 /* */
10570 /* OUTPUT */
10571 /* */
10572 /* NX_SOC_OK Successfully set up socket */
10573 /* NX_SOC_ERROR Error setting up the socket */
10574 /* */
10575 /* CALLS */
10576 /* */
10577 /* socket Allocate a BSD socket */
10578 /* nx_bsd_socket_set_inherited_settings Apply master socket options */
10579 /* nx_tcp_server_socket_listen Enable the socket to listen **/
10580 /* nx_tcp_server_socket_accept Wait for connection request */
10581 /* nx_tcp_server_socket_relisten Reset the socket to listen */
10582 /* */
10583 /* CALLED BY */
10584 /* */
10585 /* NetX Duo */
10586 /* */
10587 /* RELEASE HISTORY */
10588 /* */
10589 /* DATE NAME DESCRIPTION */
10590 /* */
10591 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10592 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10593 /* resulting in version 6.1 */
10594 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
10595 /* used new API/structs naming,*/
10596 /* resulting in version 6.3.0 */
10597 /* */
10598 /**************************************************************************/
nx_bsd_tcp_create_listen_socket(INT master_sockid,INT backlog)10599 static INT nx_bsd_tcp_create_listen_socket(INT master_sockid, INT backlog)
10600 {
10601
10602 INT i;
10603 UINT status;
10604 UINT local_port;
10605 NX_BSD_SOCKET *master_socket_ptr = &nx_bsd_socket_array[master_sockid];
10606 NX_BSD_SOCKET *bsd_secondary_socket;
10607 NX_BSD_SOCKET *bsd_socket_ptr;
10608 NX_TCP_SOCKET *sec_socket_ptr;
10609 INT secondary_sockID = NX_BSD_MAX_SOCKETS;
10610
10611
10612 /* This is called from BSD internal code so the BSD mutex is obtained. */
10613
10614 /* Search through the sockets to find a master socket that is listening on the same port. */
10615 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
10616 {
10617
10618 /* Skip the entry if it is not master socket */
10619 if((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) == 0)
10620 continue;
10621
10622 /* Skip the current master socket. */
10623 if(i == master_sockid)
10624 continue;
10625
10626 /* Skip the entry if it is not TCP */
10627 if(nx_bsd_socket_array[i].nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
10628 continue;
10629
10630 /* Skip the entry if the the secondary socket id field is not valid. */
10631 if(nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id == NX_BSD_MAX_SOCKETS)
10632 continue;
10633
10634 /* Check if another master socket is listening on the same port. */
10635 if((nx_bsd_socket_array[i].nx_bsd_socket_local_port == master_socket_ptr -> nx_bsd_socket_local_port) &&
10636 (nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id
10637 != (master_socket_ptr -> nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id)) &&
10638 (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN))
10639 {
10640
10641 /* This one is. Point to the same secondary socket. */
10642 (master_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id =
10643 nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id;
10644 master_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ENABLE_LISTEN;
10645 master_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET);
10646 master_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_client_type = NX_FALSE;
10647 master_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_SERVER_MASTER_SOCKET;
10648
10649 return(NX_SOC_OK);
10650 }
10651 }
10652
10653 /* Did not find an existing master socket for listening. */
10654
10655 /* Check for a valid backlog. */
10656 if(backlog)
10657 {
10658
10659 /* Check backlog argument is within limits. */
10660 if (backlog > NX_BSD_MAX_LISTEN_BACKLOG)
10661 {
10662
10663 /* Error, invalid backlog. */
10664 /* Set the socket error if extended socket options enabled. */
10665 nx_bsd_set_errno(ENOBUFS);
10666
10667 /* Return error code. */
10668 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
10669 return(NX_SOC_ERROR);
10670 }
10671 }
10672
10673 /* Now create a dedicated secondary socket to listen for next client connection. */
10674 secondary_sockID = nx_bsd_socket((INT)(master_socket_ptr -> nx_bsd_socket_family), SOCK_STREAM, IPPROTO_TCP);
10675
10676 /* Determine if there was an error. */
10677 if (secondary_sockID == NX_SOC_ERROR)
10678 {
10679
10680 /* Secondary socket create failed. Note: The socket thread error is set in socket(). */
10681 nx_bsd_set_errno(ENOMEM);
10682
10683 /* Return error code. */
10684 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
10685 return(NX_SOC_ERROR);
10686 }
10687
10688 /* Adjust the secondary socket ID. */
10689 secondary_sockID = secondary_sockID - NX_BSD_SOCKFD_START;
10690
10691 /* The master server socket will never connect to a client! For each successful
10692 client connection there will be a new secondary server socket and
10693 each such socket is associated with this master server socket. This is
10694 the difference between NetX and BSD sockets. The NetX listen() service is used
10695 with this secondary server socket. */
10696
10697 /* Set a pointer to the secondary socket. */
10698 bsd_secondary_socket = &nx_bsd_socket_array[secondary_sockID];
10699
10700 /* Apply the master socket options to the secondary socket. */
10701 nx_bsd_socket_set_inherited_settings((UINT)master_sockid, (UINT)secondary_sockID);
10702
10703 local_port = master_socket_ptr -> nx_bsd_socket_local_port;
10704
10705 /* Invalidate the secondary master socket ID. */
10706 (bsd_secondary_socket -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id = NX_BSD_MAX_SOCKETS;
10707
10708 /* Now call listen for the secondary server socket. */
10709 if(backlog)
10710 status = nx_tcp_server_socket_listen(nx_bsd_default_ip, local_port, bsd_secondary_socket -> nx_bsd_socket_tcp_socket, (UINT)backlog, NX_NULL);
10711 else
10712 {
10713
10714 /* Since a zero backlog is specified, this secondary socket needs to share with another master socket. */
10715 bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port = local_port;
10716
10717 /* Check if a listen request is queued up for this socket. */
10718 nx_bsd_tcp_pending_connection(local_port, bsd_secondary_socket -> nx_bsd_socket_tcp_socket);
10719
10720 status = nx_tcp_server_socket_relisten(nx_bsd_default_ip, local_port, bsd_secondary_socket -> nx_bsd_socket_tcp_socket);
10721 }
10722
10723 /* Check for an error. */
10724 if ((status != NX_SUCCESS) && (status != NX_CONNECTION_PENDING))
10725 {
10726
10727 /* Error, listen or relisten failed. */
10728
10729 /* Set the socket error depending on the NetX error status returned. */
10730 nx_bsd_set_error_code(master_socket_ptr, status);
10731
10732 /* Return error code. */
10733 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
10734 return(NX_SOC_ERROR);
10735 }
10736
10737 /* Now mark this as a master server socket listening to client connections. */
10738 master_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ENABLE_LISTEN;
10739 master_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET);
10740 master_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_client_type = NX_FALSE;
10741 master_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_SERVER_MASTER_SOCKET;
10742
10743 /* This is a master socket. So we use the nx_bsd_socket_master_socket_id field to
10744 record the secondary socket that is doing the real listen/accept work. */
10745 (master_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = secondary_sockID;
10746
10747 /* Mark the secondary server socket as assigned to this master server socket. */
10748 bsd_secondary_socket -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_ACCEPTING);
10749 bsd_secondary_socket -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET;
10750 bsd_secondary_socket -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ENABLE_LISTEN;
10751 bsd_secondary_socket -> nx_bsd_socket_local_port = (USHORT)local_port;
10752
10753 /* If the master server socket is marked as non-blocking, we need to
10754 start the NetX accept process here. */
10755
10756 sec_socket_ptr = bsd_secondary_socket -> nx_bsd_socket_tcp_socket;
10757
10758 /* Allow accept from remote. */
10759 nx_tcp_server_socket_accept(sec_socket_ptr, 0);
10760
10761 /* Set the master socket of other BSD TCP sockets that bind to the same port to the same secondary socket. */
10762 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
10763 {
10764
10765 bsd_socket_ptr = &nx_bsd_socket_array[i];
10766
10767 if((bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP) &&
10768 (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CLIENT)) &&
10769 (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) &&
10770 (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN) &&
10771 (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND) &&
10772 (bsd_socket_ptr -> nx_bsd_socket_local_port == local_port))
10773 {
10774
10775 (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = secondary_sockID;
10776 }
10777 }
10778
10779 /* Check the relisten/listen status. */
10780 if(status == NX_CONNECTION_PENDING)
10781 {
10782
10783 /* Set the connection pending flag. */
10784 bsd_secondary_socket -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
10785
10786 }
10787
10788 return(NX_SOC_OK);
10789 }
10790
10791 /**************************************************************************/
10792 /* */
10793 /* FUNCTION RELEASE */
10794 /* */
10795 /* nx_bsd_tcp_pending_connection PORTABLE C */
10796 /* 6.1 */
10797 /* AUTHOR */
10798 /* */
10799 /* Yuxin Zhou, Microsoft Corporation */
10800 /* */
10801 /* DESCRIPTION */
10802 /* */
10803 /* This routine checks if the BSD TCP socket has a listen request */
10804 /* queued up on in the specified port. */
10805 /* */
10806 /* INPUT */
10807 /* */
10808 /* local_port Listening port */
10809 /* socket_ptr Socket to check */
10810 /* */
10811 /* OUTPUT */
10812 /* */
10813 /* None */
10814 /* */
10815 /* CALLS */
10816 /* */
10817 /* nx_bsd_tcp_syn_received_notify Match connection request */
10818 /* (packet) to input socket */
10819 /* nx_packet_receive Release packet to packet pool */
10820 /* */
10821 /* CALLED BY */
10822 /* */
10823 /* NetX Duo */
10824 /* */
10825 /* RELEASE HISTORY */
10826 /* */
10827 /* DATE NAME DESCRIPTION */
10828 /* */
10829 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10830 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10831 /* resulting in version 6.1 */
10832 /* */
10833 /**************************************************************************/
nx_bsd_tcp_pending_connection(UINT local_port,NX_TCP_SOCKET * socket_ptr)10834 static VOID nx_bsd_tcp_pending_connection(UINT local_port, NX_TCP_SOCKET *socket_ptr)
10835 {
10836
10837 struct NX_TCP_LISTEN_STRUCT *listen_ptr;
10838 NX_PACKET *packet_ptr;
10839 NX_TCP_HEADER *tcp_header_ptr;
10840 UINT ret;
10841
10842
10843 listen_ptr = nx_bsd_default_ip -> nx_ip_tcp_active_listen_requests;
10844
10845 if(listen_ptr)
10846 {
10847
10848 do
10849 {
10850
10851 if((listen_ptr -> nx_tcp_listen_port == local_port) &&
10852 (listen_ptr -> nx_tcp_listen_queue_current))
10853 {
10854
10855 do
10856 {
10857
10858 packet_ptr = listen_ptr -> nx_tcp_listen_queue_head;
10859
10860 tcp_header_ptr = (NX_TCP_HEADER*)packet_ptr -> nx_packet_prepend_ptr;
10861
10862 if(tcp_header_ptr -> nx_tcp_header_word_3 & NX_TCP_SYN_BIT)
10863 {
10864
10865 ret = nx_bsd_tcp_syn_received_notify(socket_ptr, packet_ptr);
10866
10867 /* Yes. We are done. */
10868 if(ret == NX_TRUE)
10869 {
10870
10871 return;
10872 }
10873
10874 listen_ptr -> nx_tcp_listen_queue_head = packet_ptr -> nx_packet_queue_next;
10875
10876 if(packet_ptr == listen_ptr -> nx_tcp_listen_queue_tail)
10877 {
10878 listen_ptr -> nx_tcp_listen_queue_tail = NX_NULL;
10879 }
10880
10881 listen_ptr -> nx_tcp_listen_queue_current--;
10882
10883 nx_packet_release(packet_ptr);
10884
10885 }
10886 } while(listen_ptr -> nx_tcp_listen_queue_head);
10887 }
10888
10889 listen_ptr = listen_ptr -> nx_tcp_listen_next;
10890
10891 }while(listen_ptr != nx_bsd_default_ip -> nx_ip_tcp_active_listen_requests);
10892 }
10893 }
10894
10895 /**************************************************************************/
10896 /* */
10897 /* FUNCTION RELEASE */
10898 /* */
10899 /* nx_bsd_find_interface_by_source_addr PORTABLE C */
10900 /* 6.1 */
10901 /* AUTHOR */
10902 /* */
10903 /* Yuxin Zhou, Microsoft Corporation */
10904 /* */
10905 /* DESCRIPTION */
10906 /* */
10907 /* This function finds the interface index value of a given IPv4 or */
10908 /* IPv6 source address. */
10909 /* */
10910 /* INPUT */
10911 /* */
10912 /* addr_family Address Family */
10913 /* ip_addr Pointer to an array of IPv4 */
10914 /* or IPv6 address */
10915 /* */
10916 /* OUTPUT */
10917 /* */
10918 /* Index value */
10919 /* */
10920 /* CALLS */
10921 /* */
10922 /* None */
10923 /* */
10924 /* CALLED BY */
10925 /* */
10926 /* nx_bsd_send_internal */
10927 /* */
10928 /* RELEASE HISTORY */
10929 /* */
10930 /* DATE NAME DESCRIPTION */
10931 /* */
10932 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10933 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10934 /* resulting in version 6.1 */
10935 /* */
10936 /**************************************************************************/
nx_bsd_find_interface_by_source_addr(UINT addr_family,ULONG * ip_addr)10937 static INT nx_bsd_find_interface_by_source_addr(UINT addr_family, ULONG* ip_addr)
10938 {
10939 INT i;
10940 #ifndef NX_DISABLE_IPV4
10941 ULONG ipv4_addr;
10942 #endif /* NX_DISABLE_IPV4 */
10943 #ifdef FEATURE_NX_IPV6
10944 ULONG ipv6_addr[4];
10945 #endif
10946
10947 #ifndef NX_DISABLE_IPV4
10948 if(addr_family == AF_INET)
10949 {
10950 ipv4_addr = *ip_addr;
10951 NX_CHANGE_ULONG_ENDIAN(ipv4_addr);
10952
10953 for(i = 0; i < NX_MAX_IP_INTERFACES; i++)
10954 {
10955 if((nx_bsd_default_ip -> nx_ip_interface[i].nx_interface_valid) &&
10956 (nx_bsd_default_ip -> nx_ip_interface[i].nx_interface_ip_address == ipv4_addr))
10957 return i;
10958 }
10959 }
10960 #endif /* NX_DISABLE_IPV4 */
10961 #ifdef FEATURE_NX_IPV6
10962 if(addr_family == AF_INET6)
10963 {
10964 ipv6_addr[0] = *(ip_addr);
10965 ipv6_addr[1] = *(ip_addr + 1);
10966 ipv6_addr[2] = *(ip_addr + 2);
10967 ipv6_addr[3] = *(ip_addr + 3);
10968 NX_IPV6_ADDRESS_CHANGE_ENDIAN(ipv6_addr);
10969
10970 for(i = 0; i < NX_MAX_IPV6_ADDRESSES; i++)
10971 {
10972
10973 if((nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address_valid) &&
10974 (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address_attached -> nx_interface_valid) &&
10975 (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address[0] == ipv6_addr[0]) &&
10976 (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address[1] == ipv6_addr[1]) &&
10977 (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address[2] == ipv6_addr[2]) &&
10978 (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address[3] == ipv6_addr[3]))
10979 return i;
10980 }
10981 }
10982 #endif
10983
10984 return((INT)(NX_BSD_LOCAL_IF_INADDR_ANY));
10985
10986 }
10987
10988
10989 #ifndef NX_DISABLE_IPV4
10990 /**************************************************************************/
10991 /* */
10992 /* FUNCTION RELEASE */
10993 /* */
10994 /* _nxd_bsd_ipv4_packet_send PORTABLE C */
10995 /* 6.1 */
10996 /* AUTHOR */
10997 /* */
10998 /* Yuxin Zhou, Microsoft Corporation */
10999 /* */
11000 /* DESCRIPTION */
11001 /* */
11002 /* This function computes the IP header checksum and updates that into */
11003 /* the ip header ,which is assumed to be already prepended in the */
11004 /* input packet buffer, and forwards it to the driver directly. */
11005 /* */
11006 /* INPUT */
11007 /* */
11008 /* packet_ptr Pointer to packet to send */
11009 /* */
11010 /* OUTPUT */
11011 /* */
11012 /* None */
11013 /* */
11014 /* CALLS */
11015 /* */
11016 /* _nx_ip_checksum_compute Compute IP checksum */
11017 /* (_nx_arp_entry_allocate) ARP entry allocate service */
11018 /* (_nx_arp_packet_send) Send an ARP packet */
11019 /* _nx_ip_packet_deferred_receive Receive loopback packet */
11020 /* _nx_packet_copy Copy packet to input packet */
11021 /* _nx_packet_transmit_release Release transmit packet */
11022 /* (nx_ip_fragment_processing) Fragment processing */
11023 /* (ip_link_driver) User supplied link driver */
11024 /* */
11025 /* CALLED BY */
11026 /* */
11027 /* nx_bsd_send_internal */
11028 /* */
11029 /* RELEASE HISTORY */
11030 /* */
11031 /* DATE NAME DESCRIPTION */
11032 /* */
11033 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11034 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
11035 /* resulting in version 6.1 */
11036 /* */
11037 /**************************************************************************/
_nxd_bsd_ipv4_packet_send(NX_PACKET * packet_ptr)11038 static VOID _nxd_bsd_ipv4_packet_send(NX_PACKET *packet_ptr)
11039 {
11040
11041 TX_INTERRUPT_SAVE_AREA
11042 NX_IP_DRIVER driver_request;
11043 NX_IPV4_HEADER *ip_header_ptr;
11044 #ifndef NX_DISABLE_IP_TX_CHECKSUM
11045 ULONG checksum;
11046 ULONG val;
11047 #endif
11048 UINT index;
11049 NX_ARP *arp_ptr;
11050 NX_PACKET *last_packet;
11051 NX_PACKET *remove_packet;
11052 UINT queued_count;
11053 NX_PACKET *packet_copy;
11054 ULONG network_mask;
11055 ULONG network;
11056 NX_IP * ip_ptr;
11057 ULONG destination_ip;
11058
11059 ip_ptr = nx_bsd_default_ip;
11060 #ifndef NX_DISABLE_IP_INFO
11061
11062 /* Increment the total send requests counter. */
11063 ip_ptr -> nx_ip_total_packet_send_requests++;
11064 #endif
11065
11066
11067 /* Setup the IP header pointer. */
11068 ip_header_ptr = (NX_IPV4_HEADER *) packet_ptr -> nx_packet_prepend_ptr;
11069
11070 destination_ip = ip_header_ptr -> nx_ip_header_destination_ip;
11071
11072 /* Swap the destination address to host byte order.*/
11073 NX_CHANGE_ULONG_ENDIAN(destination_ip);
11074
11075 #ifndef NX_DISABLE_IP_TX_CHECKSUM
11076 checksum = _nx_ip_checksum_compute(packet_ptr, NX_IP_VERSION_V4,
11077 /* Length is the size of IP header, including options */
11078 (UINT)((*(UCHAR*)ip_header_ptr & 0xf) << 2),
11079 /* IPv4 header checksum does not use src/dest addresses */
11080 NULL, NULL);
11081
11082 val = (ULONG)(~checksum);
11083 val = val & NX_LOWER_16_MASK;
11084
11085 /* Convert to network byte order. */
11086 NX_CHANGE_ULONG_ENDIAN(val);
11087
11088 /* Now store the checksum in the IP header. */
11089 ip_header_ptr -> nx_ip_header_word_2 = ip_header_ptr -> nx_ip_header_word_2 | val;
11090
11091 #endif
11092
11093 /* Determine if physical mapping is needed by the link driver. */
11094 if (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_address_mapping_needed )
11095 {
11096
11097
11098 network_mask = packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_network_mask;
11099 network = packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_network;
11100
11101 /* Determine whether or not the destination address is out of this local network. */
11102 if (((destination_ip & network_mask) != network) ||
11103 ((destination_ip & ~network_mask) == ~network_mask) ||
11104 (destination_ip == packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_address))
11105 {
11106
11107 /* We have an out-of-network destination IP address, check for a variety
11108 of out-of-network destinations. */
11109
11110 /* Determine if an IP limited or directed broadcast is requested. */
11111 if ((destination_ip == NX_IP_LIMITED_BROADCAST) ||
11112 (((destination_ip & network_mask) == network) &&
11113 ((destination_ip & ~network_mask) == ~network_mask)))
11114 {
11115
11116 /* Build the driver request. */
11117 driver_request.nx_ip_driver_ptr = ip_ptr;
11118 driver_request.nx_ip_driver_command = NX_LINK_PACKET_BROADCAST;
11119 driver_request.nx_ip_driver_packet = packet_ptr;
11120 driver_request.nx_ip_driver_physical_address_msw = 0xFFFFUL;
11121 driver_request.nx_ip_driver_physical_address_lsw = 0xFFFFFFFFUL;
11122 driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11123
11124 #ifndef NX_DISABLE_FRAGMENTATION
11125 /* Determine if fragmentation is needed. */
11126 if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
11127 {
11128
11129 /* Fragmentation is needed, call the fragment routine if available. */
11130 if (ip_ptr -> nx_ip_fragment_processing)
11131 {
11132
11133 /* Call the IP fragment processing routine. */
11134 (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
11135 }
11136 else
11137 {
11138
11139 #ifndef NX_DISABLE_IP_INFO
11140
11141 /* Increment the IP send packets dropped count. */
11142 ip_ptr -> nx_ip_send_packets_dropped++;
11143 #endif
11144 /* Just release the packet. */
11145 _nx_packet_transmit_release(packet_ptr);
11146 }
11147
11148 /* In either case, this packet send is complete, just return. */
11149 return;
11150 }
11151 #endif
11152
11153 #ifndef NX_DISABLE_IP_INFO
11154
11155 /* Increment the IP packet sent count. */
11156 ip_ptr -> nx_ip_total_packets_sent++;
11157
11158 /* Increment the IP bytes sent count. */
11159 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11160 #endif
11161
11162 /* Broadcast packet. */
11163 (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
11164
11165 return;
11166 }
11167
11168 /* Determine if we have a loopback address. */
11169 else if ((((destination_ip >= NX_IP_LOOPBACK_FIRST) &&
11170 (destination_ip <= NX_IP_LOOPBACK_LAST))) ||
11171 (destination_ip == ip_ptr -> nx_ip_interface[0].nx_interface_ip_address))
11172 {
11173
11174 /* Yes, we have an internal loopback address. */
11175
11176 /* Copy the packet so it can be enqueued properly by the receive
11177 processing. */
11178 if (_nx_packet_copy(packet_ptr, &packet_copy, ip_ptr -> nx_ip_default_packet_pool, NX_NO_WAIT) == NX_SUCCESS)
11179 {
11180
11181 #ifndef NX_DISABLE_IP_INFO
11182
11183 /* Increment the IP packet sent count. */
11184 ip_ptr -> nx_ip_total_packets_sent++;
11185
11186 /* Increment the IP bytes sent count. */
11187 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11188 #endif
11189
11190 /* Send the packet to this IP's receive processing like it came in from the
11191 driver. */
11192 _nx_ip_packet_deferred_receive(ip_ptr, packet_copy);
11193 }
11194 #ifndef NX_DISABLE_IP_INFO
11195 else
11196 {
11197
11198 /* Increment the IP send packets dropped count. */
11199 ip_ptr -> nx_ip_send_packets_dropped++;
11200
11201 /* Increment the IP transmit resource error count. */
11202 ip_ptr -> nx_ip_transmit_resource_errors++;
11203 }
11204 #endif
11205
11206 /* Release the transmit packet. */
11207 _nx_packet_transmit_release(packet_ptr);
11208 return;
11209 }
11210
11211 /* Determine if we have a class D multicast address. */
11212 else if ((destination_ip & NX_IP_CLASS_D_MASK) == NX_IP_CLASS_D_TYPE)
11213 {
11214
11215 /* Yes, we have a class D multicast address. Derive the physical mapping from
11216 the class D address. */
11217 driver_request.nx_ip_driver_physical_address_msw = NX_IP_MULTICAST_UPPER;
11218 driver_request.nx_ip_driver_physical_address_lsw = NX_IP_MULTICAST_LOWER | (destination_ip & NX_IP_MULTICAST_MASK);
11219 driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11220
11221 /* Determine if the group address has been joined in this IP instance. */
11222 index = 0;
11223 while (index < NX_MAX_MULTICAST_GROUPS)
11224 {
11225
11226 /* Determine if the destination address matches the requested address. */
11227 if (ip_ptr -> nx_ipv4_multicast_entry[index].nx_ipv4_multicast_join_list == destination_ip)
11228 {
11229
11230 /* Yes, break the loop! */
11231 break;
11232 }
11233
11234 /* Increment the join list index. */
11235 index++;
11236 }
11237
11238 /* Determine if the group was joined by this IP instance. */
11239 if (index < NX_MAX_MULTICAST_GROUPS)
11240 {
11241
11242 /* Determine if the group has loopback enabled. */
11243 if (ip_ptr -> nx_ipv4_multicast_entry[index].nx_ipv4_multicast_loopback_enable)
11244 {
11245
11246 /* Yes, loopback is enabled! */
11247
11248 /* Copy the packet so we can send it via loopback. */
11249 if (_nx_packet_copy(packet_ptr, &packet_copy, ip_ptr -> nx_ip_default_packet_pool, NX_NO_WAIT) == NX_SUCCESS)
11250 {
11251
11252 #ifndef NX_DISABLE_IP_INFO
11253
11254 /* Increment the IP packet sent count. */
11255 ip_ptr -> nx_ip_total_packets_sent++;
11256
11257 /* Increment the IP bytes sent count. */
11258 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11259 #endif
11260
11261 /* Packet copy was successful. Send the packet to this IP's receive processing like it came in from the
11262 driver. */
11263 _nx_ip_packet_deferred_receive(ip_ptr, packet_copy);
11264 }
11265 #ifndef NX_DISABLE_IP_INFO
11266 else
11267 {
11268
11269 /* Increment the IP send packets dropped count. */
11270 ip_ptr -> nx_ip_send_packets_dropped++;
11271
11272 /* Increment the IP transmit resource error count. */
11273 ip_ptr -> nx_ip_transmit_resource_errors++;
11274 }
11275 #endif
11276 }
11277 }
11278
11279 /* Build the driver request. */
11280 driver_request.nx_ip_driver_ptr = ip_ptr;
11281 driver_request.nx_ip_driver_command = NX_LINK_PACKET_SEND;
11282 driver_request.nx_ip_driver_packet = packet_ptr;
11283 driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11284
11285 #ifndef NX_DISABLE_FRAGMENTATION
11286 /* Determine if fragmentation is needed. */
11287 if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
11288 {
11289
11290 /* Fragmentation is needed, call the fragment routine if available. */
11291 if (ip_ptr -> nx_ip_fragment_processing)
11292 {
11293
11294 /* Call the IP fragment processing routine. */
11295 (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
11296 }
11297 else
11298 {
11299
11300 #ifndef NX_DISABLE_IP_INFO
11301
11302 /* Increment the IP send packets dropped count. */
11303 ip_ptr -> nx_ip_send_packets_dropped++;
11304 #endif
11305 /* Just release the packet. */
11306 _nx_packet_transmit_release(packet_ptr);
11307 }
11308
11309 /* In either case, this packet send is complete, just return. */
11310 return;
11311 }
11312 #endif
11313
11314 #ifndef NX_DISABLE_IP_INFO
11315
11316 /* Increment the IP packet sent count. */
11317 ip_ptr -> nx_ip_total_packets_sent++;
11318
11319 /* Increment the IP bytes sent count. */
11320 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11321 #endif
11322
11323 /* Send the IP packet out on the network via the attached driver. */
11324 (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
11325
11326 /* Return to caller. */
11327 return;
11328 }
11329
11330 /* Use default gateway. */
11331 else
11332 {
11333
11334 /* We have an out-of-network destination IP address, check to see if a
11335 Gateway IP address has been specified. */
11336 if (ip_ptr -> nx_ip_gateway_address)
11337 {
11338
11339 /* Remap the destination IP address to the Gateway IP address. The ARP
11340 processing below will handle getting the physical address for the
11341 Gateway. */
11342 destination_ip = ip_ptr -> nx_ip_gateway_address;
11343 }
11344 else
11345 {
11346
11347 #ifndef NX_DISABLE_IP_INFO
11348
11349 /* Increment the number of no route errors. */
11350 ip_ptr -> nx_ip_transmit_no_route_errors++;
11351
11352 /* Increment the IP send packets dropped count. */
11353 ip_ptr -> nx_ip_send_packets_dropped++;
11354 #endif
11355 /* Just release the packet. */
11356 _nx_packet_transmit_release(packet_ptr);
11357
11358 /* In either case, this packet send is complete, just return. */
11359 return;
11360 }
11361 }
11362 }
11363
11364 /* Yes, look into the ARP Routing Table to derive the physical address. */
11365
11366 /* Calculate the hash index for the destination IP address. */
11367 index = (UINT) ((destination_ip + (destination_ip >> 8)) & NX_ARP_TABLE_MASK);
11368
11369 /* Disable interrupts temporarily. */
11370 TX_DISABLE
11371
11372 /* Determine if there is an entry for this IP address. */
11373 arp_ptr = ip_ptr -> nx_ip_arp_table[index];
11374
11375 /* Determine if this arp entry matches the destination IP address. */
11376 if ((arp_ptr) && (arp_ptr -> nx_arp_ip_address == destination_ip))
11377 {
11378
11379 /* Yes, we have an existing ARP mapping entry. */
11380
11381 /* Determine if there is a physical address. */
11382 if (arp_ptr -> nx_arp_physical_address_msw | arp_ptr -> nx_arp_physical_address_lsw)
11383 {
11384
11385 /* Yes, we have a physical mapping. Copy the physical address into the driver
11386 request structure. */
11387 driver_request.nx_ip_driver_physical_address_msw = arp_ptr -> nx_arp_physical_address_msw;
11388 driver_request.nx_ip_driver_physical_address_lsw = arp_ptr -> nx_arp_physical_address_lsw;
11389
11390 /* Restore interrupts. */
11391 TX_RESTORE
11392
11393 /* Build the driver request. */
11394 driver_request.nx_ip_driver_ptr = ip_ptr;
11395 driver_request.nx_ip_driver_command = NX_LINK_PACKET_SEND;
11396 driver_request.nx_ip_driver_packet = packet_ptr;
11397 driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11398
11399 #ifndef NX_DISABLE_FRAGMENTATION
11400 /* Determine if fragmentation is needed. */
11401 if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
11402 {
11403
11404 /* Fragmentation is needed, call the fragment routine if available. */
11405 if (ip_ptr -> nx_ip_fragment_processing)
11406 {
11407
11408 /* Call the IP fragment processing routine. */
11409 (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
11410 }
11411 else
11412 {
11413
11414 #ifndef NX_DISABLE_IP_INFO
11415
11416 /* Increment the IP send packets dropped count. */
11417 ip_ptr -> nx_ip_send_packets_dropped++;
11418 #endif
11419
11420 /* Just release the packet. */
11421 _nx_packet_transmit_release(packet_ptr);
11422 }
11423
11424 /* In either case, this packet send is complete, just return. */
11425 return;
11426 }
11427 #endif
11428
11429 #ifndef NX_DISABLE_IP_INFO
11430
11431 /* Increment the IP packet sent count. */
11432 ip_ptr -> nx_ip_total_packets_sent++;
11433
11434 /* Increment the IP bytes sent count. */
11435 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11436 #endif
11437
11438 /* Send the IP packet out on the network via the attached driver. */
11439 (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
11440
11441 /* Return to caller. */
11442 return;
11443 }
11444 else
11445 {
11446
11447 /* Ensure the current packet's queue next pointer to NULL. */
11448 packet_ptr -> nx_packet_queue_next = NX_NULL;
11449
11450 /* Determine if the queue is empty. */
11451 if (arp_ptr -> nx_arp_packets_waiting == NX_NULL)
11452 {
11453
11454 /* Yes, we have an empty ARP packet queue. Simply place the
11455 packet at the head of the list. */
11456 arp_ptr -> nx_arp_packets_waiting = packet_ptr;
11457
11458 /* Restore interrupts. */
11459 TX_RESTORE
11460 }
11461 else
11462 {
11463
11464 /* Determine how many packets are on the ARP entry's packet
11465 queue and remember the last packet in the queue. We know
11466 there is at least one on the queue and another that is
11467 going to be queued. */
11468 last_packet = arp_ptr -> nx_arp_packets_waiting;
11469 queued_count = 0;
11470 while (last_packet -> nx_packet_queue_next)
11471 {
11472
11473 /* Increment the queued count. */
11474 queued_count++;
11475
11476 /* Move to the next packet in the queue. */
11477 last_packet = last_packet -> nx_packet_queue_next;
11478 }
11479
11480 /* Place the packet at the end of the list. */
11481 last_packet -> nx_packet_queue_next = packet_ptr;
11482
11483 /* Default the remove packet pointer to NULL. */
11484 remove_packet = NX_NULL;
11485
11486 /* Determine if the packets queued has exceeded the queue
11487 depth. */
11488 if (queued_count >= NX_ARP_MAX_QUEUE_DEPTH)
11489 {
11490
11491 /* Save the packet pointer at the head of the list. */
11492 remove_packet = arp_ptr -> nx_arp_packets_waiting;
11493
11494 /* Remove the packet from the ARP queue. */
11495 arp_ptr -> nx_arp_packets_waiting = remove_packet -> nx_packet_queue_next;
11496
11497 /* Clear the remove packet queue next pointer. */
11498 remove_packet -> nx_packet_queue_next = NX_NULL;
11499
11500 #ifndef NX_DISABLE_IP_INFO
11501
11502 /* Increment the IP transmit resource error count. */
11503 ip_ptr -> nx_ip_transmit_resource_errors++;
11504
11505 /* Increment the IP send packets dropped count. */
11506 ip_ptr -> nx_ip_send_packets_dropped++;
11507 #endif
11508 }
11509
11510 /* Restore interrupts. */
11511 TX_RESTORE
11512
11513 /* Determine if there is a packet to remove. */
11514 if (remove_packet)
11515 {
11516
11517 /* Yes, the packet queue depth for this ARP entry was exceeded
11518 so release the packet that was removed from the queue. */
11519 _nx_packet_transmit_release(remove_packet);
11520 }
11521 }
11522
11523 /* Return to caller. */
11524 return;
11525 }
11526 }
11527 else
11528 {
11529
11530 /* At this point, we need to search the ARP list for a match for the
11531 destination IP. */
11532
11533 /* First, restore interrupts. */
11534 TX_RESTORE
11535
11536 /* Pickup the first ARP entry. */
11537 arp_ptr = ip_ptr -> nx_ip_arp_table[index];
11538
11539 /* Loop to look for an ARP match. */
11540 while (arp_ptr)
11541 {
11542
11543 /* Check for an IP match. */
11544 if (arp_ptr -> nx_arp_ip_address == destination_ip)
11545 {
11546
11547 /* Yes, we found a match. Get out of the loop! */
11548 break;
11549 }
11550
11551 /* Move to the next active ARP entry. */
11552 arp_ptr = arp_ptr -> nx_arp_active_next;
11553
11554 /* Determine if we are at the end of the ARP list. */
11555 if (arp_ptr == ip_ptr -> nx_ip_arp_table[index])
11556 {
11557 /* Clear the ARP pointer. */
11558 arp_ptr = NX_NULL;
11559 break;
11560 }
11561 }
11562
11563 /* Determine if we actually found a matching ARP entry. */
11564 if (arp_ptr)
11565 {
11566
11567 /* Yes, we found an ARP entry. Now check and see if
11568 it has an actual physical address. */
11569 if (arp_ptr -> nx_arp_physical_address_msw | arp_ptr -> nx_arp_physical_address_lsw)
11570 {
11571
11572 /* Yes, we have a physical mapping. Copy the physical address into the driver
11573 request structure. */
11574 driver_request.nx_ip_driver_physical_address_msw = arp_ptr -> nx_arp_physical_address_msw;
11575 driver_request.nx_ip_driver_physical_address_lsw = arp_ptr -> nx_arp_physical_address_lsw;
11576
11577 /* Disable interrupts. */
11578 TX_DISABLE
11579
11580 /* Move this ARP entry to the head of the list. */
11581 ip_ptr -> nx_ip_arp_table[index] = arp_ptr;
11582
11583 /* Restore interrupts. */
11584 TX_RESTORE
11585
11586 /* Build the driver request message. */
11587 driver_request.nx_ip_driver_ptr = ip_ptr;
11588 driver_request.nx_ip_driver_command = NX_LINK_PACKET_SEND;
11589 driver_request.nx_ip_driver_packet = packet_ptr;
11590 driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11591
11592 #ifndef NX_DISABLE_FRAGMENTATION
11593 /* Determine if fragmentation is needed. */
11594 if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
11595 {
11596
11597 /* Fragmentation is needed, call the fragment routine if available. */
11598 if (ip_ptr -> nx_ip_fragment_processing)
11599 {
11600
11601 /* Call the IP fragment processing routine. */
11602 (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
11603 }
11604 else
11605 {
11606
11607 #ifndef NX_DISABLE_IP_INFO
11608
11609 /* Increment the IP send packets dropped count. */
11610 ip_ptr -> nx_ip_send_packets_dropped++;
11611 #endif
11612
11613 /* Just release the packet. */
11614 _nx_packet_transmit_release(packet_ptr);
11615 }
11616
11617 /* In either case, this packet send is complete, just return. */
11618 return;
11619 }
11620 #endif
11621
11622 #ifndef NX_DISABLE_IP_INFO
11623
11624 /* Increment the IP packet sent count. */
11625 ip_ptr -> nx_ip_total_packets_sent++;
11626
11627 /* Increment the IP bytes sent count. */
11628 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11629 #endif
11630
11631 /* Send the IP packet out on the network via the attached driver. */
11632 (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
11633
11634 /* Return to caller. */
11635 return;
11636 }
11637 else
11638 {
11639
11640 /* We don't have physical mapping. */
11641
11642 /* Disable interrupts. */
11643 TX_DISABLE
11644
11645 /* Ensure the current packet's queue next pointer to NULL. */
11646 packet_ptr -> nx_packet_queue_next = NX_NULL;
11647
11648 /* Determine if the queue is empty. */
11649 if (arp_ptr -> nx_arp_packets_waiting == NX_NULL)
11650 {
11651
11652 /* Yes, we have an empty ARP packet queue. Simply place the
11653 packet at the head of the list. */
11654 arp_ptr -> nx_arp_packets_waiting = packet_ptr;
11655
11656 /* Restore interrupts. */
11657 TX_RESTORE
11658 }
11659 else
11660 {
11661
11662
11663 /* Determine how many packets are on the ARP entry's packet
11664 queue and remember the last packet in the queue. We know
11665 there is at least one on the queue and another that is
11666 going to be queued. */
11667 last_packet = arp_ptr -> nx_arp_packets_waiting;
11668 queued_count = 0;
11669 while (last_packet -> nx_packet_queue_next)
11670 {
11671
11672 /* Increment the queued count. */
11673 queued_count++;
11674
11675 /* Move to the next packet in the queue. */
11676 last_packet = last_packet -> nx_packet_queue_next;
11677 }
11678
11679 /* Place the packet at the end of the list. */
11680 last_packet -> nx_packet_queue_next = packet_ptr;
11681
11682 /* Default the remove packet pointer to NULL. */
11683 remove_packet = NX_NULL;
11684
11685 /* Determine if the packets queued has exceeded the queue
11686 depth. */
11687 if (queued_count >= NX_ARP_MAX_QUEUE_DEPTH)
11688 {
11689
11690 /* Save the packet pointer at the head of the list. */
11691 remove_packet = arp_ptr -> nx_arp_packets_waiting;
11692
11693 /* Remove the packet from the ARP queue. */
11694 arp_ptr -> nx_arp_packets_waiting = remove_packet -> nx_packet_queue_next;
11695
11696 /* Clear the remove packet queue next pointer. */
11697 remove_packet -> nx_packet_queue_next = NX_NULL;
11698
11699 #ifndef NX_DISABLE_IP_INFO
11700
11701 /* Increment the IP transmit resource error count. */
11702 ip_ptr -> nx_ip_transmit_resource_errors++;
11703
11704 /* Increment the IP send packets dropped count. */
11705 ip_ptr -> nx_ip_send_packets_dropped++;
11706 #endif
11707 }
11708
11709 /* Restore interrupts. */
11710 TX_RESTORE
11711
11712 /* Determine if there is a packet to remove. */
11713 if (remove_packet)
11714 {
11715
11716 /* Yes, the packet queue depth for this ARP entry was exceeded
11717 so release the packet that was removed from the queue. */
11718 _nx_packet_transmit_release(remove_packet);
11719 }
11720 }
11721
11722 /* Return to caller. */
11723 return;
11724 }
11725 }
11726 else
11727 {
11728
11729 /* No ARP entry was found. We need to allocate a new ARP entry, populate it, and
11730 initiate an ARP request to get the specific physical mapping. */
11731
11732 /* Allocate a new ARP entry. */
11733 if ((!ip_ptr -> nx_ip_arp_allocate) ||
11734 ((ip_ptr -> nx_ip_arp_allocate)(ip_ptr, &(ip_ptr -> nx_ip_arp_table[index]), NX_FALSE)))
11735 {
11736
11737 /* Error, release the protection and the packet. */
11738
11739 #ifndef NX_DISABLE_IP_INFO
11740
11741 /* Increment the IP transmit resource error count. */
11742 ip_ptr -> nx_ip_transmit_resource_errors++;
11743
11744 /* Increment the IP send packets dropped count. */
11745 ip_ptr -> nx_ip_send_packets_dropped++;
11746 #endif
11747
11748 /* Release the packet. */
11749 _nx_packet_transmit_release(packet_ptr);
11750
11751 /* Just return! */
11752 return;
11753 }
11754
11755 /* Otherwise, setup a pointer to the new ARP entry. */
11756 arp_ptr = (ip_ptr -> nx_ip_arp_table[index]) -> nx_arp_active_previous;
11757
11758 /* Setup the IP address and clear the physical mapping. */
11759 arp_ptr -> nx_arp_ip_address = destination_ip;
11760 arp_ptr -> nx_arp_physical_address_msw = 0;
11761 arp_ptr -> nx_arp_physical_address_lsw = 0;
11762 arp_ptr -> nx_arp_entry_next_update = NX_ARP_EXPIRATION_RATE;
11763 arp_ptr -> nx_arp_retries = 0;
11764 arp_ptr -> nx_arp_ip_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11765
11766 /* Ensure the queue next pointer is NULL for the packet before it
11767 is placed on the ARP waiting queue. */
11768 packet_ptr -> nx_packet_queue_next = NX_NULL;
11769
11770 /* Queue the packet for output. */
11771 arp_ptr -> nx_arp_packets_waiting = packet_ptr;
11772
11773 /* Call ARP send to send an ARP request. */
11774 (ip_ptr -> nx_ip_arp_packet_send)(ip_ptr, destination_ip, packet_ptr -> nx_packet_address.nx_packet_interface_ptr);
11775 return;
11776 }
11777 }
11778 }
11779 else
11780 {
11781
11782 /* This IP instance does not require any IP-to-physical mapping. */
11783
11784 /* Determine if we have a loopback address. */
11785 if ((((destination_ip >= NX_IP_LOOPBACK_FIRST) &&
11786 (destination_ip <= NX_IP_LOOPBACK_LAST))) ||
11787 (destination_ip == packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_address))
11788 {
11789
11790 /* Yes, we have an internal loopback address. */
11791
11792 /* Copy the packet so it can be enqueued properly by the receive
11793 processing. */
11794 if (_nx_packet_copy(packet_ptr, &packet_copy, ip_ptr -> nx_ip_default_packet_pool, NX_NO_WAIT) == NX_SUCCESS)
11795 {
11796
11797 #ifndef NX_DISABLE_IP_INFO
11798
11799 /* Increment the IP packet sent count. */
11800 ip_ptr -> nx_ip_total_packets_sent++;
11801
11802 /* Increment the IP bytes sent count. */
11803 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11804 #endif
11805
11806 /* Send the packet to this IP's receive processing like it came in from the
11807 driver. */
11808 _nx_ip_packet_deferred_receive(ip_ptr, packet_copy);
11809 }
11810 #ifndef NX_DISABLE_IP_INFO
11811 else
11812 {
11813
11814 /* Increment the IP transmit resource error count. */
11815 ip_ptr -> nx_ip_transmit_resource_errors++;
11816
11817 /* Increment the IP send packets dropped count. */
11818 ip_ptr -> nx_ip_send_packets_dropped++;
11819 }
11820 #endif
11821
11822 /* Release the transmit packet. */
11823 _nx_packet_transmit_release(packet_ptr);
11824 return;
11825 }
11826
11827 /* Build the driver request. */
11828 driver_request.nx_ip_driver_ptr = ip_ptr;
11829 driver_request.nx_ip_driver_command = NX_LINK_PACKET_SEND;
11830 driver_request.nx_ip_driver_packet = packet_ptr;
11831 driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11832
11833 #ifndef NX_DISABLE_FRAGMENTATION
11834 /* Determine if fragmentation is needed. */
11835 if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
11836 {
11837
11838 /* Fragmentation is needed, call the fragment routine if available. */
11839 if (ip_ptr -> nx_ip_fragment_processing)
11840 {
11841
11842 /* Call the IP fragment processing routine. */
11843 (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
11844 }
11845 else
11846 {
11847
11848 #ifndef NX_DISABLE_IP_INFO
11849
11850 /* Increment the IP send packets dropped count. */
11851 ip_ptr -> nx_ip_send_packets_dropped++;
11852 #endif
11853
11854 /* Just release the packet. */
11855 _nx_packet_transmit_release(packet_ptr);
11856 }
11857
11858 /* In either case, this packet send is complete, just return. */
11859 return;
11860 }
11861 #endif
11862
11863 #ifndef NX_DISABLE_IP_INFO
11864
11865 /* Increment the IP packet sent count. */
11866 ip_ptr -> nx_ip_total_packets_sent++;
11867
11868 /* Increment the IP bytes sent count. */
11869 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11870
11871 #endif
11872
11873 /* No mapping driver. Just send the packet out! */
11874 (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
11875 }
11876 }
11877 #endif /*NX_DISABLE_IPV4 */
11878
11879 #ifdef FEATURE_NX_IPV6
11880 /**************************************************************************/
11881 /* */
11882 /* FUNCTION RELEASE */
11883 /* */
11884 /* _nxd_bsd_ipv6_packet_send PORTABLE C */
11885 /* 6.1 */
11886 /* AUTHOR */
11887 /* */
11888 /* Yuxin Zhou, Microsoft Corporation */
11889 /* */
11890 /* DESCRIPTION */
11891 /* */
11892 /* This function forwards the input packet directly to the appropriate */
11893 /* link driver. The caller needs to fill in the correct */
11894 /* source and destination addresses into the packet source and */
11895 /* destination address. The caller also makes sure that the packet */
11896 /* interface address is valid (not in tentative state), and source */
11897 /* address is not unspecified e.g. NULL. */
11898 /* */
11899 /* INPUT */
11900 /* */
11901 /* packet_ptr Pointer to packet to send */
11902 /* src_addr Pointer to source address */
11903 /* dest_addr Pointer to dest address */
11904 /* */
11905 /* OUTPUT */
11906 /* */
11907 /* None */
11908 /* */
11909 /* CALLS */
11910 /* */
11911 /* _nx_packet_transmit_release Release transmit packet */
11912 /* _nx_nd_cache_add_entry Add new entry to ND Cache */
11913 /* IPv6_Address_Type Find IPv6 address type */
11914 /* _nx_packet_copy Packet copy */
11915 /* _nx_ip_packet_deferred_receive Places received packets in */
11916 /* deferred packet queue */
11917 /* _nx_icmpv6_send_ns Send neighbor solicitation */
11918 /* _nxd_ipv6_search_onlink Find onlink match */
11919 /* _nx_ipv6_fragment_processing Fragment processing */
11920 /* (ip_link_driver) User supplied link driver */
11921 /* */
11922 /* CALLED BY */
11923 /* */
11924 /* nx_bsd_send_internal */
11925 /* */
11926 /* RELEASE HISTORY */
11927 /* */
11928 /* DATE NAME DESCRIPTION */
11929 /* */
11930 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11931 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
11932 /* resulting in version 6.1 */
11933 /* */
11934 /**************************************************************************/
_nxd_bsd_ipv6_packet_send(NX_PACKET * packet_ptr,ULONG * src_addr,ULONG * dest_addr)11935 static VOID _nxd_bsd_ipv6_packet_send(NX_PACKET *packet_ptr, ULONG *src_addr, ULONG *dest_addr)
11936 {
11937
11938 UINT status;
11939 ULONG address_type;
11940 NX_IP_DRIVER driver_request;
11941 NX_PACKET *remove_packet;
11942 NX_PACKET *packet_copy;
11943 UINT same_address;
11944 NX_INTERFACE *if_ptr;
11945 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
11946 NX_IPV6_HEADER *ip_header_ptr;
11947 #endif
11948 NX_IPV6_DESTINATION_ENTRY *dest_entry_ptr;
11949 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
11950 UINT next_hop_path_mtu;
11951 NX_IPV6_DESTINATION_ENTRY *next_hop_dest_entry_ptr;
11952 #endif
11953 NX_IP *ip_ptr;
11954
11955 ip_ptr = nx_bsd_default_ip;
11956 #ifndef NX_DISABLE_IP_INFO
11957
11958 /* Increment the total send requests counter. */
11959 ip_ptr -> nx_ip_total_packet_send_requests++;
11960 #endif
11961
11962 if_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
11963
11964
11965 /* If the interface IP address is not valid (in DAD state), only ICMP is allowed */
11966 if(packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_state != NX_IPV6_ADDR_STATE_VALID)
11967 {
11968
11969 #ifndef NX_DISABLE_IP_INFO
11970
11971 /* Increment the IP invalid packet error. */
11972 ip_ptr -> nx_ip_invalid_transmit_packets++;
11973 #endif
11974
11975 /* Release the packet. */
11976 _nx_packet_transmit_release(packet_ptr);
11977
11978 /* Return... nothing more can be done! */
11979 return;
11980 }
11981
11982 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
11983 /* Build the IP header. */
11984 ip_header_ptr = (NX_IPV6_HEADER*)packet_ptr -> nx_packet_prepend_ptr;
11985 #endif
11986
11987 /* Check if the host is sending itself a packet. */
11988 same_address = (UINT)CHECK_IPV6_ADDRESSES_SAME(dest_addr, src_addr);
11989
11990 /* If it is, consider this a loopback address. */
11991 if (same_address == 1)
11992 {
11993
11994 address_type = IPV6_ADDRESS_LOOPBACK;
11995 }
11996 else
11997 {
11998
11999 /* Otherwise check if this packet sending to a known loopback address. */
12000 address_type = IPv6_Address_Type(dest_addr);
12001 }
12002
12003 /* Handle the internal loopback case. */
12004 if(address_type == IPV6_ADDRESS_LOOPBACK)
12005 {
12006
12007 if(_nx_packet_copy(packet_ptr, &packet_copy, ip_ptr -> nx_ip_default_packet_pool, NX_NO_WAIT) == NX_SUCCESS)
12008 {
12009 #ifndef NX_DISABLE_IP_INFO
12010
12011 /* Increment the IP packet sent count. */
12012 ip_ptr -> nx_ip_total_packets_sent++;
12013
12014 /* Increment the IP bytes sent count. */
12015 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV6_HEADER);
12016 #endif
12017
12018 /* Send the packet to this IP's receive processing like it came in from the driver. */
12019 _nx_ip_packet_deferred_receive(ip_ptr, packet_copy);
12020 }
12021 #ifndef NX_DISABLE_IP_INFO
12022 else
12023 {
12024 /* Increment the IP send packets dropped count. */
12025 ip_ptr -> nx_ip_send_packets_dropped++;
12026
12027 /* Increment the IP transmit resource error count. */
12028 ip_ptr -> nx_ip_transmit_resource_errors++;
12029 }
12030 #endif
12031 /* Release the transmit packet. */
12032 _nx_packet_transmit_release(packet_ptr);
12033 return;
12034
12035 }
12036
12037 /* Is this packet a multicast ? */
12038 if((dest_addr[0] & 0xFF000000) == 0xFF000000)
12039 {
12040
12041
12042 /* Set up the driver request. */
12043 driver_request.nx_ip_driver_ptr = ip_ptr;
12044 driver_request.nx_ip_driver_command = NX_LINK_PACKET_SEND;
12045 driver_request.nx_ip_driver_packet = packet_ptr;
12046 driver_request.nx_ip_driver_physical_address_msw = 0x00003333;
12047 driver_request.nx_ip_driver_physical_address_lsw = dest_addr[3];
12048 driver_request.nx_ip_driver_interface = if_ptr;
12049
12050 #ifndef NX_DISABLE_IP_INFO
12051
12052 /* Increment the IP packet sent count. */
12053 ip_ptr -> nx_ip_total_packets_sent++;
12054
12055 /* Increment the IP bytes sent count. */
12056 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV6_HEADER);
12057 #endif
12058
12059 /* Check if fragmentation is enabled. */
12060 #ifndef NX_DISABLE_FRAGMENTATION
12061
12062 /* It is; is path MTU enabled? */
12063 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
12064
12065 /* It is. We will check the path MTU for the packet destination to
12066 determine if we need to fragment the packet. */
12067
12068 /* Get a pointer to the packet IP header. */
12069 ip_header_ptr = (NX_IPV6_HEADER *)packet_ptr -> nx_packet_prepend_ptr;
12070
12071 /* Lookup the multicast destination in the destination table. */
12072 status = _nx_icmpv6_dest_table_find(ip_ptr, ip_header_ptr -> nx_ip_header_destination_ip, &dest_entry_ptr, 0, 0);
12073
12074 /* Did we find it in the table? */
12075 if ((status == NX_SUCCESS) && (dest_entry_ptr != NX_NULL))
12076 {
12077
12078 /* Yes; Check the destination path MTU if fragmentation is needed. */
12079 if ((dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu > 0) && (packet_ptr -> nx_packet_length >
12080 dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu))
12081 {
12082
12083 /* Yes we must fragment the payload. */
12084 _nx_ipv6_fragment_process(&driver_request, dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu);
12085
12086 /* This packet send is complete, just return. */
12087 return;
12088 }
12089
12090 /* Packet should drop through and be checked against the IP mtu. */
12091 }
12092
12093 #endif /* NX_ENABLE_IPV6_PATH_MTU_DISCOVERY */
12094
12095
12096 /* Does the packet payload exceed our IP instance MTU? */
12097 if (packet_ptr -> nx_packet_length > if_ptr -> nx_interface_ip_mtu_size)
12098 {
12099 /* Yes; ok to fragment the packet payload. */
12100 _nx_ipv6_fragment_process(&driver_request, if_ptr -> nx_interface_ip_mtu_size);
12101
12102 /* This packet send is complete, just return. */
12103 return;
12104 }
12105
12106 /* Packet will go out unfragmented. */
12107
12108 #endif /* NX_DISABLE_FRAGMENTATION */
12109
12110
12111 /* Send the IP packet out on the network via the attached driver. */
12112 (if_ptr -> nx_interface_link_driver_entry) (&driver_request);
12113
12114 /* Return to caller. */
12115 return;
12116 }
12117
12118 /* Determine if physical mapping is needed by this link driver. */
12119 if( if_ptr && if_ptr -> nx_interface_address_mapping_needed )
12120 {
12121
12122 /* Obtain MAC address */
12123 ND_CACHE_ENTRY *NDCacheEntry = NX_NULL;
12124 ULONG next_hop_address[4];
12125
12126 SET_UNSPECIFIED_ADDRESS(next_hop_address);
12127
12128 /* Lookup the packet destination in the destination table. */
12129 status = _nx_icmpv6_dest_table_find(ip_ptr, dest_addr, &dest_entry_ptr, 0, 0);
12130
12131 /* Was a matching entry found? */
12132 if(status != NX_SUCCESS)
12133 {
12134
12135 /* No; If the packet is either onlink or there is no default router,
12136 just copy the packet destination address to the 'next hop' address. */
12137
12138 if(_nxd_ipv6_search_onlink(ip_ptr, dest_addr))
12139 {
12140 COPY_IPV6_ADDRESS(dest_addr, next_hop_address);
12141
12142 /* Add the next_hop in destination table. */
12143 status = _nx_icmpv6_dest_table_add(ip_ptr, dest_addr, &dest_entry_ptr,
12144 next_hop_address, if_ptr -> nx_interface_ip_mtu_size,
12145 NX_WAIT_FOREVER, packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr);
12146
12147 /* Get the NDCacheEntry. */
12148 if(status == NX_SUCCESS)
12149 NDCacheEntry = dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry;
12150 }
12151
12152 /* Check whether or not we have a default router. */
12153 else if(_nxd_ipv6_router_lookup(ip_ptr, if_ptr, next_hop_address, (VOID**)&NDCacheEntry) == NX_SUCCESS)
12154 {
12155 /* Add the next_hop in destination table. */
12156 status = _nx_icmpv6_dest_table_add(ip_ptr, dest_addr, &dest_entry_ptr,
12157 next_hop_address, if_ptr -> nx_interface_ip_mtu_size,
12158 NX_WAIT_FOREVER, packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr);
12159
12160 /* If the default router did not has a reachable ND_CACHE_ENTRY. Get the NDCacheEntry. */
12161 if(!NDCacheEntry)
12162 NDCacheEntry = dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry;
12163 }
12164
12165 /* Can not find next_hop or the destination table add failed. */
12166 if(status || ((next_hop_address[0] == 0) && (next_hop_address[1] == 0) && (next_hop_address[2] == 0) && (next_hop_address[3] == 0)))
12167 {
12168
12169 /* Release the packet. */
12170 _nx_packet_release(packet_ptr);
12171
12172 /* Can't send it. */
12173 return;
12174 }
12175
12176 }
12177
12178 /* Find a valid destination cache, set the nd cache and next hop address. */
12179 else
12180 {
12181
12182 /* Check the NDCacheEntry is valid. */
12183 if(dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry -> nx_nd_cache_nd_status == ND_CACHE_STATE_INVALID)
12184 {
12185 if(_nx_nd_cache_add_entry(ip_ptr, dest_addr, packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr, &dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry))
12186 {
12187 /* Release the packet. */
12188 _nx_packet_release(packet_ptr);
12189
12190 /* Can't send it. */
12191 return;
12192 }
12193
12194 }
12195
12196 /* Get the destination and next hop address. */
12197 NDCacheEntry = dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry;
12198 COPY_IPV6_ADDRESS(dest_entry_ptr -> nx_ipv6_destination_entry_next_hop, next_hop_address);
12199 }
12200
12201 /* According RFC2461 ch 7.3.3, as long as the entry is valid and not in INCOMPLETE state,
12202 the IP layer should use the cached link layer address. */
12203 if((NDCacheEntry -> nx_nd_cache_nd_status >= ND_CACHE_STATE_REACHABLE) &&
12204 (NDCacheEntry -> nx_nd_cache_nd_status <= ND_CACHE_STATE_PROBE))
12205 {
12206
12207 UCHAR *mac_addr;
12208
12209 mac_addr = NDCacheEntry -> nx_nd_cache_mac_addr;
12210
12211 /* Assume we find the mac */
12212 driver_request.nx_ip_driver_ptr = ip_ptr;
12213 driver_request.nx_ip_driver_command = NX_LINK_PACKET_SEND;
12214 driver_request.nx_ip_driver_packet = packet_ptr;
12215 driver_request.nx_ip_driver_physical_address_msw = (ULONG)((mac_addr[0] << 8) | mac_addr[1]);
12216 driver_request.nx_ip_driver_physical_address_lsw =
12217 (ULONG)((mac_addr[2] << 24) | (mac_addr[3] << 16) | (mac_addr[4] << 8) | mac_addr[5]);
12218 driver_request.nx_ip_driver_interface = if_ptr;
12219
12220 #ifndef NX_DISABLE_FRAGMENTATION
12221
12222 /* If the packet size is bigger than MTU, NetX Duo is enabled to fragment
12223 the packet payload. */
12224
12225 /* Check if path MTU Discovery is enabled first. */
12226
12227 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
12228
12229 /* It is. To know if we need to fragment this packet we need the path MTU for the packet
12230 destination. */
12231
12232 /* If this destination has a non null next hop, we need to ascertain the next hop MTU. */
12233
12234 /* Get the path MTU for the actual destination. */
12235 next_hop_path_mtu = dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu;
12236
12237
12238 /* Find the next hop in the destination table. */
12239 status = _nx_icmpv6_dest_table_find(ip_ptr, next_hop_address, &next_hop_dest_entry_ptr, 0, 0);
12240
12241 if (status == NX_SUCCESS)
12242 {
12243
12244 /* Now compare the destination path MTU with the next hop path MTU*/
12245 if ((next_hop_dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu > 0) &&
12246 (next_hop_path_mtu > next_hop_dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu))
12247 {
12248
12249 /* Update the path mtu to reflect the next hop route. */
12250 next_hop_path_mtu = next_hop_dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu;
12251 }
12252 }
12253
12254 /* Yes; Check the destination path MTU if fragmentation is needed. */
12255 if ((next_hop_path_mtu > 0) &&
12256 (packet_ptr -> nx_packet_length > next_hop_path_mtu))
12257 {
12258
12259 /* Yes we must fragment the payload. */
12260 _nx_ipv6_fragment_process(&driver_request, next_hop_path_mtu);
12261
12262 /* This packet send is complete, just return. */
12263 return;
12264 }
12265 #endif /* NX_ENABLE_IPV6_PATH_MTU_DISCOVERY */
12266
12267 /* Send packet unfragmented. */
12268
12269 /* If we didn't find anything in the destination table, let the packet drop through. NetX Duo
12270 will check our IP instance MTU if fragmentation is needed before sending. */
12271
12272
12273 /* Does the packet payload exceed our IP instance MTU? */
12274 if (packet_ptr -> nx_packet_length > if_ptr -> nx_interface_ip_mtu_size)
12275 {
12276 /* Yes; ok to fragment the packet payload. */
12277 _nx_ipv6_fragment_process(&driver_request, if_ptr -> nx_interface_ip_mtu_size);
12278
12279 /* This packet send is complete, just return. */
12280 return;
12281 }
12282
12283 /* The packet requires no fragmentation. Proceed with sending the packet. */
12284
12285 #endif /* NX_DISABLE_FRAGMENTATION */
12286
12287
12288 #ifndef NX_DISABLE_IP_INFO
12289
12290 /* Increment the IP packet sent count. */
12291 ip_ptr -> nx_ip_total_packets_sent++;
12292
12293 /* Increment the IP bytes sent count. */
12294 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV6_HEADER);
12295 #endif
12296
12297 /* Send the IP packet out on the network via the attached driver. */
12298 (if_ptr -> nx_interface_link_driver_entry) (&driver_request);
12299
12300 /* If the entry is in STALE state, move it to DELAY state. */
12301 if(NDCacheEntry -> nx_nd_cache_nd_status == ND_CACHE_STATE_STALE)
12302 {
12303 NDCacheEntry -> nx_nd_cache_nd_status = ND_CACHE_STATE_DELAY;
12304
12305 /* Start the Delay first probe timer */
12306 NDCacheEntry -> nx_nd_cache_timer_tick = NX_DELAY_FIRST_PROBE_TIME;
12307
12308 }
12309
12310 /* Return to caller. */
12311 return;
12312 }
12313
12314 /* No MAC address was found in our cache table. Start the Neighbor Discovery (ND)
12315 process to get it. */
12316
12317 /* Ensure the current packet's queue next pointer to NULL */
12318 packet_ptr -> nx_packet_queue_next = NX_NULL;
12319
12320 /* Determine if the queue is empty. */
12321 if(NDCacheEntry -> nx_nd_cache_packet_waiting_head == NX_NULL)
12322 {
12323 /* ICMPv6 is enabled */
12324 if(ip_ptr -> nx_ip_icmpv6_packet_process)
12325 {
12326
12327 /* Queue up this packet */
12328 NDCacheEntry -> nx_nd_cache_packet_waiting_head = packet_ptr;
12329 NDCacheEntry -> nx_nd_cache_packet_waiting_tail = packet_ptr;
12330 NDCacheEntry -> nx_nd_cache_packet_waiting_queue_length = 1;
12331
12332 /* Set the outgoing address and interface to the cache entry. */
12333 NDCacheEntry -> nx_nd_cache_outgoing_address = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr;
12334 NDCacheEntry -> nx_nd_cache_interface_ptr = if_ptr;
12335
12336 /* Is this a new entry? */
12337 if(NDCacheEntry -> nx_nd_cache_nd_status == ND_CACHE_STATE_CREATED)
12338 {
12339
12340 /* Start Neighbor discovery process by advancing to the incomplete state. */
12341 NDCacheEntry -> nx_nd_cache_nd_status = ND_CACHE_STATE_INCOMPLETE;
12342 }
12343
12344 _nx_icmpv6_send_ns(ip_ptr, next_hop_address,
12345 1, packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr, 0, NX_NULL);
12346
12347 NDCacheEntry -> nx_nd_cache_num_solicit = NX_MAX_MULTICAST_SOLICIT - 1;
12348 NDCacheEntry -> nx_nd_cache_timer_tick = ip_ptr -> nx_ipv6_retrans_timer_ticks;
12349
12350 }
12351 else
12352 {
12353
12354 _nx_packet_transmit_release(packet_ptr);
12355 #ifndef NX_DISABLE_IP_INFO
12356
12357 /* Increment the IP transmit resource error count. */
12358 ip_ptr -> nx_ip_transmit_resource_errors++;
12359
12360 /* Increment the IP send packets dropped count. */
12361 ip_ptr -> nx_ip_send_packets_dropped++;
12362 #endif
12363 }
12364 return;
12365 }
12366
12367 /* The ND process already started. Simply queue up this packet */
12368 NDCacheEntry -> nx_nd_cache_packet_waiting_tail -> nx_packet_queue_next = packet_ptr;
12369 NDCacheEntry -> nx_nd_cache_packet_waiting_tail = packet_ptr;
12370 NDCacheEntry -> nx_nd_cache_packet_waiting_queue_length++;
12371
12372 /* Check if the number of packets enqueued exceeds the allowed number. */
12373 if(NDCacheEntry -> nx_nd_cache_packet_waiting_queue_length > NX_ND_MAX_QUEUE_DEPTH)
12374 {
12375
12376 /* Yes, so delete the first packet. */
12377 remove_packet = NDCacheEntry -> nx_nd_cache_packet_waiting_head;
12378
12379 NDCacheEntry -> nx_nd_cache_packet_waiting_head = remove_packet -> nx_packet_queue_next;
12380
12381 /* Update the queued packet count for this cache entry. */
12382 NDCacheEntry -> nx_nd_cache_packet_waiting_queue_length--;
12383
12384 _nx_packet_transmit_release(remove_packet);
12385 #ifndef NX_DISABLE_IP_INFO
12386 /* Increment the IP transmit resource error count. */
12387 ip_ptr -> nx_ip_transmit_resource_errors++;
12388
12389 /* Increment the IP send packets dropped count. */
12390 ip_ptr -> nx_ip_send_packets_dropped++;
12391 #endif
12392 }
12393
12394 return;
12395 }
12396
12397 /* For now do nothing. Just release the packet */
12398 _nx_packet_release(packet_ptr);
12399 }
12400
12401 #endif /* FEATURE_NX_IPV6 */
12402
12403 #if defined(FEATURE_NX_IPV6) && defined(NX_ENABLE_IP_RAW_PACKET_FILTER)
12404 /**************************************************************************/
12405 /* */
12406 /* FUNCTION RELEASE */
12407 /* */
12408 /* _nxd_bsd_swap_ipv6_extension_headers PORTABLE C */
12409 /* 6.1 */
12410 /* AUTHOR */
12411 /* */
12412 /* Yuxin Zhou, Microsoft Corporation */
12413 /* */
12414 /* DESCRIPTION */
12415 /* */
12416 /* This function performs endian swap operations on the IPv6 */
12417 /* extension headers. */
12418 /* */
12419 /* INPUT */
12420 /* */
12421 /* packet_ptr Pointer to packet */
12422 /* header_type Type of the first extension */
12423 /* header */
12424 /* */
12425 /* OUTPUT */
12426 /* */
12427 /* None */
12428 /* */
12429 /* CALLS */
12430 /* */
12431 /* NX_CHANGE_USHORT_ENDIAN Swap endian-ness on 16-bit */
12432 /* integer. */
12433 /* */
12434 /* CALLED BY */
12435 /* */
12436 /* NetX Duo BSD Layer Source Code */
12437 /* */
12438 /* RELEASE HISTORY */
12439 /* */
12440 /* DATE NAME DESCRIPTION */
12441 /* */
12442 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12443 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12444 /* resulting in version 6.1 */
12445 /* */
12446 /**************************************************************************/
_nxd_bsd_swap_ipv6_extension_headers(NX_PACKET * packet_ptr,UCHAR header_type)12447 static VOID _nxd_bsd_swap_ipv6_extension_headers(NX_PACKET *packet_ptr, UCHAR header_type)
12448 {
12449 UCHAR *scan_ptr;
12450 ULONG remaining_bytes;
12451 ULONG header_length = 40;
12452 NX_IPV6_HEADER_OPTION *option;
12453
12454
12455 remaining_bytes = (ULONG)packet_ptr -> nx_packet_prepend_ptr - (ULONG)packet_ptr -> nx_packet_ip_header;
12456
12457 scan_ptr = packet_ptr -> nx_packet_ip_header;
12458
12459 remaining_bytes -= header_length;
12460 scan_ptr += header_length;
12461
12462 while(remaining_bytes)
12463 {
12464 option = (NX_IPV6_HEADER_OPTION*)scan_ptr;
12465 switch(header_type)
12466 {
12467 case NX_PROTOCOL_NEXT_HEADER_HOP_BY_HOP:
12468
12469 break;
12470
12471 case NX_PROTOCOL_NEXT_HEADER_DESTINATION:
12472
12473 break;
12474
12475 case NX_PROTOCOL_NEXT_HEADER_ROUTING:
12476 break;
12477
12478
12479 case NX_PROTOCOL_NEXT_HEADER_FRAGMENT:
12480 NX_CHANGE_USHORT_ENDIAN(((NX_IPV6_HEADER_FRAGMENT_OPTION *)scan_ptr) -> nx_ipv6_header_fragment_option_offset_flag);
12481 break;
12482
12483 default:
12484
12485 break;
12486 }
12487
12488 header_type = option -> nx_ipv6_header_option_next_header;
12489
12490 if(header_type == NX_PROTOCOL_NEXT_HEADER_AUTHENTICATION)
12491 header_length = (ULONG)((option -> nx_ipv6_header_option_ext_length << 2) + 2);
12492 else
12493 header_length = (ULONG)((option -> nx_ipv6_header_option_ext_length + 1) << 3);
12494
12495
12496 remaining_bytes -= header_length;
12497 scan_ptr += header_length;
12498 }
12499 }
12500 #endif /* defined(FEATURE_NX_IPV6) && defined(NX_ENABLE_IP_RAW_PACKET_FILTER) */
12501 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
12502
12503
12504 /**************************************************************************/
12505 /* */
12506 /* FUNCTION RELEASE */
12507 /* */
12508 /* nx_bsd_pppoe_internal_sendto PORTABLE C */
12509 /* 6.3.0 */
12510 /* AUTHOR */
12511 /* */
12512 /* Yuxin Zhou, Microsoft Corporation */
12513 /* */
12514 /* DESCRIPTION */
12515 /* */
12516 /* This function sends raw PPPOE packet to driver directly. */
12517 /* */
12518 /* INPUT */
12519 /* */
12520 /* bsd_socket_ptr Pointer to bsd socket */
12521 /* msg Message to send */
12522 /* msgLength Length of message */
12523 /* flags Flags */
12524 /* destAddr Pointer to destination address*/
12525 /* destAddrLen Length of destination address */
12526 /* */
12527 /* OUTPUT */
12528 /* */
12529 /* msgLength On success */
12530 /* NX_SOC_ERROR (-1) On failure */
12531 /* */
12532 /* CALLS */
12533 /* */
12534 /* nx_packet_allocate Allocate a packet */
12535 /* nx_packet_data_append Append data to the packet */
12536 /* nx_packet_release Release the packet on error */
12537 /* tx_mutex_get Obtain exclusive access to */
12538 /* tx_mutex_put Release exclusive access */
12539 /* */
12540 /* CALLED BY */
12541 /* */
12542 /* Application Code */
12543 /* */
12544 /* RELEASE HISTORY */
12545 /* */
12546 /* DATE NAME DESCRIPTION */
12547 /* */
12548 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12549 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12550 /* resulting in version 6.1 */
12551 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
12552 /* used new API/structs naming,*/
12553 /* resulting in version 6.3.0 */
12554 /* */
12555 /**************************************************************************/
nx_bsd_pppoe_internal_sendto(NX_BSD_SOCKET * bsd_socket_ptr,CHAR * msg,INT msgLength,INT flags,struct nx_bsd_sockaddr * destAddr,INT destAddrLen)12556 static INT nx_bsd_pppoe_internal_sendto(NX_BSD_SOCKET *bsd_socket_ptr, CHAR *msg, INT msgLength, INT flags, struct nx_bsd_sockaddr* destAddr, INT destAddrLen)
12557 {
12558 UINT if_index;
12559 struct nx_bsd_sockaddr_ll
12560 *destAddr_ll;
12561 #if 0
12562 ULONG src_mac_msw;
12563 ULONG src_mac_lsw;
12564 #endif
12565 NX_IP_DRIVER driver_request;
12566 UINT status;
12567 NX_PACKET *packet_ptr = NX_NULL;
12568
12569 NX_PARAMETER_NOT_USED(bsd_socket_ptr);
12570 NX_PARAMETER_NOT_USED(flags);
12571
12572 /* Validate the parameters. */
12573 if(destAddr == NX_NULL)
12574 {
12575 /* Set the socket error if extended socket options enabled. */
12576 nx_bsd_set_errno(EINVAL);
12577
12578 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12579 return(NX_SOC_ERROR);
12580 }
12581
12582 if(destAddr -> sa_family != AF_PACKET)
12583 {
12584 /* Set the socket error if extended socket options enabled. */
12585 nx_bsd_set_errno(EINVAL);
12586
12587 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12588 return(NX_SOC_ERROR);
12589 }
12590
12591 if(destAddrLen != sizeof(struct nx_bsd_sockaddr_ll))
12592 {
12593 /* Set the socket error if extended socket options enabled. */
12594 nx_bsd_set_errno(EINVAL);
12595
12596 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12597 return(NX_SOC_ERROR);
12598 }
12599
12600 destAddr_ll = (struct nx_bsd_sockaddr_ll*)destAddr;
12601
12602 if((destAddr_ll -> sll_protocol != ETHERTYPE_PPPOE_SESS) && (destAddr_ll -> sll_protocol != ETHERTYPE_PPPOE_DISC))
12603 {
12604 /* Set the socket error if extended socket options enabled. */
12605 nx_bsd_set_errno(EINVAL);
12606
12607 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12608 return(NX_SOC_ERROR);
12609 }
12610
12611 /* Validate the interface ID */
12612 if_index = (UINT)(destAddr_ll -> sll_ifindex);
12613 if(if_index >= NX_MAX_IP_INTERFACES)
12614 {
12615 /* Set the socket error if extended socket options enabled. */
12616 nx_bsd_set_errno(EINVAL);
12617
12618 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12619 return(NX_SOC_ERROR);
12620 }
12621
12622 if(nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_valid == 0)
12623 {
12624 /* Set the socket error if extended socket options enabled. */
12625 nx_bsd_set_errno(EINVAL);
12626
12627 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12628 return(NX_SOC_ERROR);
12629 }
12630
12631 #if 0
12632 /* Pickup the source MAC address */
12633 src_mac_msw = nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_physical_address_msw;
12634 src_mac_lsw = nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_physical_address_lsw;
12635 #endif
12636
12637
12638
12639 /* Validate the packet length */
12640 if(msgLength > (INT)(nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_ip_mtu_size + 14))
12641 {
12642 /* Set the socket error if extended socket options enabled. */
12643 nx_bsd_set_errno(EINVAL);
12644
12645 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12646 return(NX_SOC_ERROR);
12647 }
12648
12649 /* FIXME: If the socket is non-blocking, Timeout value should be set to 0 */
12650 status = nx_packet_allocate(nx_bsd_default_packet_pool, &packet_ptr, NX_PHYSICAL_HEADER, NX_NO_WAIT);
12651
12652 /* Check for errors. */
12653 if (status != NX_SUCCESS)
12654 {
12655
12656 /* Set the socket error. */
12657 nx_bsd_set_errno(ENOBUFS);
12658
12659 /* Return an error status.*/
12660 NX_BSD_ERROR(status, __LINE__);
12661 return(NX_SOC_ERROR);
12662 }
12663
12664
12665
12666 /* Now copy the data into the NetX packet. */
12667 status = nx_packet_data_append(packet_ptr, (VOID *) msg, (ULONG)msgLength, nx_bsd_default_packet_pool, NX_NO_WAIT);
12668
12669 /* Was the data copy successful? */
12670 if (status != NX_SUCCESS)
12671 {
12672
12673 nx_packet_release(packet_ptr);
12674
12675 /* Set the socket error. */
12676 nx_bsd_set_errno(ENOBUFS);
12677
12678 /* Return an error status.*/
12679 NX_BSD_ERROR(status, __LINE__);
12680 return(NX_SOC_ERROR);
12681 }
12682
12683 /* Now ready to transmit this packet. */
12684 driver_request.nx_ip_driver_ptr = nx_bsd_default_ip;
12685 if(destAddr_ll -> sll_protocol == ETHERTYPE_PPPOE_SESS)
12686 driver_request.nx_ip_driver_command = NX_LINK_PACKET_PPPOE_SESS_SEND;
12687 else
12688 driver_request.nx_ip_driver_command = NX_LINK_PACKET_PPPOE_DISC_SEND;
12689 driver_request.nx_ip_driver_packet = packet_ptr;
12690 driver_request.nx_ip_driver_interface = &nx_bsd_default_ip -> nx_ip_interface[if_index];
12691
12692 /* Obtain the BSD lock. */
12693 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
12694
12695 /* Check the status. */
12696 if (status != NX_SUCCESS)
12697 {
12698
12699 nx_packet_release(packet_ptr);
12700
12701 /* Set the socket error if extended socket options enabled. */
12702 nx_bsd_set_errno(EACCES);
12703
12704 /* Return an error. */
12705 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
12706 return(NX_SOC_ERROR);
12707 }
12708
12709 (driver_request.nx_ip_driver_interface -> nx_interface_link_driver_entry)(&driver_request);
12710
12711 /* Release the mutex. */
12712 tx_mutex_put(nx_bsd_protection_ptr);
12713
12714 return(msgLength);
12715 }
12716
12717
12718 /**************************************************************************/
12719 /* */
12720 /* FUNCTION RELEASE */
12721 /* */
12722 /* _nx_bsd_pppoe_packet_received PORTABLE C */
12723 /* 6.1 */
12724 /* AUTHOR */
12725 /* */
12726 /* Yuxin Zhou, Microsoft Corporation */
12727 /* */
12728 /* DESCRIPTION */
12729 /* */
12730 /* This function receives raw PPPOE packet from driver directly. */
12731 /* */
12732 /* INPUT */
12733 /* */
12734 /* packet_ptr Pointer to received packet */
12735 /* frame_type Type of frame */
12736 /* interface_id Interface ID */
12737 /* */
12738 /* OUTPUT */
12739 /* */
12740 /* NX_SUCCESS */
12741 /* */
12742 /* CALLS */
12743 /* */
12744 /* nx_bsd_select_wakeup Wake up any asychronous */
12745 /* receive call */
12746 /* nx_packet_release Release the packet on error */
12747 /* */
12748 /* CALLED BY */
12749 /* */
12750 /* Application Code */
12751 /* */
12752 /* RELEASE HISTORY */
12753 /* */
12754 /* DATE NAME DESCRIPTION */
12755 /* */
12756 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12757 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12758 /* resulting in version 6.1 */
12759 /* */
12760 /**************************************************************************/
_nx_bsd_pppoe_packet_received(NX_PACKET * packet_ptr,UINT frame_type,UINT interface_id)12761 UINT _nx_bsd_pppoe_packet_received(NX_PACKET *packet_ptr, UINT frame_type, UINT interface_id)
12762 {
12763
12764 UINT i;
12765 UINT sockid = NX_BSD_MAX_SOCKETS;
12766 UINT create_id = 0xFFFFFFFF;
12767 NX_BSD_SOCKET *bsd_ptr;
12768
12769 NX_PARAMETER_NOT_USED(interface_id);
12770
12771 /* Find the socket with the lowest create-ID. Put the packet into the socket's recevie queue. */
12772 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
12773 {
12774 if((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE) &&
12775 /*
12776 (nx_bsd_socket_array[i].nx_bsd_raw_socket_enabled == NX_TRUE) &&
12777 */
12778 (nx_bsd_socket_array[i].nx_bsd_socket_family == AF_PACKET) &&
12779 (nx_bsd_socket_array[i].nx_bsd_socket_protocol == frame_type))
12780 {
12781 if(nx_bsd_socket_array[i].nx_bsd_socket_create_id < create_id)
12782 {
12783 sockid = i;
12784 create_id = nx_bsd_socket_array[i].nx_bsd_socket_create_id;
12785 }
12786 }
12787 }
12788 if(sockid == NX_BSD_MAX_SOCKETS)
12789 {
12790 /* No BSD sockets are avaialble for this frame type. */
12791 nx_packet_release(packet_ptr);
12792 return(NX_SUCCESS);
12793 }
12794 /* Now we need to put the packet into the socket. */
12795 bsd_ptr = &nx_bsd_socket_array[sockid];
12796
12797 /* Drop the packet if the receive queue exceeds max depth. */
12798 if(bsd_ptr -> nx_bsd_socket_received_packet_count >=
12799 bsd_ptr -> nx_bsd_socket_received_packet_count_max)
12800 {
12801 nx_packet_release(packet_ptr);
12802 return(NX_SUCCESS);
12803 }
12804
12805 if(bsd_ptr -> nx_bsd_socket_received_packet)
12806 {
12807 bsd_ptr -> nx_bsd_socket_received_packet_tail -> nx_packet_queue_next = packet_ptr;
12808 }
12809 else
12810 {
12811 bsd_ptr -> nx_bsd_socket_received_packet = packet_ptr;
12812 bsd_ptr -> nx_bsd_socket_received_packet_offset = 0;
12813 }
12814
12815 bsd_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
12816 bsd_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
12817 bsd_ptr -> nx_bsd_socket_received_packet_count ++;
12818
12819 nx_bsd_select_wakeup(sockid, FDSET_READ);
12820
12821 return 0;
12822 }
12823 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
12824
12825 #ifdef NX_BSD_RAW_SUPPORT
12826
12827 /**************************************************************************/
12828 /* */
12829 /* FUNCTION RELEASE */
12830 /* */
12831 /* _nx_bsd_hardware_internal_sendto PORTABLE C */
12832 /* 6.1 */
12833 /* AUTHOR */
12834 /* */
12835 /* Yuxin Zhou, Microsoft Corporation */
12836 /* */
12837 /* DESCRIPTION */
12838 /* */
12839 /* This function sends raw packet to driver directly. */
12840 /* */
12841 /* INPUT */
12842 /* */
12843 /* bsd_socket_ptr Pointer to bsd socket */
12844 /* msg Message to send */
12845 /* msgLength Length of message */
12846 /* flags Flags */
12847 /* destAddr Pointer to destination address*/
12848 /* destAddrLen Length of destination address */
12849 /* */
12850 /* OUTPUT */
12851 /* */
12852 /* msgLength On success */
12853 /* NX_SOC_ERROR (-1) On failure */
12854 /* */
12855 /* CALLS */
12856 /* */
12857 /* nx_packet_allocate Allocate a packet */
12858 /* nx_packet_data_append Append data to the packet */
12859 /* nx_packet_release Release the packet on error */
12860 /* tx_mutex_get Obtain exclusive access to */
12861 /* tx_mutex_put Release exclusive access */
12862 /* */
12863 /* CALLED BY */
12864 /* */
12865 /* Application Code */
12866 /* */
12867 /* RELEASE HISTORY */
12868 /* */
12869 /* DATE NAME DESCRIPTION */
12870 /* */
12871 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12872 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12873 /* resulting in version 6.1 */
12874 /* */
12875 /**************************************************************************/
_nx_bsd_hardware_internal_sendto(NX_BSD_SOCKET * bsd_socket_ptr,CHAR * msg,INT msgLength,INT flags,struct nx_bsd_sockaddr * destAddr,INT destAddrLen)12876 static INT _nx_bsd_hardware_internal_sendto(NX_BSD_SOCKET *bsd_socket_ptr, CHAR *msg, INT msgLength, INT flags, struct nx_bsd_sockaddr* destAddr, INT destAddrLen)
12877 {
12878 UINT if_index;
12879 struct nx_bsd_sockaddr_ll
12880 *destAddr_ll;
12881 UINT status;
12882 NX_PACKET *packet_ptr = NX_NULL;
12883
12884 NX_PARAMETER_NOT_USED(bsd_socket_ptr);
12885 NX_PARAMETER_NOT_USED(flags);
12886
12887 /* Validate the parameters. */
12888 if(destAddr == NX_NULL)
12889 {
12890 /* Set the socket error if extended socket options enabled. */
12891 nx_bsd_set_errno(EINVAL);
12892
12893 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12894 return(NX_SOC_ERROR);
12895 }
12896
12897 if(destAddr -> sa_family != AF_PACKET)
12898 {
12899 /* Set the socket error if extended socket options enabled. */
12900 nx_bsd_set_errno(EINVAL);
12901
12902 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12903 return(NX_SOC_ERROR);
12904 }
12905
12906 if(destAddrLen != sizeof(struct nx_bsd_sockaddr_ll))
12907 {
12908 /* Set the socket error if extended socket options enabled. */
12909 nx_bsd_set_errno(EINVAL);
12910
12911 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12912 return(NX_SOC_ERROR);
12913 }
12914
12915 destAddr_ll = (struct nx_bsd_sockaddr_ll*)destAddr;
12916
12917 /* Validate the interface ID */
12918 if_index = (UINT)(destAddr_ll -> sll_ifindex);
12919 if(if_index >= NX_MAX_IP_INTERFACES)
12920 {
12921 /* Set the socket error if extended socket options enabled. */
12922 nx_bsd_set_errno(EINVAL);
12923
12924 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12925 return(NX_SOC_ERROR);
12926 }
12927
12928 if(nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_valid == 0)
12929 {
12930 /* Set the socket error if extended socket options enabled. */
12931 nx_bsd_set_errno(EINVAL);
12932
12933 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12934 return(NX_SOC_ERROR);
12935 }
12936
12937 /* Validate the packet length */
12938 if(msgLength > (INT)(nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_ip_mtu_size + 18))
12939 {
12940 /* Set the socket error if extended socket options enabled. */
12941 nx_bsd_set_errno(EINVAL);
12942
12943 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12944 return(NX_SOC_ERROR);
12945 }
12946
12947 status = nx_packet_allocate(nx_bsd_default_packet_pool, &packet_ptr, NX_PHYSICAL_HEADER, NX_NO_WAIT);
12948
12949 /* Check for errors. */
12950 if (status != NX_SUCCESS)
12951 {
12952
12953 /* Set the socket error. */
12954 nx_bsd_set_errno(ENOBUFS);
12955
12956 /* Return an error status.*/
12957 NX_BSD_ERROR(status, __LINE__);
12958 return(NX_SOC_ERROR);
12959 }
12960
12961 /* Set IP interface. */
12962 packet_ptr -> nx_packet_ip_interface = &nx_bsd_default_ip -> nx_ip_interface[if_index];
12963
12964 /* Now copy the data into the NetX packet. */
12965 status = nx_packet_data_append(packet_ptr, (VOID *) msg, (ULONG)msgLength, nx_bsd_default_packet_pool, NX_NO_WAIT);
12966
12967 /* Was the data copy successful? */
12968 if (status != NX_SUCCESS)
12969 {
12970
12971 nx_packet_release(packet_ptr);
12972
12973 /* Set the socket error. */
12974 nx_bsd_set_errno(ENOBUFS);
12975
12976 /* Return an error status.*/
12977 NX_BSD_ERROR(status, __LINE__);
12978 return(NX_SOC_ERROR);
12979 }
12980
12981 #if defined(__PRODUCT_NETXDUO__) && defined(NX_ENABLE_INTERFACE_CAPABILITY)
12982 packet_ptr -> nx_packet_interface_capability_flag = nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_capability_flag;
12983 #endif /* defined(__PRODUCT_NETXDUO__) && defined(NX_ENABLE_INTERFACE_CAPABILITY) */
12984
12985 /* Obtain the BSD lock. */
12986 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
12987
12988 /* Check the status. */
12989 if (status != NX_SUCCESS)
12990 {
12991
12992 nx_packet_release(packet_ptr);
12993
12994 /* Set the socket error if extended socket options enabled. */
12995 nx_bsd_set_errno(EACCES);
12996
12997 /* Return an error. */
12998 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
12999 return(NX_SOC_ERROR);
13000 }
13001
13002 _nx_driver_hardware_packet_send(packet_ptr);
13003
13004 /* Release the mutex. */
13005 tx_mutex_put(nx_bsd_protection_ptr);
13006
13007 return(msgLength);
13008 }
13009
13010
13011 /**************************************************************************/
13012 /* */
13013 /* FUNCTION RELEASE */
13014 /* */
13015 /* _nx_bsd_hardware_packet_received PORTABLE C */
13016 /* 6.1 */
13017 /* AUTHOR */
13018 /* */
13019 /* Yuxin Zhou, Microsoft Corporation */
13020 /* */
13021 /* DESCRIPTION */
13022 /* */
13023 /* This function receives raw packet from driver directly. */
13024 /* */
13025 /* INPUT */
13026 /* */
13027 /* packet_ptr Pointer to received packet */
13028 /* consumed Return packet consumed or not */
13029 /* */
13030 /* OUTPUT */
13031 /* */
13032 /* None */
13033 /* */
13034 /* CALLS */
13035 /* */
13036 /* nx_bsd_select_wakeup Wake up any asychronous */
13037 /* receive call */
13038 /* */
13039 /* CALLED BY */
13040 /* */
13041 /* Application Code */
13042 /* */
13043 /* RELEASE HISTORY */
13044 /* */
13045 /* DATE NAME DESCRIPTION */
13046 /* */
13047 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13048 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13049 /* resulting in version 6.1 */
13050 /* */
13051 /**************************************************************************/
_nx_bsd_hardware_packet_received(NX_PACKET * packet_ptr,UCHAR * consumed)13052 static VOID _nx_bsd_hardware_packet_received(NX_PACKET *packet_ptr, UCHAR *consumed)
13053 {
13054
13055 UINT i;
13056 UINT sockid = NX_BSD_MAX_SOCKETS;
13057 NX_BSD_SOCKET *bsd_ptr;
13058
13059 /* Initialize the consumed to be false. */
13060 *consumed = NX_FALSE;
13061
13062 /* Find the socket with the matching interface. Put the packet into the socket's recevie queue. */
13063 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
13064 {
13065 if((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE) &&
13066 (nx_bsd_socket_array[i].nx_bsd_socket_family == AF_PACKET) &&
13067 ((nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY) ||
13068 (nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface == (ULONG)(packet_ptr -> nx_packet_ip_interface))))
13069 {
13070 sockid = i;
13071 }
13072 }
13073 if(sockid == NX_BSD_MAX_SOCKETS)
13074 {
13075 /* No BSD sockets are avaialble for this frame type. */
13076 return;
13077 }
13078 /* Now we need to put the packet into the socket. */
13079 bsd_ptr = &nx_bsd_socket_array[sockid];
13080
13081 /* Drop the packet if the receive queue exceeds max depth. */
13082 if(bsd_ptr -> nx_bsd_socket_received_packet_count >=
13083 bsd_ptr -> nx_bsd_socket_received_packet_count_max)
13084 {
13085 return;
13086 }
13087
13088 #ifndef NX_DISABLE_BSD_RAW_PACKET_DUPLICATE
13089 /* Duplicate the packet. */
13090 if (nx_packet_copy(packet_ptr, &packet_ptr, nx_bsd_default_packet_pool, NX_NO_WAIT) != NX_SUCCESS)
13091 {
13092 return;
13093 }
13094 #else
13095 /* Consume the packet. IP layer will not see it. */
13096 *consumed = NX_TRUE;
13097 #endif /* NX_DISABLE_BSD_RAW_PACKET_DUPLICATE */
13098
13099 if(bsd_ptr -> nx_bsd_socket_received_packet)
13100 {
13101 bsd_ptr -> nx_bsd_socket_received_packet_tail -> nx_packet_queue_next = packet_ptr;
13102 }
13103 else
13104 {
13105 bsd_ptr -> nx_bsd_socket_received_packet = packet_ptr;
13106 bsd_ptr -> nx_bsd_socket_received_packet_offset = 0;
13107 }
13108
13109 bsd_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
13110 bsd_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
13111 bsd_ptr -> nx_bsd_socket_received_packet_count ++;
13112
13113 nx_bsd_select_wakeup(sockid, FDSET_READ);
13114
13115 return;
13116 }
13117 #endif /* NX_BSD_RAW_SUPPORT */
13118
13119
13120
13121 /**************************************************************************/
13122 /* */
13123 /* FUNCTION RELEASE */
13124 /* */
13125 /* inet_pton PORTABLE C */
13126 /* 6.3.0 */
13127 /* AUTHOR */
13128 /* */
13129 /* Yuxin Zhou, Microsoft Corporation */
13130 /* */
13131 /* DESCRIPTION */
13132 /* */
13133 /* This function converts an IP address from presentation to numeric. */
13134 /* */
13135 /* INPUT */
13136 /* */
13137 /* af Either AF_INET or AF_INET6 */
13138 /* src A pointer pointing to the */
13139 /* presentation of IP address */
13140 /* dst A pointer pointing to the */
13141 /* destination memory */
13142 /* */
13143 /* OUTPUT */
13144 /* */
13145 /* status 1 OK */
13146 /* 0 invalid presentation */
13147 /* -1 error */
13148 /* */
13149 /* CALLS */
13150 /* */
13151 /* inet_aton Convert IPv4 address from */
13152 /* presentation to numeric */
13153 /* */
13154 /* CALLED BY */
13155 /* */
13156 /* Application Code */
13157 /* */
13158 /* RELEASE HISTORY */
13159 /* */
13160 /* DATE NAME DESCRIPTION */
13161 /* */
13162 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13163 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13164 /* resulting in version 6.1 */
13165 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
13166 /* used new API/structs naming,*/
13167 /* resulting in version 6.3.0 */
13168 /* */
13169 /**************************************************************************/
nx_bsd_inet_pton(INT af,const CHAR * src,VOID * dst)13170 INT nx_bsd_inet_pton(INT af, const CHAR *src, VOID *dst)
13171 {
13172 CHAR ch;
13173 USHORT value;
13174 /* A number used to convert a character in '0123456789abcdefABCDEF' to a number. */
13175 UINT minuend;
13176 /* A counter used to recoder the number of digits between 2 colons. */
13177 UINT digit_counter;
13178
13179 UCHAR *colon_location;
13180 /* A pointer used to traverse the destination memory. */
13181 UCHAR *dst_cur_ptr;
13182 /* A pointer to the end of the destination memory. */
13183 UCHAR *dst_end_ptr;
13184 ULONG *dst_long_ptr;
13185
13186 const CHAR *ipv4_addr_start = src;
13187 UINT n, i;
13188
13189 struct nx_bsd_in_addr ipv4_addr;
13190
13191 if(af == AF_INET)
13192 {
13193 /* Convert IPv4 address from presentation to numeric. */
13194 if(nx_bsd_inet_aton(src, &ipv4_addr))
13195 {
13196 /* Copy the IPv4 address to the destination. */
13197 *((ULONG *)dst) = ipv4_addr.s_addr;
13198 return 1;
13199 }
13200 return 0;
13201 }
13202 else if(af == AF_INET6)
13203 {
13204 /* If : is at the beginning, the next value must be : .*/
13205 if(*src == ':')
13206 if(*src++ != ':')
13207 return 0;
13208
13209 /* Initialization. */
13210 value = 0;
13211 digit_counter = 0;
13212 colon_location = NX_NULL;
13213 dst_cur_ptr = dst;
13214 /* Calculate the end of the destination memory. */
13215 dst_end_ptr = (UCHAR*)dst + 15;
13216 /* Clear the destination memory. */
13217 memset(dst_cur_ptr, 0, 16);
13218
13219 while(*src != 0)
13220 {
13221 /* Get the current character. */
13222 ch = *src++;
13223
13224 /* Judge which minuend to use.
13225 * '0' - 48 == 0
13226 * 'a' - 87 == 10
13227 * 'A' - 55 == 10
13228 */
13229 minuend = 0;
13230 if(ch >= '0' && ch <= '9')
13231 minuend = 48;
13232 else if(ch >= 'a' && ch <= 'f')
13233 minuend = 87;
13234 else if(ch >= 'A' && ch <= 'F')
13235 minuend = 55;
13236
13237 /* if minuend is not 0, then ch is character in "0123456789abcdefABCDEF" */
13238 if(minuend)
13239 {
13240 /* Convert the character to number. */
13241 value = (USHORT)(value << 4);
13242 value = (USHORT)(value | ((UINT)ch - minuend));
13243
13244 /* The max number of digits between 2 colons is 4. */
13245 if(++digit_counter > 4)
13246 return 0;
13247
13248 continue;
13249 }
13250
13251 if(ch == ':')
13252 {
13253 ipv4_addr_start = src;
13254
13255 /* Is there a digit before the colon? */
13256 if(!digit_counter)
13257 {
13258 /* There is no digit before the colon. */
13259
13260 /* If there are 2 "::", Invalid Presentation Format.
13261 * IF there is a ":::", Invalid Presention Format. */
13262 if(colon_location)
13263 return 0;
13264
13265 /* Record the colon location. */
13266 colon_location = dst_cur_ptr;
13267 continue;
13268 }
13269 else if(*src == '\0')
13270 {
13271 /* The colon is at the end of src, Invalid Presention Format. */
13272 return 0;
13273 }
13274
13275 if(dst_cur_ptr + 1 > dst_end_ptr)
13276 {
13277 /* Invalid Presentation Format. */
13278 return 0;
13279 }
13280
13281 /* Store the value to the dst memory. */
13282 *(dst_cur_ptr++) = (UCHAR) (value >> 8) & 0xff;
13283 *(dst_cur_ptr++) = (UCHAR) (value) & 0xff;
13284
13285 /* Reset the value and digit counter. */
13286 digit_counter = 0;
13287 value = 0;
13288
13289 continue;
13290
13291 }
13292 else if(ch == '.')
13293 {
13294 /* Process the dotted-decimal string in IPv4-mapped IPv6 address and IPv4-compatible IPv6 address. */
13295
13296 if(dst_cur_ptr + 3 > dst_end_ptr)
13297 {
13298 /* Invalid Presentation Format. */
13299 return 0;
13300 }
13301
13302 /* Convert the ipv4 address from presentation to numeric. */
13303 if(nx_bsd_inet_aton(ipv4_addr_start, &ipv4_addr))
13304 {
13305
13306 /* Make sure the result is in network byte order. */
13307 ipv4_addr.s_addr = ntohl(ipv4_addr.s_addr);
13308 NX_CHANGE_ULONG_ENDIAN(ipv4_addr.s_addr);
13309
13310 /* Store the value to the dst memory. */
13311 *(ULONG *)dst_cur_ptr = ipv4_addr.s_addr;
13312
13313 dst_cur_ptr += 4;
13314 digit_counter = 0;
13315
13316 break;
13317 }
13318 else
13319 return 0;
13320
13321
13322 }
13323 else
13324 {
13325 return 0;
13326 }
13327 }
13328
13329 if(digit_counter)
13330 {
13331
13332 /* Invalid Presentation Format. */
13333 if(dst_cur_ptr + 1 > dst_end_ptr)
13334 return 0;
13335
13336 /* Store the value to the dst memory. */
13337 *(dst_cur_ptr++) = (UCHAR) (value >> 8) & 0xff;
13338 *(dst_cur_ptr++) = (UCHAR) (value) & 0xff;
13339
13340 }
13341
13342 if(colon_location)
13343 {
13344 /* There is a :: in the IPv6 address presentation. */
13345
13346 /* Calculate how many octets should be moved to the end of the dst memory. */
13347 n = (UINT)(dst_cur_ptr - colon_location);
13348
13349 if(dst_cur_ptr == dst_end_ptr)
13350 return 0;
13351
13352 /* Move the data to the end of dst memory.
13353 * ----------- -----------
13354 * |aabb0000000| ----> |aa0000000bb|
13355 * ----------- -----------
13356 */
13357 for(i = 1; i <=n; i++)
13358 {
13359 *(dst_end_ptr--) = colon_location[n - i];
13360 colon_location[n-i] = 0;
13361 }
13362
13363 dst_cur_ptr = dst_end_ptr + 1;
13364 }
13365
13366 if(dst_cur_ptr != (dst_end_ptr + 1))
13367 return 0;
13368
13369 dst_long_ptr = (ULONG *)dst;
13370
13371 /* First convert it to host byte order. */
13372 NX_CHANGE_ULONG_ENDIAN(dst_long_ptr[0]);
13373 NX_CHANGE_ULONG_ENDIAN(dst_long_ptr[1]);
13374 NX_CHANGE_ULONG_ENDIAN(dst_long_ptr[2]);
13375 NX_CHANGE_ULONG_ENDIAN(dst_long_ptr[3]);
13376
13377 /* Convert it to network byte order by BSD macros. */
13378 dst_long_ptr[0] = htonl(dst_long_ptr[0]);
13379 dst_long_ptr[1] = htonl(dst_long_ptr[1]);
13380 dst_long_ptr[2] = htonl(dst_long_ptr[2]);
13381 dst_long_ptr[3] = htonl(dst_long_ptr[3]);
13382 return 1;
13383 }
13384 else
13385 {
13386 /* Error. */
13387 return -1;
13388 }
13389 }
13390
13391 /**************************************************************************/
13392 /* */
13393 /* FUNCTION RELEASE */
13394 /* */
13395 /* inet_ntop PORTABLE C */
13396 /* 6.3.0 */
13397 /* AUTHOR */
13398 /* */
13399 /* Yuxin Zhou, Microsoft Corporation */
13400 /* */
13401 /* DESCRIPTION */
13402 /* */
13403 /* This function converts an IP address from numeric to presentation. */
13404 /* */
13405 /* INPUT */
13406 /* */
13407 /* af Either AF_INET or AF_INET6 */
13408 /* src A void pointer pointing to */
13409 /* network byte order IP address*/
13410 /* dst A char pointer pointing to */
13411 /* the destination buffer */
13412 /* size The size of the destination */
13413 /* buffer */
13414 /* */
13415 /* OUTPUT */
13416 /* */
13417 /* dst The destination buffer */
13418 /* */
13419 /* CALLS */
13420 /* */
13421 /* inet_ntoa_internal Convert IPv4 address from */
13422 /* numeric to presentation */
13423 /* */
13424 /* CALLED BY */
13425 /* */
13426 /* Application Code */
13427 /* */
13428 /* RELEASE HISTORY */
13429 /* */
13430 /* DATE NAME DESCRIPTION */
13431 /* */
13432 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13433 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13434 /* resulting in version 6.1 */
13435 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
13436 /* used new API/structs naming,*/
13437 /* resulting in version 6.3.0 */
13438 /* */
13439 /**************************************************************************/
nx_bsd_inet_ntop(INT af,const VOID * src,CHAR * dst,nx_bsd_socklen_t size)13440 const CHAR *nx_bsd_inet_ntop(INT af, const VOID *src, CHAR *dst, nx_bsd_socklen_t size)
13441 {
13442
13443 INT shorthand_index;
13444 INT shorthand_len;
13445 INT current_index;
13446 INT current_len;
13447
13448 INT i;
13449 INT index;
13450 UINT rt_size;
13451
13452
13453 if(af == AF_INET)
13454 {
13455 /* Convert IPv4 address from numeric to presentation. */
13456 if(inet_ntoa_internal(src, dst, size))
13457 return dst;
13458 else
13459 return NX_NULL;
13460 }
13461 else if(af == AF_INET6)
13462 {
13463 USHORT temp[8];
13464 temp[0] = (USHORT)(ntohl(*((ULONG *)src)) >> 16);
13465 temp[1] = (USHORT)(ntohl(*((ULONG *)src)) & 0xFFFF);
13466 temp[2] = (USHORT)(ntohl(*(((ULONG *)src) + 1)) >> 16);
13467 temp[3] = (USHORT)(ntohl(*(((ULONG *)src) + 1)) & 0xFFFF);
13468 temp[4] = (USHORT)(ntohl(*(((ULONG *)src) + 2)) >> 16);
13469 temp[5] = (USHORT)(ntohl(*(((ULONG *)src) + 2)) & 0xFFFF);
13470 temp[6] = (USHORT)(ntohl(*(((ULONG *)src) + 3)) >> 16);
13471 temp[7] = (USHORT)(ntohl(*(((ULONG *)src) + 3)) & 0xFFFF);
13472
13473 /* Initialization. */
13474 shorthand_index = -1;
13475 shorthand_len = 0;
13476 current_index = -1;
13477 current_len = 0;
13478
13479 /* Find the longest 0x00 in src for ::
13480 * 16 * 8 == 128 */
13481 for(i = 0; i < 8; i++)
13482 {
13483 if(temp[i] == 0)
13484 {
13485 if(current_index == -1)
13486 {
13487 /* Record the index of 0x00, Initialize the length to 1. */
13488 current_index = i;
13489 current_len = 1;
13490 }
13491 else
13492 {
13493 current_len++;
13494 }
13495 }
13496 else
13497 {
13498 /* Not 0x00 . */
13499
13500 if(current_index != -1)
13501 {
13502 /* Not equal -1, means there is record of 0x00s . */
13503
13504 if(shorthand_index == -1 || current_len > shorthand_len)
13505 {
13506 /* Record the longest 0x00s. */
13507 shorthand_index = current_index;
13508 shorthand_len = current_len;
13509 }
13510
13511 /* Reset the index. */
13512 current_index = -1;
13513 }
13514
13515 }
13516 }
13517
13518
13519 if(current_len > shorthand_len)
13520 {
13521 /* Record the longest 0x00s. */
13522 shorthand_index = current_index;
13523 shorthand_len = current_len;
13524 }
13525
13526 /* If length is less than 2, no need for shorthand. */
13527 if(shorthand_len < 2)
13528 {
13529 shorthand_index = -1;
13530 }
13531
13532 index = 0;
13533 /* Format the result. */
13534 for(i = 0; i < 8; i++)
13535 {
13536 /* Is i in the range of :: */
13537 if((shorthand_index != -1) &&
13538 (i >= shorthand_index) &&
13539 (i < (shorthand_index + shorthand_len)))
13540 {
13541 if(i == shorthand_index)
13542 {
13543 /* Check if there is enough memory to store a character. */
13544 if((size - (ULONG)index) < 1)
13545 return NX_NULL;
13546
13547 dst[index++] = ':';
13548 }
13549 continue;
13550 }
13551
13552 if(i != 0)
13553 {
13554 /* Check if there is enough memory to store a character. */
13555 if((size - (ULONG)index) < 1)
13556 return NX_NULL;
13557
13558 dst[index++] = ':';
13559 }
13560
13561 /* Does this address contain IPv4 address. */
13562 if(i == 6 && shorthand_index == 0 &&
13563 (shorthand_len == 6 || /* IPv4-mapped IPv6 address -----> ::1.2.3.4 */
13564 (shorthand_len == 5 && temp[5] == 0xffff))) /* IPv4-compatible IPv6 address -----> ::ffff:1.2.3.4 */
13565 {
13566 /* Convert ipv4 address to string. 12 == 16 - 4*/
13567 rt_size = (UINT)inet_ntoa_internal((UCHAR*)src + 12, &dst[index], size - (ULONG)index);
13568
13569 /* Check the return size, 0 means error. */
13570 if(rt_size)
13571 index += (INT)rt_size;
13572 else
13573 return NX_NULL;
13574 }
13575
13576 /* Convert hex number to string */
13577 rt_size = bsd_number_convert(temp[i], &dst[index], size - (ULONG)index, 16);
13578 if(!rt_size)
13579 return NX_NULL;
13580
13581 /* Increment the index. */
13582 index += (INT)rt_size;
13583
13584 }
13585
13586 /* Is there a trailing : */
13587 if((shorthand_index != -1) && (shorthand_index + shorthand_len == 8))
13588 {
13589 /* Check if there is enough memory to store a character. */
13590 if((size - (ULONG)index) < 1)
13591 return NX_NULL;
13592
13593 dst[index++] = ':';
13594
13595 }
13596
13597 /* Check if there is enough memory to store a character. */
13598 if((size - (ULONG)index) < 1)
13599 return NX_NULL;
13600
13601 dst[index] = '\0';
13602
13603 return dst;
13604 }
13605 else
13606 {
13607 return NX_NULL;
13608 }
13609 }
13610
13611 /**************************************************************************/
13612 /* */
13613 /* FUNCTION RELEASE */
13614 /* */
13615 /* inet_ntoa_internal PORTABLE C */
13616 /* 6.1 */
13617 /* AUTHOR */
13618 /* */
13619 /* Yuxin Zhou, Microsoft Corporation */
13620 /* */
13621 /* DESCRIPTION */
13622 /* */
13623 /* This function converts an IPv4 address to a string and returns the */
13624 /* size of the string. */
13625 /* */
13626 /* INPUT */
13627 /* */
13628 /* src A void pointer pointing to */
13629 /* IPv4 address */
13630 /* dst A char pointer pointing to */
13631 /* the destination buffer */
13632 /* dst_size The size of the destination */
13633 /* buffer */
13634 /* */
13635 /* OUTPUT */
13636 /* */
13637 /* index The size of the IPv4 address */
13638 /* string */
13639 /* */
13640 /* CALLS */
13641 /* */
13642 /* memset Set the memory to 0 */
13643 /* bsd_number_convert Convert a number to string */
13644 /* */
13645 /* CALLED BY */
13646 /* */
13647 /* NetX Duo BSD Layer Source Code */
13648 /* */
13649 /* RELEASE HISTORY */
13650 /* */
13651 /* DATE NAME DESCRIPTION */
13652 /* */
13653 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13654 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13655 /* resulting in version 6.1 */
13656 /* */
13657 /**************************************************************************/
13658
inet_ntoa_internal(const VOID * src,CHAR * dst,ULONG dst_size)13659 static INT inet_ntoa_internal(const VOID *src, CHAR *dst, ULONG dst_size)
13660 {
13661 ULONG temp;
13662 UINT size;
13663 UINT index = 0;
13664
13665
13666 /* Set a local pointer to move up the buffer. */
13667 temp = ntohl(*((ULONG *)src));
13668
13669 memset(dst, 0, dst_size);
13670
13671 /* Convert the first number to a string. */
13672 size = bsd_number_convert((temp >> 24), &dst[0], dst_size - index, 10);
13673
13674 if(!size)
13675 return 0;
13676
13677 /* Move up the index and buffer pointer. */
13678 index += size;
13679
13680 /* Check the rest of the dst buffer. */
13681 if((dst_size - index) < 1)
13682 return 0;
13683
13684 /* Add the decimal. */
13685 dst[index++] = '.';
13686
13687 /* And repeat three more times...*/
13688 size = bsd_number_convert((temp >> 16) & 0xff, &dst[index], dst_size - index, 10);
13689
13690 if(!size)
13691 return 0;
13692
13693 index += size;
13694
13695 if((dst_size - index) < 1)
13696 return 0;
13697
13698 dst[index++] = '.';
13699
13700 size = bsd_number_convert((temp >> 8) & 0xff, &dst[index], dst_size - index, 10);
13701
13702 if(!size)
13703 return 0;
13704
13705 index += size;
13706
13707 if((dst_size - index) < 1)
13708 return 0;
13709
13710 dst[index++] = '.';
13711
13712 size = bsd_number_convert(temp & 0xff, &dst[index], dst_size - index, 10);
13713
13714 if(!size)
13715 return 0;
13716
13717 index += size;
13718
13719 if((dst_size - index) < 1)
13720 return 0;
13721
13722 dst[index++] = '\0';
13723
13724 /* Return the size of the dst string. */
13725 return((INT)(index));
13726 }
13727
13728
13729 /**************************************************************************/
13730 /* */
13731 /* FUNCTION RELEASE */
13732 /* */
13733 /* getaddrinfo PORTABLE C */
13734 /* 6.3.0 */
13735 /* AUTHOR */
13736 /* */
13737 /* Yuxin Zhou, Microsoft Corporation */
13738 /* */
13739 /* DESCRIPTION */
13740 /* */
13741 /* This function returns one or more addrinfo structures according to */
13742 /* the specified node and service. */
13743 /* */
13744 /* INPUT */
13745 /* */
13746 /* node Node is either a hostname or */
13747 /* an address string(dotted- */
13748 /* decimal for IPv4 or a hex */
13749 /* string for IPv6). */
13750 /* service Service is either a service */
13751 /* name or a decimal port number*/
13752 /* string. */
13753 /* hints Hints is either a null pointer*/
13754 /* or a pointer to an addrinfo */
13755 /* structure that the caller */
13756 /* fills in with hints about the*/
13757 /* types of information the */
13758 /* caller wants returned. */
13759 /* res Pointer to the returned */
13760 /* addrinfo list. */
13761 /* */
13762 /* OUTPUT */
13763 /* */
13764 /* status 0 if OK, nonzero on errors */
13765 /* */
13766 /* CALLS */
13767 /* */
13768 /* bsd_string_to_number Convert a string to a number */
13769 /* htons Host byte order to network */
13770 /* byte order */
13771 /* memcmp Memory compare */
13772 /* inet_pton Convert IP address from */
13773 /* presentation to numeric */
13774 /* tx_block_allocate Allocate memory for address or*/
13775 /* addrinfo */
13776 /* memset Set the memory to 0 */
13777 /* freeaddrinfo Release addrinfo memory */
13778 /* nx_dns_ipv4_address_by_name_get Get ipv4 addr by name via dns */
13779 /* nxd_dns_ipv6_address_by_name_get Get ipv6 addr by name via dns */
13780 /* */
13781 /* CALLED BY */
13782 /* */
13783 /* Application Code */
13784 /* */
13785 /* RELEASE HISTORY */
13786 /* */
13787 /* DATE NAME DESCRIPTION */
13788 /* */
13789 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13790 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
13791 /* buffer length verification, */
13792 /* verified memcpy use cases, */
13793 /* fixed compiler errors, */
13794 /* resulting in version 6.1 */
13795 /* 07-29-2022 Yuxin Zhou Modified comment(s), and */
13796 /* fixed compiler warnings, */
13797 /* resulting in version 6.1.12 */
13798 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
13799 /* used new API/structs naming,*/
13800 /* resulting in version 6.3.0 */
13801 /* */
13802 /**************************************************************************/
nx_bsd_getaddrinfo(const CHAR * node,const CHAR * service,const struct nx_bsd_addrinfo * hints,struct nx_bsd_addrinfo ** res)13803 INT nx_bsd_getaddrinfo(const CHAR *node, const CHAR *service, const struct nx_bsd_addrinfo *hints, struct nx_bsd_addrinfo **res)
13804 {
13805
13806 UINT status;
13807 #ifdef NX_BSD_ENABLE_DNS
13808 UINT status2;
13809 #endif
13810 UINT pton_flag;
13811 UINT port;
13812 UINT i, j;
13813 INT addr_family;
13814 UINT ipv4_addr_count = 0;
13815 UINT ipv6_addr_count = 0;
13816 UINT match_service_count;
13817 UINT match_service_socktype[3];
13818 UINT match_service_protocol[3];
13819 struct nx_bsd_addrinfo
13820 *addrinfo_cur_ptr = NX_NULL;
13821 struct nx_bsd_addrinfo
13822 *addrinfo_head_ptr = NX_NULL;
13823 struct nx_bsd_addrinfo
13824 *addrinfo_tail_ptr = NX_NULL;
13825 struct nx_bsd_sockaddr
13826 *sockaddr_ptr = NX_NULL;
13827 UCHAR *cname_buffer = NX_NULL;
13828
13829 /* When hints is a null pointer, use the default value below. */
13830 static struct nx_bsd_addrinfo default_hints = {0, AF_UNSPEC, 0, 0, 0, NX_NULL, NX_NULL, NX_NULL};
13831
13832
13833
13834 /* if node and service are null return an error, invalid input. */
13835 if((node == NX_NULL) && (service == NX_NULL))
13836 return EAI_NONAME;
13837
13838 if(hints)
13839 {
13840
13841 /* Check if the address family is valid. */
13842 if((hints -> ai_family != AF_INET) &&
13843 (hints -> ai_family != AF_INET6) &&
13844 (hints -> ai_family != AF_UNSPEC))
13845 return EAI_FAMILY;
13846
13847 /* Check if the socket type is valid. */
13848 if((hints -> ai_socktype != SOCK_DGRAM) &&
13849 (hints -> ai_socktype != SOCK_STREAM) &&
13850 (hints -> ai_socktype != 0))
13851 return EAI_SOCKTYPE;
13852
13853 /* If socktype and protocol are both specified, check if they are meaningful. */
13854 if((hints -> ai_socktype != 0) && (hints -> ai_protocol != 0))
13855 {
13856 if(((hints -> ai_socktype == SOCK_STREAM) && (hints -> ai_protocol != IPPROTO_TCP)) ||
13857 ((hints -> ai_socktype == SOCK_DGRAM) && (hints -> ai_protocol != IPPROTO_UDP)) ||
13858 ((hints -> ai_socktype == SOCK_RAW) && (hints -> ai_protocol != IPPROTO_RAW)))
13859 return EAI_SOCKTYPE;
13860 }
13861
13862 }
13863 else
13864 {
13865 hints = &default_hints;
13866 }
13867
13868 /* Sock type specified? */
13869 if(hints -> ai_socktype == 0)
13870 {
13871
13872 /* No; is protocol specified? */
13873 if(hints -> ai_protocol == 0)
13874 {
13875
13876 /* No, protocol is not specified. */
13877
13878 /* Set default socktype and protocol. */
13879 match_service_count = 3;
13880 match_service_socktype[0] = SOCK_STREAM;
13881 match_service_protocol[0] = IPPROTO_TCP;
13882 match_service_socktype[1] = SOCK_DGRAM;
13883 match_service_protocol[1] = IPPROTO_UDP;
13884 match_service_socktype[2] = SOCK_RAW;
13885 match_service_protocol[2] = 0;
13886 }
13887 else
13888 {
13889
13890 /* protocol is specified. */
13891 match_service_count = 1;
13892 match_service_protocol[0] = (UINT)(hints -> ai_protocol);
13893
13894 /* Set default socktype according to protocol. */
13895 if(hints -> ai_protocol == IPPROTO_TCP)
13896 match_service_socktype[0] = SOCK_STREAM;
13897 else if(hints -> ai_protocol == IPPROTO_UDP)
13898 match_service_socktype[0] = SOCK_DGRAM;
13899 }
13900 }
13901 else
13902 {
13903
13904 /* Socktype is specified. */
13905 match_service_count = 1;
13906 match_service_socktype[0] = (UINT)(hints -> ai_socktype);
13907
13908 if(hints -> ai_protocol == 0)
13909 {
13910
13911 /* Protocol is not specified. */
13912
13913 /* Set default protocol according to socktype. */
13914 if(hints -> ai_socktype == SOCK_STREAM)
13915 match_service_protocol[0] = IPPROTO_TCP;
13916 else if(hints -> ai_socktype == SOCK_DGRAM)
13917 match_service_protocol[0] = IPPROTO_UDP;
13918 else if(hints -> ai_socktype == SOCK_RAW)
13919 match_service_protocol[0] = 0;
13920 }
13921 else
13922 {
13923
13924 /* Protocol is specififed. */
13925 match_service_protocol[0] = (UINT)(hints -> ai_protocol);
13926 }
13927 }
13928
13929 if(service)
13930 {
13931
13932 /* Service is not null. */
13933 if(bsd_string_to_number(service, &port) != NX_SOC_ERROR)
13934 {
13935
13936 /* Service is a decimal port number string, and has been converted to a numeric port successfully. */
13937
13938 /* Convert port from host byte order to network byte order. */
13939 port = htons((USHORT)port);
13940 }
13941 else
13942 {
13943
13944 /* Service is an address name, not a decimal port number string. */
13945
13946 /* Check if numeric service flag is set. If so this is an invalid string. */
13947 if(hints -> ai_flags & AI_NUMERICSERV)
13948 return EAI_NONAME;
13949
13950 match_service_count = 0;
13951
13952 /* Look for a match of name, protocol and socket type for a match in the service list. */
13953 for(i = 0; i < _nx_bsd_serv_list_len; i++)
13954 {
13955
13956 /* Check if there is a match. */
13957 if(!memcmp(_nx_bsd_serv_list_ptr[i].service_name, service, _nx_bsd_string_length((CHAR *)service)) &&
13958 ((_nx_bsd_serv_list_ptr[i].service_socktype == hints -> ai_socktype) ||(hints -> ai_socktype == 0)) &&
13959 ((_nx_bsd_serv_list_ptr[i].service_protocol == hints -> ai_protocol) ||(hints -> ai_protocol == 0)))
13960 {
13961 match_service_socktype[match_service_count] = (UINT)(_nx_bsd_serv_list_ptr[i].service_socktype);
13962 match_service_protocol[match_service_count++] = (UINT)(_nx_bsd_serv_list_ptr[i].service_protocol);
13963
13964 /* Convert host byte order to network byte order. */
13965 port = htons(_nx_bsd_serv_list_ptr[i].service_port);
13966 }
13967 }
13968
13969 /* Service is not available. */
13970 if(match_service_count == 0)
13971 return EAI_SERVICE;
13972 }
13973 }
13974 else
13975 {
13976
13977 /* Convert host byte order to network byte order. */
13978 port = htons(0);
13979 }
13980
13981 if(node)
13982 {
13983
13984 /* Node is not null. */
13985
13986 /* Determine the address family. */
13987 addr_family = AF_INET;
13988
13989 for(i = 0; i < _nx_bsd_string_length((CHAR *)node); i++)
13990 {
13991 if(node[i] == ':')
13992 {
13993 /* There is a colon, so it is an IPv6 address. */
13994 addr_family = AF_INET6;
13995 break;
13996 }
13997 }
13998
13999 /* Initialize to 0, default to pton failing. */
14000 pton_flag = 0;
14001
14002 if(addr_family == AF_INET)
14003 {
14004
14005 /* Convert node from a string presentation to a numeric address. */
14006 if(nx_bsd_inet_pton(addr_family, node, &(nx_bsd_ipv4_addr_buffer[0])) == 1)
14007 {
14008 /* pton has successful completion. */
14009 pton_flag = 1;
14010
14011 /* Check if the address and the specified family match. */
14012 if((hints -> ai_family != AF_INET) && (hints -> ai_family != AF_UNSPEC))
14013 return EAI_ADDRFAMILY;
14014
14015 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv4_addr_buffer[0]);
14016 ipv4_addr_count = 1;
14017 }
14018 }
14019 else
14020 {
14021
14022 /* Convert node from a string presentation to a numeric address. */
14023 if(nx_bsd_inet_pton(addr_family, node, &(nx_bsd_ipv6_addr_buffer[0])) == 1)
14024 {
14025 /* pton completed successfully. */
14026 pton_flag = 1;
14027
14028 /* Check is the address and the specified family matches. */
14029 if((hints -> ai_family != AF_INET6) && (hints -> ai_family != AF_UNSPEC))
14030 return EAI_ADDRFAMILY;
14031
14032 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv6_addr_buffer[0]);
14033 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv6_addr_buffer[1]);
14034 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv6_addr_buffer[2]);
14035 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv6_addr_buffer[3]);
14036 ipv6_addr_count = 1;
14037 }
14038 }
14039
14040 if(pton_flag == 1)
14041 {
14042
14043 /* pton completed successfull. Host (node) is an address string. */
14044
14045 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
14046 /* DNS supports extended services including Canonical name queries. */
14047 if((hints -> ai_flags & AI_CANONNAME) && !(hints -> ai_flags & AI_NUMERICHOST))
14048 {
14049
14050 /* Allocate a block for canonical name. */
14051 status = tx_block_allocate(&nx_bsd_cname_block_pool, (VOID *) &cname_buffer, NX_BSD_TIMEOUT);
14052
14053 /* Check for error status. */
14054 if (status != TX_SUCCESS)
14055 {
14056 /* Set the error. */
14057 nx_bsd_set_errno(ENOMEM);
14058
14059 /* Error getting NetX socket memory. */
14060 NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
14061
14062 /* Return memory allocation error. */
14063 return(EAI_MEMORY);
14064 }
14065
14066 /* Verify buffer size. */
14067 if (_nx_bsd_string_length((CHAR *)node) > NX_DNS_NAME_MAX)
14068 return(EAI_OVERFLOW);
14069
14070 memcpy(cname_buffer, node, _nx_bsd_string_length((CHAR *)node)); /* Use case of memcpy is verified. */
14071
14072 }
14073 #endif /* NX_BSD_ENABLE_DNS && NX_DNS_ENABLE_EXTENDED_RR_TYPES */
14074
14075 }
14076 else
14077 {
14078
14079 /* Presentation to numeric format fails, node may be a hostname, not a numeric IP address. */
14080
14081 /* Check if numeric host flag is set. */
14082 if(hints -> ai_flags & AI_NUMERICHOST)
14083 return EAI_NONAME;
14084
14085 #ifdef NX_BSD_ENABLE_DNS
14086 if(hints -> ai_family == AF_INET)
14087 {
14088
14089 /* Get IPv4 address by hostname. */
14090 status = nx_dns_ipv4_address_by_name_get(_nx_dns_instance_ptr, (UCHAR *)node, &nx_bsd_ipv4_addr_buffer[0],
14091 NX_BSD_IPV4_ADDR_PER_HOST * 4, &ipv4_addr_count, NX_BSD_TIMEOUT);
14092
14093 if(status != NX_SUCCESS)
14094 {
14095
14096 /* Just return EAI_FAIL, because we can't discriminate between DNS FAIL and the situation where the specified
14097 network host exists but does not have any network addresses defined. It would be better to return EAI_FAIL
14098 for DNS FAIL, and EAI_NODATA for the latter situation. */
14099 return EAI_FAIL;
14100 }
14101 }
14102 else if(hints -> ai_family == AF_INET6)
14103 {
14104
14105 /* Get IPv6 address by hostname. */
14106 status = nxd_dns_ipv6_address_by_name_get(_nx_dns_instance_ptr, (UCHAR *)node, &nx_bsd_ipv6_addr_buffer[0],
14107 NX_BSD_IPV6_ADDR_PER_HOST * 16, &ipv6_addr_count, NX_BSD_TIMEOUT);
14108
14109 if(status != NX_SUCCESS)
14110 {
14111 /* Just return EAI_FAIL, because we can't discriminate between DNS FAIL and the situation where the specified
14112 network host exists but does not have any network addresses defined. It would be better to return EAI_FAIL
14113 for DNS FAIL, and EAI_NODATA for the latter situation. */
14114 return EAI_FAIL;
14115 }
14116 }
14117 else
14118 {
14119
14120 /* Address family is not specified. Query for both IPv4 and IPv6 address. */
14121
14122 /* Get IPv4 address by hostname. */
14123 status = nx_dns_ipv4_address_by_name_get(_nx_dns_instance_ptr, (UCHAR *)node, &nx_bsd_ipv4_addr_buffer[0],
14124 NX_BSD_IPV4_ADDR_PER_HOST * 4, &ipv4_addr_count, NX_BSD_TIMEOUT);
14125
14126 /* Get IPv6 address by hostname. */
14127 status2 = nxd_dns_ipv6_address_by_name_get(_nx_dns_instance_ptr, (UCHAR *)node, &nx_bsd_ipv6_addr_buffer[0],
14128 NX_BSD_IPV6_ADDR_PER_HOST * 16, &ipv6_addr_count, NX_BSD_TIMEOUT);
14129
14130 if((status != NX_SUCCESS) && status2 != NX_SUCCESS)
14131 {
14132 /* Just return EAI_FAIL, because we can't discriminate between DNS FAIL and the situation that the specified
14133 network host exists, but does not have any network addresses defined. It would be better to return EAI_FAIL
14134 for DNS FAIL, and EAI_NODATA for the latter situation. */
14135 return EAI_FAIL;
14136 }
14137 }
14138
14139 if(hints -> ai_flags & AI_CANONNAME)
14140 {
14141
14142 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14143 /* Allocate a block for canonical name. */
14144 status = tx_block_allocate(&nx_bsd_cname_block_pool, (VOID *) &cname_buffer, NX_BSD_TIMEOUT);
14145
14146 /* Check for error status. */
14147 if (status != TX_SUCCESS)
14148 {
14149 /* Set the error. */
14150 set_errno(ENOMEM);
14151
14152 /* Error getting NetX socket memory. */
14153 NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
14154
14155 /* Return memory allocation error. */
14156 return(EAI_MEMORY);
14157 }
14158
14159 status = nx_dns_cname_get(_nx_dns_instance_ptr, (UCHAR *)node, cname_buffer,
14160 nx_bsd_cname_block_pool.tx_block_pool_block_size, NX_BSD_TIMEOUT);
14161 if(status != NX_SUCCESS)
14162 {
14163
14164 /* Verify buffer size. */
14165 if (_nx_bsd_string_length((CHAR *)node) > NX_DNS_NAME_MAX)
14166 return(EAI_OVERFLOW);
14167
14168 memcpy(cname_buffer, node, _nx_bsd_string_length((CHAR *)node)); /* Use case of memcpy is verified. */
14169 }
14170
14171 #else
14172 cname_buffer = (UCHAR *)node;
14173 #endif
14174 }
14175 #else
14176 return EAI_FAIL;
14177 #endif
14178
14179 }
14180 }
14181 else
14182 {
14183
14184 /* Node is null. */
14185 if(hints -> ai_flags & AI_PASSIVE)
14186 {
14187 /* The caller wiil use the socket for a passive open. */
14188
14189 nx_bsd_ipv4_addr_buffer[0] = INADDR_ANY;
14190
14191 nx_bsd_ipv6_addr_buffer[0] = 0;
14192 nx_bsd_ipv6_addr_buffer[1] = 0;
14193 nx_bsd_ipv6_addr_buffer[2] = 0;
14194 nx_bsd_ipv6_addr_buffer[3] = 0;
14195 }
14196 else
14197 {
14198
14199 /* Localhost address. */
14200 nx_bsd_ipv4_addr_buffer[0] = 0x7F000001;
14201
14202 nx_bsd_ipv6_addr_buffer[0] = 0;
14203 nx_bsd_ipv6_addr_buffer[1] = 0;
14204 nx_bsd_ipv6_addr_buffer[2] = 0;
14205 nx_bsd_ipv6_addr_buffer[3] = 1;
14206 }
14207
14208 if (hints -> ai_family != AF_INET6)
14209 {
14210 ipv4_addr_count = 1;
14211 }
14212 ipv6_addr_count = 1;
14213 }
14214
14215
14216 for(i = 0; i < ipv4_addr_count + ipv6_addr_count; i++)
14217 {
14218
14219 /* Allocate a block for ipv4 address. */
14220 status = tx_block_allocate(&nx_bsd_addrinfo_block_pool, (VOID *) &sockaddr_ptr, NX_BSD_TIMEOUT);
14221
14222 /* Check for error status. */
14223 if (status != TX_SUCCESS)
14224 {
14225
14226 /* Set the error. */
14227 nx_bsd_set_errno(ENOMEM);
14228
14229 /* If head is not null, free the memory. */
14230 if(addrinfo_head_ptr)
14231 nx_bsd_freeaddrinfo(addrinfo_head_ptr);
14232
14233 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14234 if(hints -> ai_flags & AI_CANONNAME)
14235 tx_block_release((VOID *)cname_buffer);
14236 #endif
14237
14238 /* Error getting NetX socket memory. */
14239 NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
14240
14241 /* Return memory allocation error. */
14242 return(EAI_MEMORY);
14243 }
14244
14245 /* Clear the memory. */
14246 memset((VOID*)sockaddr_ptr, 0, sizeof(struct nx_bsd_addrinfo));
14247
14248 if(i < ipv4_addr_count)
14249 {
14250
14251 /* Process IPv4 address. */
14252 ((struct nx_bsd_sockaddr_in*)sockaddr_ptr) -> sin_family = AF_INET;
14253 ((struct nx_bsd_sockaddr_in*)sockaddr_ptr) -> sin_port = (USHORT)port;
14254 ((struct nx_bsd_sockaddr_in*)sockaddr_ptr) -> sin_addr.s_addr = nx_bsd_ipv4_addr_buffer[i];
14255
14256 NX_CHANGE_ULONG_ENDIAN(((struct nx_bsd_sockaddr_in*)sockaddr_ptr) -> sin_addr.s_addr);
14257 }
14258 else
14259 {
14260
14261 /* Process IPv6 address. */
14262 ((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_family = AF_INET6;
14263 ((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_port = (USHORT)port;
14264 memcpy(&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr), &nx_bsd_ipv6_addr_buffer[(i - ipv4_addr_count)*4], 16); /* Use case of memcpy is verified. */
14265
14266 NX_CHANGE_ULONG_ENDIAN(*(ULONG*)&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr.s6_addr32[0]));
14267 NX_CHANGE_ULONG_ENDIAN(*(ULONG*)&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr.s6_addr32[1]));
14268 NX_CHANGE_ULONG_ENDIAN(*(ULONG*)&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr.s6_addr32[2]));
14269 NX_CHANGE_ULONG_ENDIAN(*(ULONG*)&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr.s6_addr32[3]));
14270
14271 }
14272
14273 for(j = 0; j < match_service_count; j++)
14274 {
14275
14276 /* Allocate a block from the addrinfo block pool. */
14277 status = tx_block_allocate(&nx_bsd_addrinfo_block_pool, (VOID *) &addrinfo_cur_ptr, NX_BSD_TIMEOUT);
14278
14279 /* Check for error status. */
14280 if (status != TX_SUCCESS)
14281 {
14282
14283 /* Set the error. */
14284 nx_bsd_set_errno(ENOMEM);
14285
14286 /* If head is not null, free the memory. */
14287 if(addrinfo_head_ptr)
14288 nx_bsd_freeaddrinfo(addrinfo_head_ptr);
14289
14290 tx_block_release((VOID *)sockaddr_ptr);
14291
14292 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14293 if(hints -> ai_flags & AI_CANONNAME)
14294 tx_block_release((VOID *)cname_buffer);
14295 #endif
14296
14297 /* Error getting NetX socket memory. */
14298 NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
14299
14300 /* Return memory allocation error. */
14301 return(EAI_MEMORY);
14302 }
14303
14304 /* Clear the socket memory. */
14305 memset((VOID*)addrinfo_cur_ptr, 0, sizeof(struct nx_bsd_addrinfo));
14306
14307 if(i < ipv4_addr_count)
14308 {
14309
14310 /* IPv4 */
14311 addrinfo_cur_ptr -> ai_family = AF_INET;
14312 addrinfo_cur_ptr -> ai_addrlen = sizeof(struct nx_bsd_sockaddr_in);
14313 }
14314 else
14315 {
14316
14317 /* IPv6 */
14318 addrinfo_cur_ptr -> ai_family = AF_INET6;
14319 addrinfo_cur_ptr -> ai_addrlen = sizeof(struct nx_bsd_sockaddr_in6);
14320 }
14321
14322 addrinfo_cur_ptr -> ai_socktype = (INT)(match_service_socktype[j]);
14323 addrinfo_cur_ptr -> ai_protocol = (INT)(match_service_protocol[j]);
14324 addrinfo_cur_ptr -> ai_addr = sockaddr_ptr;
14325 if((i == 0) && (j == 0) && (hints -> ai_flags & AI_CANONNAME))
14326 addrinfo_cur_ptr -> ai_canonname = (CHAR *)cname_buffer;
14327 else
14328 addrinfo_cur_ptr -> ai_canonname = NX_NULL;
14329 addrinfo_cur_ptr -> ai_next = NX_NULL;
14330
14331 /* Make a list. */
14332 if(addrinfo_head_ptr == NX_NULL)
14333 addrinfo_head_ptr = addrinfo_cur_ptr;
14334 else
14335 addrinfo_tail_ptr -> ai_next = addrinfo_cur_ptr;
14336
14337 addrinfo_tail_ptr = addrinfo_cur_ptr;
14338
14339 }
14340 }
14341
14342 *res = addrinfo_head_ptr;
14343
14344 return 0;
14345 }
14346
14347 /**************************************************************************/
14348 /* */
14349 /* FUNCTION RELEASE */
14350 /* */
14351 /* freeaddrinfo PORTABLE C */
14352 /* 6.3.0 */
14353 /* AUTHOR */
14354 /* */
14355 /* Yuxin Zhou, Microsoft Corporation */
14356 /* */
14357 /* DESCRIPTION */
14358 /* */
14359 /* This function releases the memory allocated by getaddrinfo. */
14360 /* */
14361 /* INPUT */
14362 /* */
14363 /* res Pointer to a addrinfo struct */
14364 /* */
14365 /* OUTPUT */
14366 /* */
14367 /* None */
14368 /* */
14369 /* CALLS */
14370 /* */
14371 /* tx_block_release Release socket memory */
14372 /* */
14373 /* CALLED BY */
14374 /* */
14375 /* Application Code */
14376 /* */
14377 /* RELEASE HISTORY */
14378 /* */
14379 /* DATE NAME DESCRIPTION */
14380 /* */
14381 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14382 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
14383 /* resulting in version 6.1 */
14384 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
14385 /* used new API/structs naming,*/
14386 /* resulting in version 6.3.0 */
14387 /* */
14388 /**************************************************************************/
nx_bsd_freeaddrinfo(struct nx_bsd_addrinfo * res)14389 VOID nx_bsd_freeaddrinfo(struct nx_bsd_addrinfo *res)
14390 {
14391
14392 struct nx_bsd_addrinfo *next_addrinfo;
14393 struct nx_bsd_sockaddr *ai_addr_ptr = NX_NULL;
14394 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14395 CHAR *ai_canonname_ptr = NX_NULL;
14396 #endif
14397
14398 while(res)
14399 {
14400 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14401 if((res -> ai_canonname) &&
14402 (res -> ai_canonname != ai_canonname_ptr))
14403 {
14404
14405 /* Release the CNAME memory. */
14406 tx_block_release((VOID *)res -> ai_canonname);
14407
14408 ai_canonname_ptr = res -> ai_canonname;
14409 }
14410 #endif
14411 if((res -> ai_addr) &&
14412 (res -> ai_addr != ai_addr_ptr))
14413 {
14414
14415 /* Release the address memory. */
14416 tx_block_release((VOID *)res -> ai_addr);
14417
14418 ai_addr_ptr = res -> ai_addr;
14419 }
14420
14421 /* Move next. */
14422 next_addrinfo = res -> ai_next;
14423
14424 /* Release the addrinfo memory. */
14425 tx_block_release((VOID *)res);
14426
14427 res = next_addrinfo;
14428 }
14429 }
14430
14431
14432 /**************************************************************************/
14433 /* */
14434 /* FUNCTION RELEASE */
14435 /* */
14436 /* bsd_string_to_number PORTABLE C */
14437 /* 6.1 */
14438 /* AUTHOR */
14439 /* */
14440 /* Yuxin Zhou, Microsoft Corporation */
14441 /* */
14442 /* DESCRIPTION */
14443 /* */
14444 /* This function converts string to number. */
14445 /* */
14446 /* INPUT */
14447 /* */
14448 /* string Pointer to a string */
14449 /* number Pointer to a number */
14450 /* */
14451 /* OUTPUT */
14452 /* */
14453 /* status */
14454 /* */
14455 /* CALLS */
14456 /* */
14457 /* nx_bsd_isdigit Indicate char is a number */
14458 /* */
14459 /* CALLED BY */
14460 /* */
14461 /* Application Code */
14462 /* */
14463 /* RELEASE HISTORY */
14464 /* */
14465 /* DATE NAME DESCRIPTION */
14466 /* */
14467 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14468 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
14469 /* resulting in version 6.1 */
14470 /* */
14471 /**************************************************************************/
bsd_string_to_number(const CHAR * string,UINT * number)14472 static INT bsd_string_to_number(const CHAR *string, UINT *number)
14473 {
14474
14475 /* Initialize the numbet to zero. */
14476 *number = 0;
14477
14478 while(*string != '\0')
14479 {
14480
14481 /* Check if the current character is a digit character. */
14482 if(!nx_bsd_isdigit((UCHAR)(*string)))
14483 return NX_SOC_ERROR;
14484
14485 *number = (*number * 10) + (UINT)(*string - 0x30);
14486
14487 string++;
14488 }
14489
14490 return NX_SOC_OK;
14491 }
14492
14493 /**************************************************************************/
14494 /* */
14495 /* FUNCTION RELEASE */
14496 /* */
14497 /* getnameinfo PORTABLE C */
14498 /* 6.3.0 */
14499 /* AUTHOR */
14500 /* */
14501 /* Yuxin Zhou, Microsoft Corporation */
14502 /* */
14503 /* DESCRIPTION */
14504 /* */
14505 /* This function converts a socket address to a corresponding host and */
14506 /* service. */
14507 /* */
14508 /* INPUT */
14509 /* */
14510 /* sa Pointer to a generic socket */
14511 /* address structure */
14512 /* salen Length of sa structure */
14513 /* host Pointer to caller-allocated */
14514 /* buffer for hostname */
14515 /* hostlen Host buffer size */
14516 /* serv Pointer to caller-allocated */
14517 /* buffer for service name */
14518 /* servlen Service buffer size */
14519 /* */
14520 /* OUTPUT */
14521 /* */
14522 /* status 0 if OK, nonzero on errors */
14523 /* */
14524 /* CALLS */
14525 /* */
14526 /* nx_dns_host_by_address_get Get hostname by IPv4 address */
14527 /* nxd_dns_host_by_address_get Get hostname by IPv6 address */
14528 /* */
14529 /* CALLED BY */
14530 /* */
14531 /* Application Code */
14532 /* */
14533 /* RELEASE HISTORY */
14534 /* */
14535 /* DATE NAME DESCRIPTION */
14536 /* */
14537 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14538 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
14539 /* verified memcpy use cases, */
14540 /* resulting in version 6.1 */
14541 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
14542 /* used new API/structs naming,*/
14543 /* resulting in version 6.3.0 */
14544 /* */
14545 /**************************************************************************/
nx_bsd_getnameinfo(const struct nx_bsd_sockaddr * sa,nx_bsd_socklen_t salen,char * host,size_t hostlen,char * serv,size_t servlen,int flags)14546 INT nx_bsd_getnameinfo(const struct nx_bsd_sockaddr *sa, nx_bsd_socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
14547 {
14548
14549 UINT i = 0;
14550 /* Flag used to identify whether host/service is numeric, 0 no, 1 yes. */
14551 UINT numeric_flag;
14552 USHORT *temp;
14553 #ifdef NX_BSD_ENABLE_DNS
14554 UINT status;
14555 #ifdef FEATURE_NX_IPV6
14556 NXD_ADDRESS nxd_ipv6_addr;
14557 #endif
14558 #endif
14559 const CHAR *rt_ptr;
14560
14561 if(!sa)
14562 {
14563
14564 /* sa is NULL. */
14565 return EAI_FAMILY;
14566 }
14567 else
14568 {
14569 if((sa -> sa_family != AF_INET) &&
14570 (sa -> sa_family != AF_INET6))
14571 {
14572
14573 /* sa isn't NULL, but family type is invalid. */
14574 return EAI_FAMILY;
14575 }
14576 else if((sa -> sa_family == AF_INET && salen != sizeof(struct nx_bsd_sockaddr_in)) ||
14577 (sa -> sa_family == AF_INET6 && salen != sizeof(struct nx_bsd_sockaddr_in6)))
14578 {
14579
14580 /* Address length is invalid. */
14581 return EAI_FAMILY;
14582 }
14583 }
14584
14585 /* Both host and service null are invalid */
14586 if((host == NX_NULL) && (serv == NX_NULL) && ((flags & NI_NAMEREQD) == 0))
14587 return EAI_NONAME;
14588
14589 if(serv && servlen > 0)
14590 {
14591 numeric_flag = 1;
14592
14593 /* If NUMERICSERV bit is set, set to 1. */
14594 if(flags & NI_NUMERICSERV)
14595 {
14596 numeric_flag = 1;
14597 }
14598 else if(flags & NI_DGRAM)
14599 {
14600 /* Socket type must be SOCK_DGRAM. */
14601
14602 for(i = 0; i < _nx_bsd_serv_list_len; i++)
14603 {
14604 temp = (USHORT *)(sa -> sa_data);
14605 if((_nx_bsd_serv_list_ptr[i].service_port == *temp) &&
14606 (_nx_bsd_serv_list_ptr[i].service_socktype == SOCK_DGRAM))
14607 {
14608
14609 /* Found a matched service, set numeric flag to 0. */
14610 numeric_flag = 0;
14611 break;
14612 }
14613 }
14614 }
14615 else
14616 {
14617
14618 /* Socket type is SOCK_STREAM. */
14619 for(i = 0; i < _nx_bsd_serv_list_len; i++)
14620 {
14621 temp = (USHORT *)(sa -> sa_data);
14622 if((_nx_bsd_serv_list_ptr[i].service_port == *temp) &&
14623 (_nx_bsd_serv_list_ptr[i].service_socktype == SOCK_STREAM))
14624 {
14625
14626 /* Found a matched service, set numeric flag to 0. */
14627 numeric_flag = 0;
14628 break;
14629 }
14630 }
14631 }
14632
14633 if(numeric_flag)
14634 {
14635
14636 /* Service is numeric, copy the service port. Then convert host byte order to network byte order. */
14637 temp = (USHORT *)(sa -> sa_data);
14638 if(bsd_number_convert(htons(*temp), (CHAR *)serv, servlen, 10) == 0)
14639 return EAI_OVERFLOW;
14640 }
14641 else
14642 {
14643
14644 /* Service isn't numeric, copy the service name. */
14645 if(_nx_bsd_string_length(_nx_bsd_serv_list_ptr[i].service_name) > servlen)
14646 return EAI_OVERFLOW;
14647
14648 memcpy(serv, _nx_bsd_serv_list_ptr[i].service_name, /* Use case of memcpy is verified. */
14649 _nx_bsd_string_length(_nx_bsd_serv_list_ptr[i].service_name));
14650 }
14651 }
14652
14653 if(host && hostlen > 0)
14654 {
14655 numeric_flag = 1;
14656
14657 /* If NUMERIC bit is set, set flag to 1. */
14658 if(flags & NI_NUMERICHOST)
14659 numeric_flag = 1;
14660 else
14661 {
14662
14663 #ifdef NX_BSD_ENABLE_DNS
14664 if(sa -> sa_family == AF_INET)
14665 {
14666
14667 #ifndef NX_DISABLE_IPV4
14668 /* Get host name by IPv4 address via DNS. */
14669 status = nx_dns_host_by_address_get(_nx_dns_instance_ptr, ntohl(((struct nx_bsd_sockaddr_in *)sa) -> sin_addr.s_addr),
14670 (UCHAR *)host, hostlen, NX_BSD_TIMEOUT);
14671 #else
14672 status = NX_DNS_NO_SERVER;
14673 #endif /* NX_DISABLE_IPV4 */
14674 }
14675 else
14676 {
14677 #ifdef FEATURE_NX_IPV6
14678 /* copy data from sockaddr structure to NXD_ADDRESS structure. */
14679 nxd_ipv6_addr.nxd_ip_version = NX_IP_VERSION_V6;
14680 nxd_ipv6_addr.nxd_ip_address.v6[0] = ntohl(((struct nx_bsd_sockaddr_in6 *)sa) -> sin6_addr.s6_addr32[0]);
14681 nxd_ipv6_addr.nxd_ip_address.v6[1] = ntohl(((struct nx_bsd_sockaddr_in6 *)sa) -> sin6_addr.s6_addr32[1]);
14682 nxd_ipv6_addr.nxd_ip_address.v6[2] = ntohl(((struct nx_bsd_sockaddr_in6 *)sa) -> sin6_addr.s6_addr32[2]);
14683 nxd_ipv6_addr.nxd_ip_address.v6[3] = ntohl(((struct nx_bsd_sockaddr_in6 *)sa) -> sin6_addr.s6_addr32[3]);
14684
14685 /* Get host name by IPv6 address via DNS. */
14686 status = nxd_dns_host_by_address_get(_nx_dns_instance_ptr, &nxd_ipv6_addr,
14687 (UCHAR *) host, hostlen, NX_BSD_TIMEOUT);
14688 #else
14689 status = NX_DNS_NO_SERVER;
14690 #endif
14691 }
14692
14693
14694 if(status == NX_DNS_SIZE_ERROR)
14695 return EAI_OVERFLOW;
14696 else if(status != NX_SUCCESS)
14697 {
14698
14699 /* DNS query fails. */
14700 if(flags & NI_NAMEREQD)
14701 return EAI_NONAME;
14702 }
14703 else
14704 {
14705
14706 /* DNS query succeeds. */
14707 numeric_flag = 0;
14708 }
14709 #else
14710 if(flags & NI_NAMEREQD)
14711 return EAI_NONAME;
14712 #endif
14713 }
14714
14715 if(numeric_flag)
14716 {
14717
14718 /* Host must be numeric string. Convert IP address from numeric to presentation. */
14719 if(sa -> sa_family == AF_INET)
14720 rt_ptr = nx_bsd_inet_ntop(AF_INET, &((struct nx_bsd_sockaddr_in*)sa) -> sin_addr, (CHAR *)host, hostlen);
14721 else
14722 rt_ptr = nx_bsd_inet_ntop(AF_INET6, &((struct nx_bsd_sockaddr_in6*)sa) -> sin6_addr, (CHAR *)host, hostlen);
14723
14724 if(!rt_ptr)
14725 return EAI_OVERFLOW;
14726 }
14727
14728 }
14729
14730 return 0;
14731 }
14732
14733 /**************************************************************************/
14734 /* */
14735 /* FUNCTION RELEASE */
14736 /* */
14737 /* nx_bsd_set_service_list PORTABLE C */
14738 /* 6.1 */
14739 /* AUTHOR */
14740 /* */
14741 /* Yuxin Zhou, Microsoft Corporation */
14742 /* */
14743 /* DESCRIPTION */
14744 /* */
14745 /* This function lets user set the service list used by getaddrinfo */
14746 /* */
14747 /* INPUT */
14748 /* */
14749 /* serv_list_ptr Pointer to a service list */
14750 /* serv_list_len Service list length */
14751 /* */
14752 /* OUTPUT */
14753 /* */
14754 /* None */
14755 /* */
14756 /* CALLS */
14757 /* */
14758 /* None */
14759 /* */
14760 /* CALLED BY */
14761 /* */
14762 /* Application Code */
14763 /* */
14764 /* RELEASE HISTORY */
14765 /* */
14766 /* DATE NAME DESCRIPTION */
14767 /* */
14768 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14769 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
14770 /* resulting in version 6.1 */
14771 /* */
14772 /**************************************************************************/
nx_bsd_set_service_list(struct NX_BSD_SERVICE_LIST * serv_list_ptr,ULONG serv_list_len)14773 VOID nx_bsd_set_service_list(struct NX_BSD_SERVICE_LIST *serv_list_ptr, ULONG serv_list_len)
14774 {
14775 _nx_bsd_serv_list_ptr = serv_list_ptr;
14776 _nx_bsd_serv_list_len = serv_list_len;
14777 }
14778
14779
14780 /**************************************************************************/
14781 /* */
14782 /* FUNCTION RELEASE */
14783 /* */
14784 /* _nx_bsd_string_length PORTABLE C */
14785 /* 6.1 */
14786 /* AUTHOR */
14787 /* */
14788 /* Yuxin Zhou, Microsoft Corporation */
14789 /* */
14790 /* DESCRIPTION */
14791 /* */
14792 /* This function returns the length of string. */
14793 /* */
14794 /* INPUT */
14795 /* */
14796 /* string Pointer to a string */
14797 /* */
14798 /* OUTPUT */
14799 /* */
14800 /* ULONG String length */
14801 /* */
14802 /* CALLS */
14803 /* */
14804 /* None */
14805 /* */
14806 /* CALLED BY */
14807 /* */
14808 /* NetX Duo BSD Layer Source Code */
14809 /* */
14810 /* RELEASE HISTORY */
14811 /* */
14812 /* DATE NAME DESCRIPTION */
14813 /* */
14814 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14815 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
14816 /* resulting in version 6.1 */
14817 /* */
14818 /**************************************************************************/
_nx_bsd_string_length(CHAR * string)14819 static ULONG _nx_bsd_string_length(CHAR * string)
14820 {
14821 int length = 0;
14822
14823 while(*string != '\0')
14824 {
14825 length++;
14826 string++;
14827 }
14828
14829 return((ULONG)length);
14830
14831 }
14832
14833
14834 /**************************************************************************/
14835 /* */
14836 /* FUNCTION RELEASE */
14837 /* */
14838 /* _nx_bsd_fast_periodic_timer_entry PORTABLE C */
14839 /* 6.1 */
14840 /* AUTHOR */
14841 /* */
14842 /* Yuxin Zhou, Microsoft Corporation */
14843 /* */
14844 /* DESCRIPTION */
14845 /* */
14846 /* This function handles BSD system clock. When the timer expires, the */
14847 /* BSD system clock is updated and then default IP fast periodic entry */
14848 /* routine is invoked. */
14849 /* */
14850 /* INPUT */
14851 /* */
14852 /* id Argument of default timer entry*/
14853 /* */
14854 /* OUTPUT */
14855 /* */
14856 /* None */
14857 /* */
14858 /* CALLS */
14859 /* */
14860 /* None */
14861 /* */
14862 /* CALLED BY */
14863 /* */
14864 /* None */
14865 /* */
14866 /* RELEASE HISTORY */
14867 /* */
14868 /* DATE NAME DESCRIPTION */
14869 /* */
14870 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14871 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
14872 /* resulting in version 6.1 */
14873 /* */
14874 /**************************************************************************/
_nx_bsd_fast_periodic_timer_entry(ULONG id)14875 static VOID _nx_bsd_fast_periodic_timer_entry(ULONG id)
14876 {
14877
14878 /* Update the BSD system clock. */
14879 nx_bsd_system_clock += nx_bsd_timer_rate;
14880
14881 /* Call default IP fast periodic timer entry. */
14882 nx_bsd_ip_fast_periodic_timer_entry(id);
14883 }
14884
14885
14886 /**************************************************************************/
14887 /* */
14888 /* FUNCTION RELEASE */
14889 /* */
14890 /* poll PORTABLE C */
14891 /* 6.3.0 */
14892 /* AUTHOR */
14893 /* */
14894 /* Chaoqiong Xiao, Microsoft Corporation */
14895 /* */
14896 /* DESCRIPTION */
14897 /* */
14898 /* This function allows for list of sockets to be checked for incoming */
14899 /* events. */
14900 /* */
14901 /* Before invoked, each item inside fds array should be initialized, */
14902 /* pollfd::fd must be the descriptor ID to check and pollfd::events */
14903 /* must be the events (bits) to check. */
14904 /* */
14905 /* Returned, the pollfd::revents of each item is updated, to indicate */
14906 /* if the checked events happen. */
14907 /* */
14908 /* The event (bit) currently supported: */
14909 /* - POLLIN : checking socket read FD */
14910 /* - POLLOUT: checking socket write FD */
14911 /* - POLLPRI: checking socket exception FD */
14912 /* */
14913 /* NOTE: ****** When select returns NX_SOC_ERROR it won't update */
14914 /* the fds descriptor. */
14915 /* */
14916 /* INPUT */
14917 /* */
14918 /* fds Socket descriptor list to poll */
14919 /* and report actual status */
14920 /* nfds Number of socket descriptors */
14921 /* timeOut Timeout in microseconds, set */
14922 /* to below 0 to wait infinitely */
14923 /* */
14924 /* OUTPUT */
14925 /* */
14926 /* NX_SUCCESS Descriptors check ends */
14927 /* (successful completion) */
14928 /* NX_SOC_ERROR (-1) Error occured */
14929 /* */
14930 /* CALLS */
14931 /* */
14932 /* FD_ZERO Clear a socket ready list */
14933 /* FD_ISSET Check a socket is ready */
14934 /* FD_SET Set a socket */
14935 /* select Perform checks, see select() */
14936 /* set_errno Set the error code */
14937 /* */
14938 /* CALLED BY */
14939 /* */
14940 /* Application Code */
14941 /* */
14942 /* RELEASE HISTORY */
14943 /* */
14944 /* DATE NAME DESCRIPTION */
14945 /* */
14946 /* 10-31-2023 Chaoqiong Xiao Initial Version 6.3.0 */
14947 /* */
14948 /**************************************************************************/
nx_bsd_poll(struct nx_bsd_pollfd * fds,ULONG nfds,INT timeout)14949 INT nx_bsd_poll(struct nx_bsd_pollfd *fds, ULONG nfds, INT timeout)
14950 {
14951 nx_bsd_fd_set read_fds;
14952 nx_bsd_fd_set write_fds;
14953 nx_bsd_fd_set except_fds;
14954 struct nx_bsd_timeval stime;
14955 struct nx_bsd_timeval *ptime;
14956 INT n_ready_fds;
14957 INT max_fd;
14958 ULONG i;
14959 struct nx_bsd_pollfd *poll_fd;
14960
14961 /* Check input parameter. */
14962 if (fds == NX_NULL)
14963 {
14964 nx_bsd_set_errno(EFAULT);
14965 return(NX_SOC_ERROR);
14966 }
14967 if (nfds == 0)
14968 {
14969 nx_bsd_set_errno(EFAULT);
14970 return(NX_SOC_ERROR);
14971 }
14972
14973 /* Initialize local FDs. */
14974 NX_BSD_FD_ZERO(&read_fds);
14975 NX_BSD_FD_ZERO(&write_fds);
14976 NX_BSD_FD_ZERO(&except_fds);
14977
14978 /* Map the poll() FD to select() FDs. */
14979 max_fd = 0;
14980 for(i = 0; i < nfds; i ++)
14981 {
14982 poll_fd = &fds[i];
14983
14984 /* Skip bad FDs. */
14985 if (poll_fd -> fd < 0)
14986 continue;
14987
14988 /* POLLIN. */
14989 if (poll_fd -> events & POLLIN)
14990 {
14991 NX_BSD_FD_SET(poll_fd -> fd, &read_fds);
14992 }
14993
14994 /* POLLOUT. */
14995 if (poll_fd -> events & POLLOUT)
14996 {
14997 NX_BSD_FD_SET(poll_fd -> fd, &write_fds);
14998 }
14999
15000 /* POLLPRI. */
15001 if (poll_fd -> events & POLLPRI)
15002 {
15003 NX_BSD_FD_SET(poll_fd -> fd, &except_fds);
15004 }
15005
15006 /* Update max FD. */
15007 if (poll_fd -> fd > max_fd)
15008 max_fd = poll_fd -> fd;
15009 }
15010
15011 /* Map the select() timeout. */
15012 if (timeout < 0)
15013 {
15014
15015 /* select() wait infinitely. */
15016 ptime = NX_NULL;
15017 }
15018 else
15019 {
15020
15021 /* select() uses timeval option. */
15022 ptime = &stime;
15023
15024 if (timeout == 0)
15025 {
15026
15027 /* select() no wait. */
15028 ptime -> tv_sec = 0;
15029 ptime -> tv_usec = 0;
15030 }
15031 else
15032 {
15033
15034 /* select() wait specific time in ms. */
15035 ptime -> tv_sec = (timeout / 1000);
15036 ptime -> tv_usec = (timeout % 1000);
15037 }
15038
15039 }
15040
15041 /* Invoke select(). */
15042 n_ready_fds = nx_bsd_select(max_fd + 1, &read_fds, &write_fds, &except_fds, ptime);
15043
15044 /* Parse result events if FDs updated. */
15045 if (n_ready_fds)
15046 {
15047
15048 for (i = 0; i < nfds; i ++)
15049 {
15050 poll_fd = &fds[i];
15051
15052 /* Skip bad FDs. */
15053 if (poll_fd -> fd < 0)
15054 continue;
15055
15056 /* Exceptions. */
15057 if (NX_BSD_FD_ISSET(poll_fd -> fd, &except_fds))
15058 poll_fd -> revents |= POLLPRI;
15059
15060 else
15061 {
15062
15063 /* Inputs. */
15064 if (NX_BSD_FD_ISSET(poll_fd -> fd, &read_fds))
15065 poll_fd -> revents |= POLLIN;
15066 }
15067
15068 /* Outputs. */
15069 if (NX_BSD_FD_ISSET(poll_fd -> fd, &write_fds))
15070 poll_fd -> revents |= POLLOUT;
15071 }
15072 }
15073
15074 return(n_ready_fds);
15075 }
15076