1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11 /**************************************************************************/
12 /**************************************************************************/
13 /** */
14 /** BSD 4.3 Socket API Compatible Interface to NetX Duo */
15 /** */
16 /**************************************************************************/
17 /**************************************************************************/
18
19
20 /* Include necessary files. */
21 #include "nx_api.h"
22 #include "nx_packet.h"
23 #include "nx_tcp.h"
24 #include "nx_ip.h"
25
26 #include "nx_ipv6.h"
27 #include "nx_ipv4.h"
28 #include "nxd_bsd.h"
29 #include "nx_link.h"
30
31 #ifdef NX_BSD_ENABLE_DNS
32 #include "nxd_dns.h"
33 #endif
34
35
36 #include "nx_udp.h"
37 #include "nx_igmp.h"
38 #include "nx_system.h"
39 #ifdef FEATURE_NX_IPV6
40 #include "nx_icmpv6.h"
41 #endif
42 #include "tx_timer.h"
43
44 /* Define a NetX packet pool pointer for BSD use. */
45
46 NX_PACKET_POOL *nx_bsd_default_packet_pool;
47
48
49 /* Define the default IP instance for BSD use. */
50
51 NX_IP *nx_bsd_default_ip;
52
53
54 /* Define the single mutex protection for the BSD layer calls. */
55
56 TX_MUTEX *nx_bsd_protection_ptr;
57
58
59 /* Define IP fast periodic timer entry. */
60 VOID (*nx_bsd_ip_fast_periodic_timer_entry)(ULONG id);
61
62 /* Define BSD system clock time. The precision depends on _nx_ip_fast_timer_rate. */
63 ULONG nx_bsd_system_clock;
64
65 /* Define BSD system clock timer rate. */
66 ULONG nx_bsd_timer_rate;
67
68 /* Define the event flag group for notifying threads suspended on BSD sockets to wakeup. */
69
70 TX_EVENT_FLAGS_GROUP nx_bsd_events;
71
72
73 /* Define the array of BSD managed sockets. */
74
75 NX_BSD_SOCKET nx_bsd_socket_array[NX_BSD_MAX_SOCKETS];
76
77 /* Define the raw socket protocol hash table. */
78
79 NX_BSD_SOCKET *nx_bsd_socket_raw_protocol_table[NX_BSD_SOCKET_RAW_PROTOCOL_TABLE_SIZE];
80
81 /* Create some buffer space for number string conversions. */
82 #define NX_BSD_URL_BUFSIZE 18
83 CHAR nx_bsd_url_buffer[NX_BSD_URL_BUFSIZE];
84
85 /* Define the search index for the BSD array. */
86
87 UINT nx_bsd_socket_array_index;
88
89
90 /* Define the block pool that will be used to dynamically allocate either NetX UDP or TCP sockets. */
91
92 TX_BLOCK_POOL nx_bsd_socket_block_pool;
93
94 /* Define the memory area for the socket block pool... use TCP socket size, since it is the larger. */
95
96 static ULONG nx_bsd_socket_pool_memory[NX_BSD_MAX_SOCKETS * (sizeof(NX_TCP_SOCKET) + sizeof(VOID *)) / sizeof(ULONG)];
97
98 /* Define the block pool that will be used to dynamically allocate addrinfo struct. */
99
100 TX_BLOCK_POOL nx_bsd_addrinfo_block_pool;
101
102 /* Define the memory area for addrinfo pool. sizeof(addrinfo) is the MAX of:
103 * {sizeof(addrinfo)== 32, sizeof(sockaddr_in) == 16, or sizeof(sockaddr_in6)} = 28.
104 * Every address may be mapped to 3 socktypes, SOCK_STREAM, SOCK_DGRAM and SOCK_RAW,
105 * 3 blocks for addrinfo) + 1 block for IP adddress = 4 blocks */
106
107 static ULONG nx_bsd_addrinfo_pool_memory[(NX_BSD_IPV4_ADDR_MAX_NUM + NX_BSD_IPV6_ADDR_MAX_NUM) * 4
108 *(sizeof(struct nx_bsd_addrinfo) + sizeof(VOID *)) / sizeof(ULONG)];
109
110 #ifdef NX_BSD_ENABLE_DNS
111
112 /* The global DNS client instance. */
113 extern NX_DNS *_nx_dns_instance_ptr;
114
115 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
116 /* Define the block pool that will be used to dynamically allocate canonical name buffer. */
117 TX_BLOCK_POOL nx_bsd_cname_block_pool;
118
119 /* Here we just support a CNAME per IP address. */
120 static ULONG nx_bsd_cname_pool_memory[(NX_BSD_IPV4_ADDR_MAX_NUM + NX_BSD_IPV6_ADDR_MAX_NUM) *
121 (NX_DNS_NAME_MAX + 1) / sizeof(ULONG)];
122 #endif /* NX_DNS_ENABLE_EXTENDED_RR_TYPES */
123 #endif /* NX_BSD_ENABLE_DNS */
124
125 #if (defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)) && defined(NX_ENABLE_VLAN)
126 NX_LINK_RECEIVE_QUEUE nx_bsd_socket_link_receive_queue[NX_MAX_IP_INTERFACES];
127 #endif
128
129 /* Buffer used to store IP address get from DNS. */
130 static ULONG nx_bsd_ipv4_addr_buffer[NX_BSD_IPV4_ADDR_PER_HOST];
131 static ULONG nx_bsd_ipv6_addr_buffer[NX_BSD_IPV6_ADDR_PER_HOST * 4];
132
133 /* Utility character type functions*/
134 static UINT nx_bsd_isspace(UCHAR c);
135 static UINT nx_bsd_islower(UCHAR c);
136 static UINT nx_bsd_isdigit(UCHAR c);
137 static UINT nx_bsd_isxdigit(UCHAR c);
138
139 /* Standard BSD callback functions to register with NetX Duo. */
140
141 static VOID nx_bsd_tcp_receive_notify(NX_TCP_SOCKET *socket_ptr);
142 static VOID nx_bsd_tcp_socket_disconnect_notify(NX_TCP_SOCKET *socket_ptr);
143 static VOID nx_bsd_udp_receive_notify(NX_UDP_SOCKET *socket_ptr);
144 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
145 static UINT nx_bsd_raw_packet_filter(NX_IP *ip_ptr, ULONG protocol, NX_PACKET *packet_ptr);
146 #ifdef FEATURE_NX_IPV6
147 static VOID _nxd_bsd_swap_ipv6_extension_headers(NX_PACKET *packet_ptr, UCHAR header_type);
148 #endif /* FEATURE_NX_IPV6 */
149 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
150 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
151 static VOID nx_bsd_tcp_establish_notify(NX_TCP_SOCKET *socket_ptr);
152 #endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */
153 static VOID nx_bsd_select_wakeup(UINT sock_id, UINT fdsets);
154 static VOID nx_bsd_set_error_code(NX_BSD_SOCKET *bsd_socket_ptr, UINT status_code);
155 static VOID nx_bsd_udp_packet_received(INT sockID, NX_PACKET *packet_ptr);
156 static UINT nx_bsd_tcp_syn_received_notify(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr);
157 static INT nx_bsd_tcp_create_listen_socket(INT master_sockid, INT backlog);
158 static VOID nx_bsd_tcp_pending_connection(UINT local_port, NX_TCP_SOCKET *socket_ptr);
159 static INT nx_bsd_find_interface_by_source_addr(UINT addr_family, ULONG* ip_addr);
160 #ifndef NX_DISABLE_IPV4
161 static VOID _nxd_bsd_ipv4_packet_send(NX_PACKET *packet_ptr);
162 #endif /* NX_DISABLE_IPV4 */
163 static INT nx_bsd_send_internal(INT sockID, const CHAR *msg, INT msgLength, INT flags,
164 NXD_ADDRESS *dst_address, USHORT dst_port, UINT local_interface_index);
165 static INT nx_bsd_recv_internal(INT sockID, struct nx_bsd_iovec *iov, size_t iovlen, INT flags,
166 struct nx_bsd_sockaddr *fromAddr, INT *fromAddrLen);
167 #ifdef FEATURE_NX_IPV6
168 static VOID _nxd_bsd_ipv6_packet_send(NX_PACKET *packet_ptr, ULONG *src_addr, ULONG *dest_addr);
169 #endif /* FEATURE_NX_IPV6 */
170
171 static INT inet_ntoa_internal(const VOID *src, CHAR *dst, ULONG dst_size);
172 static INT bsd_string_to_number(const CHAR *string, UINT *number);
173 static ULONG _nx_bsd_string_length(CHAR * string);
174
175 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
176 static INT nx_bsd_pppoe_internal_sendto(NX_BSD_SOCKET *bsd_socket_ptr, CHAR *msg, INT msgLength,
177 INT flags, struct nx_bsd_sockaddr* destAddr, INT destAddrLen);
178 static UINT nx_bsd_socket_create_id = 0;
179 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
180
181 #ifdef NX_BSD_RAW_SUPPORT
182 static INT _nx_bsd_hardware_internal_sendto(NX_BSD_SOCKET *bsd_socket_ptr, CHAR *msg, INT msgLength,
183 INT flags, struct nx_bsd_sockaddr* destAddr, INT destAddrLen);
184 static VOID _nx_bsd_hardware_packet_received(NX_PACKET *packet_ptr, UCHAR *consumed);
185 #ifdef NX_ENABLE_VLAN
186 static UINT _nx_bsd_ethernet_receive_notify(NX_IP *ip_ptr, UINT interface_index, NX_PACKET *packet_ptr,
187 ULONG physical_address_msw, ULONG physical_address_lsw,
188 UINT packet_type, UINT header_size, VOID *context,
189 struct NX_LINK_TIME_STRUCT *time_ptr);
190 #endif /* NX_ENABLE_VLAN */
191 #endif /* NX_BSD_RAW_SUPPORT */
192 static VOID _nx_bsd_fast_periodic_timer_entry(ULONG id);
193
194 #ifndef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
195 TX_THREAD nx_bsd_task_thread;
196 static VOID nx_bsd_thread_entry(ULONG info);
197 #else
198 static TX_TIMER nx_bsd_timer;
199 static VOID nx_bsd_timer_entry(ULONG info);
200 #endif
201 UINT bsd_number_convert(UINT number, CHAR *string, ULONG buffer_len, UINT base);
202 VOID nx_bsd_socket_timed_wait_callback(NX_TCP_SOCKET *tcp_socket_ptr);
203
204 #define FDSET_READ 1
205 #define FDSET_WRITE 2
206 #define FDSET_EXCEPTION 4
207
208 extern TX_THREAD *_tx_thread_current_ptr;
209
210 static ULONG _nx_bsd_serv_list_len;
211 static struct NX_BSD_SERVICE_LIST *_nx_bsd_serv_list_ptr;
212
213
214 /**************************************************************************/
215 /* */
216 /* FUNCTION RELEASE */
217 /* */
218 /* bsd_initialize PORTABLE C */
219 /* 6.3.0 */
220 /* AUTHOR */
221 /* */
222 /* Yuxin Zhou, Microsoft Corporation */
223 /* */
224 /* DESCRIPTION */
225 /* */
226 /* This function sets up all data structures and NetX, and ThreadX */
227 /* resources needed by the BSD compatibility layer. It is recommended */
228 /* to call this routine from tx_application_define. */
229 /* */
230 /* INPUTS */
231 /* */
232 /* *default_ip NX_IP created for BSD API */
233 /* *default_pool Packet Pool used by BSD API */
234 /* *bsd_thread_stack_area Stack memory pointer for the */
235 /* BSD thread stack space */
236 /* bsd_thread_stack_size Size of thread stack */
237 /* bsd_thread_priority BSD thread priority */
238 /* */
239 /* OUTPUT */
240 /* */
241 /* NX_SUCCESS Successful completion */
242 /* NX_BSD_BLOCK_POOL_ERROR Error creating socket block */
243 /* pool */
244 /* NX_BSD_EVENT_ERROR Error creating the event flag */
245 /* group */
246 /* NX_BSD_MUTEX_ERROR Error creating mutex */
247 /* NX_BSD_ENVIRONMENT_ERROR Error environment */
248 /* */
249 /* CALLS */
250 /* */
251 /* memset Set memory */
252 /* tx_block_pool_create Create a block pool */
253 /* tx_block_pool_delete Delete a block pool */
254 /* tx_event_flags_create Create event flag group */
255 /* tx_mutex_create Create protection mutex */
256 /* tx_mutex_delete Delete protection mutex */
257 /* */
258 /* CALLED BY */
259 /* */
260 /* Start-up code */
261 /* */
262 /* RELEASE HISTORY */
263 /* */
264 /* DATE NAME DESCRIPTION */
265 /* */
266 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
267 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
268 /* resulting in version 6.1 */
269 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
270 /* used new API/structs naming,*/
271 /* resulting in version 6.3.0 */
272 /* 12-31-2023 Yanwu Cai Modified comment(s), and */
273 /* added nx_link layer, */
274 /* resulting in version 6.4.0 */
275 /* */
276 /**************************************************************************/
nx_bsd_initialize(NX_IP * default_ip,NX_PACKET_POOL * default_pool,CHAR * bsd_thread_stack_area,ULONG bsd_thread_stack_size,UINT bsd_thread_priority)277 INT nx_bsd_initialize(NX_IP *default_ip, NX_PACKET_POOL *default_pool, CHAR *bsd_thread_stack_area,
278 ULONG bsd_thread_stack_size, UINT bsd_thread_priority)
279 {
280
281 INT i;
282 UINT status;
283 ULONG info;
284
285 #ifndef NX_ENABLE_EXTENDED_NOTIFY_SUPPORT
286
287 /* Error, return the error message. */
288 /* BSD doesn't work with out NX_ENABLE_EXTENDED_NOTIFY_SUPPORT option. */
289 NX_BSD_ERROR(NX_BSD_ENVIRONMENT_ERROR, __LINE__);
290 return(NX_BSD_ENVIRONMENT_ERROR);
291 #endif /* NX_ENABLE_EXTENDED_NOTIFY_SUPPORT */
292
293 /* Create a block pool for dynamically allocating sockets. */
294 status = tx_block_pool_create(&nx_bsd_socket_block_pool, "NetX BSD Socket Block Pool", sizeof(NX_TCP_SOCKET),
295 nx_bsd_socket_pool_memory, sizeof(nx_bsd_socket_pool_memory));
296
297 /* Determine if the pool was created. */
298 if (status)
299 {
300
301 /* Error, return the error message. */
302 NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
303 return(NX_BSD_BLOCK_POOL_ERROR);
304 }
305
306 /* Create a block pool for dynamically allocating addrinfo. */
307 status = tx_block_pool_create(&nx_bsd_addrinfo_block_pool, "NetX BSD Addrinfo Block Pool", sizeof(struct nx_bsd_addrinfo),
308 nx_bsd_addrinfo_pool_memory, sizeof(nx_bsd_addrinfo_pool_memory));
309
310 /* Determine if the pool was created. */
311 if(status)
312 {
313
314 /* Error, return the error messafe. */
315 NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
316
317 /* Delete the block pool. */
318 tx_block_pool_delete(&nx_bsd_socket_block_pool);
319 return(NX_BSD_BLOCK_POOL_ERROR);
320
321 }
322
323 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
324 /* Create a block pool for dynamically allocating canonical name buffer. */
325 status = tx_block_pool_create(&nx_bsd_cname_block_pool, "NetX BSD CNAME Block Pool", (NX_DNS_NAME_MAX + 1),
326 nx_bsd_cname_pool_memory, sizeof(nx_bsd_cname_pool_memory));
327
328 /* Determine if the pool was created. */
329 if(status)
330 {
331
332 /* Error, return the error messafe. */
333 NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
334
335 /* Delete the block pool. */
336 tx_block_pool_delete(&nx_bsd_socket_block_pool);
337 tx_block_pool_delete(&nx_bsd_addrinfo_block_pool);
338 return(NX_BSD_BLOCK_POOL_ERROR);
339
340 }
341 #endif
342
343 nx_bsd_protection_ptr = &default_ip -> nx_ip_protection;
344
345 /* Create the BSD event flag group. */
346 status = tx_event_flags_create(&nx_bsd_events, "NetX BSD Events");
347
348 /* Check the return status. */
349 if (status)
350 {
351 /* Delete the block pool. */
352 tx_block_pool_delete(&nx_bsd_socket_block_pool);
353 tx_block_pool_delete(&nx_bsd_addrinfo_block_pool);
354 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
355 tx_block_pool_delete(&nx_bsd_cname_block_pool);
356 #endif
357
358 /* Error present, return error code. */
359 NX_BSD_ERROR(NX_BSD_EVENT_ERROR, __LINE__);
360 return(NX_BSD_EVENT_ERROR);
361 }
362
363 /* Set the array index to 0. */
364 nx_bsd_socket_array_index = 0;
365
366 /* Loop through the BSD socket array and clear it out! */
367 for (i = 0; i < NX_BSD_MAX_SOCKETS; i++)
368 {
369
370 /* Clear the BSD socket structure. */
371 memset((VOID*) &nx_bsd_socket_array[i], 0, sizeof(NX_BSD_SOCKET));
372 }
373
374 /* Save the IP instance and NX_PACKET_POOL for BSD Socket API. */
375 nx_bsd_default_ip = default_ip;
376 nx_bsd_default_packet_pool = default_pool;
377
378
379 if ((bsd_thread_stack_area == TX_NULL) || (bsd_thread_stack_size == 0))
380 {
381 /* Return error. */
382 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
383 return(NX_SOC_ERROR);
384 }
385
386 #ifndef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
387 /* Create a thread for BSD socket features requiring periodic tasks. */
388 info = 0 ;
389 status = tx_thread_create(&nx_bsd_task_thread, "BSD thread task", nx_bsd_thread_entry, info,
390 bsd_thread_stack_area, bsd_thread_stack_size, bsd_thread_priority,
391 bsd_thread_priority, 1, TX_AUTO_START);
392
393 if (status != TX_SUCCESS)
394 {
395 /* Delete the event flag group. */
396 tx_event_flags_delete(&nx_bsd_events);
397
398 /* Delete the block pool. */
399 tx_block_pool_delete(&nx_bsd_socket_block_pool);
400 tx_block_pool_delete(&nx_bsd_addrinfo_block_pool);
401 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
402 tx_block_pool_delete(&nx_bsd_cname_block_pool);
403 #endif
404
405 /* Error, return the error message. */
406 NX_BSD_ERROR(NX_BSD_THREAD_ERROR, __LINE__);
407
408 /* Return an error. */
409 return(NX_IP_INTERNAL_ERROR);
410 }
411 #else
412
413 info = 0 ;
414
415 /* Create a one shot timer. Do not activate it. We will use it if
416 a socket being disconnected is NOT enabled for REUSEADDR socket option. */
417 status = tx_timer_create(&nx_bsd_timer, "BSD Timer",
418 nx_bsd_timer_entry, info,
419 NX_BSD_TIMER_RATE, NX_BSD_TIMER_RATE, TX_AUTO_START);
420
421 if (status != TX_SUCCESS)
422 {
423
424 /* Delete the event flag group. */
425 tx_event_flags_delete(&nx_bsd_events);
426
427 /* Delete the block pool. */
428 tx_block_pool_delete(&nx_bsd_socket_block_pool);
429 tx_block_pool_delete(&nx_bsd_addrinfo_block_pool);
430 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
431 tx_block_pool_delete(&nx_bsd_cname_block_pool);
432 #endif
433
434 #ifndef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
435 /* Delete the thread. */
436 tx_thread_delete(&nx_bsd_task_thread);
437 #endif
438 /* Error, return the error message. */
439 NX_BSD_ERROR(NX_BSD_THREAD_ERROR, __LINE__);
440
441 /* Return an error. */
442 return(NX_IP_INTERNAL_ERROR);
443 }
444 #endif
445
446 #ifdef NX_BSD_RAW_SUPPORT
447 #ifdef NX_ENABLE_VLAN
448
449 /* set link layer receive notification */
450 for(i = 0; i< NX_MAX_IP_INTERFACES; i++)
451 {
452
453 status = nx_link_packet_receive_callback_add(default_ip,
454 i,
455 &nx_bsd_socket_link_receive_queue[i],
456 NX_LINK_PACKET_TYPE_ALL,
457 _nx_bsd_ethernet_receive_notify,
458 NX_NULL);
459 if (status != NX_SUCCESS)
460 {
461 return(status);
462 }
463 }
464 #else
465 _nx_driver_hardware_packet_received_callback = _nx_bsd_hardware_packet_received;
466 #endif /* NX_ENABLE_VLAN */
467 #endif /* NX_BSD_RAW_SUPPORT */
468
469 /* Calculate BSD system timer rate. */
470 nx_bsd_timer_rate = (NX_IP_PERIODIC_RATE + (NX_IP_FAST_TIMER_RATE - 1)) / NX_IP_FAST_TIMER_RATE;
471
472 /* Return success! */
473 return(NX_SOC_OK);
474 }
475
476
477 /**************************************************************************/
478 /* */
479 /* FUNCTION RELEASE */
480 /* */
481 /* nx_bsd_timeout_process PORTABLE C */
482 /* 6.1 */
483 /* AUTHOR */
484 /* */
485 /* Yuxin Zhou, Microsoft Corporation */
486 /* */
487 /* DESCRIPTION */
488 /* */
489 /* This function checks for sockets waiting to make a TCP connection. */
490 /* */
491 /* INPUT */
492 /* */
493 /* None */
494 /* */
495 /* OUTPUT */
496 /* */
497 /* None */
498 /* */
499 /* CALLS */
500 /* */
501 /* tx_mutex_get Obtain exclusive access to */
502 /* tx_mutex_put Release exclusive access */
503 /* nx_tcp_server_socket_unaccept Remove socket from listen list */
504 /* nx_tcp_server_socket_relisten Restore socket to listening */
505 /* nx_tcp_server_socket_accept Accept to connection request */
506 /* */
507 /* CALLED BY */
508 /* */
509 /* ThreadX */
510 /* */
511 /* RELEASE HISTORY */
512 /* */
513 /* DATE NAME DESCRIPTION */
514 /* */
515 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
516 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
517 /* resulting in version 6.1 */
518 /* */
519 /**************************************************************************/
nx_bsd_timeout_process()520 static VOID nx_bsd_timeout_process()
521 {
522
523 INT i;
524 ULONG status;
525 INT master_socket_index;
526 NX_BSD_SOCKET *bsd_socket_ptr;
527
528
529 /* Obtain the BSD lock. */
530 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
531
532 if(status)
533 {
534 /* Mutex operation failed. This should be fatal. */
535 return;
536 }
537
538 for( i = 0; i < NX_BSD_MAX_SOCKETS; i++)
539 {
540
541 /* Skip the unused sockets. */
542 if(!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
543 {
544
545 continue;
546 }
547
548 /* Skip if it is not TCP server socket. */
549 if((nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket == NX_NULL) ||
550 ((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CLIENT)))
551 {
552 continue;
553 }
554
555 /* Check for sockets trying to make a TCP connection.
556 Detect that the socket state is CLOSED, which is an indication
557 that the attempted connection failed, and we shall signal any pending
558 select on the socket. */
559 if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_INPROGRESS)
560 {
561
562 /* Is the NetX socket closed? */
563 if(nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket -> nx_tcp_socket_state == NX_TCP_CLOSED)
564 {
565
566 /* Yes. Set up a local pointer to the BSD socket. */
567 bsd_socket_ptr = &nx_bsd_socket_array[i];
568
569 /* Is this a secondary socket (passive open)? */
570 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET)
571 {
572
573 /* Yes; Is the socket is connected yet? */
574 if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED))
575 {
576
577 /* No; Turn off the disconnection_request flag. */
578 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_DISCONNECTION_REQUEST);
579
580 /* Remove the underlying NetX socket from the listen state. */
581 nx_tcp_server_socket_unaccept(bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
582
583 /* Check if a listen request is queued up for this socket. */
584 nx_bsd_tcp_pending_connection(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port,
585 bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
586
587 /* Relisten on this socket. */
588 status = nx_tcp_server_socket_relisten(nx_bsd_default_ip,
589 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port,
590 bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
591 /* Set the socket to accept the connection. */
592 nx_tcp_server_socket_accept(bsd_socket_ptr -> nx_bsd_socket_tcp_socket, NX_NO_WAIT);
593
594 /* Check the result of the relisten call. */
595 if(status == NX_CONNECTION_PENDING)
596 {
597
598 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
599 }
600 else if(status != NX_SUCCESS)
601 {
602
603
604 /* Failed the relisten on the secondary socket. Set the error code on the
605 master socket, and wake it up. */
606
607 master_socket_index = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id;
608
609 nx_bsd_socket_array[master_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
610 nx_bsd_set_error_code(&nx_bsd_socket_array[master_socket_index], status);
611
612 nx_bsd_select_wakeup((UINT)master_socket_index, (FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION));
613 }
614 }
615 }
616 else
617 {
618 /* The underlying socket is closed. This indicates an error, and since is a non-blocking
619 socket, we need to wake up the corresponding thread. */
620
621 /* Mark this socket as error, and remove the CONNECT and INPROGRESS flags */
622 nx_bsd_socket_array[i].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
623 nx_bsd_socket_array[i].nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
624 nx_bsd_socket_array[i].nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTED);
625 nx_bsd_socket_array[i].nx_bsd_socket_error_code = ECONNREFUSED;
626
627 /* Wake up the socket that could be listening on it. */
628 /* Notice that on error the both read and write are selectable. */
629 nx_bsd_select_wakeup((UINT)i, FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION);
630 }
631 }
632 }
633 }
634
635 /* Release the mutex. */
636 tx_mutex_put(nx_bsd_protection_ptr);
637 }
638
639 /**************************************************************************/
640 /* */
641 /* FUNCTION RELEASE */
642 /* */
643 /* nx_bsd_thread_entry PORTABLE C */
644 /* 6.1 */
645 /* AUTHOR */
646 /* */
647 /* Yuxin Zhou, Microsoft Corporation */
648 /* */
649 /* DESCRIPTION */
650 /* */
651 /* This function checks for events indicating BSD TCP socket tasks are */
652 /* waiting to be performed. */
653 /* */
654 /* INPUT */
655 /* */
656 /* None */
657 /* */
658 /* OUTPUT */
659 /* */
660 /* None */
661 /* */
662 /* CALLS */
663 /* */
664 /* tx_event_flags_get Check for registered events */
665 /* nx_bsd_timeout_process Process BSD tasks */
666 /* */
667 /* CALLED BY */
668 /* */
669 /* ThreadX */
670 /* */
671 /* RELEASE HISTORY */
672 /* */
673 /* DATE NAME DESCRIPTION */
674 /* */
675 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
676 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
677 /* resulting in version 6.1 */
678 /* */
679 /**************************************************************************/
680
681 #ifndef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
nx_bsd_thread_entry(ULONG info)682 VOID nx_bsd_thread_entry(ULONG info)
683 {
684 NX_PARAMETER_NOT_USED(info);
685
686 while(1)
687 {
688
689 /* Wait for timeout. */
690 tx_thread_sleep(NX_BSD_TIMER_RATE);
691
692 /* Timeout process. */
693 nx_bsd_timeout_process();
694 }
695 }
696 #endif
697
698 /**************************************************************************/
699 /* */
700 /* FUNCTION RELEASE */
701 /* */
702 /* socket PORTABLE C */
703 /* 6.3.0 */
704 /* AUTHOR */
705 /* */
706 /* Yuxin Zhou, Microsoft Corporation */
707 /* */
708 /* DESCRIPTION */
709 /* */
710 /* Creates a TCP or UDP socket, which may then be used as an end point */
711 /* of communication for sending and receiving data using the specified */
712 /* protocol. */
713 /* */
714 /* INPUT */
715 /* */
716 /* protocolFamily Protocol family e.g AF_INET */
717 /* type Type of the socket TCP or UDP */
718 /* protocol Socket protocol */
719 /* */
720 /* OUTPUT */
721 /* */
722 /* socket descriptor On success */
723 /* NX_SOC_ERROR (-1) On failure */
724 /* */
725 /* CALLS */
726 /* */
727 /* memset Clears memory */
728 /* nx_tcp_socket_create Create TCP BSD Socket */
729 /* nx_udp_socket_create Create UDP BSD Socket */
730 /* nx_tcp_socket_receive_notify TCP receive notify function */
731 /* nx_udp_socket_receive_notify UDP receive notify function */
732 /* tx_block_allocate Allocate socket memory */
733 /* tx_block_release Release socket memory */
734 /* tx_mutex_get Get protection */
735 /* tx_mutex_put Release protection */
736 /* */
737 /* CALLED BY */
738 /* */
739 /* Application Code */
740 /* */
741 /* RELEASE HISTORY */
742 /* */
743 /* DATE NAME DESCRIPTION */
744 /* */
745 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
746 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
747 /* resulting in version 6.1 */
748 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
749 /* used new API/structs naming,*/
750 /* resulting in version 6.3.0 */
751 /* */
752 /**************************************************************************/
nx_bsd_socket(INT protocolFamily,INT type,INT protocol)753 INT nx_bsd_socket(INT protocolFamily, INT type, INT protocol)
754 {
755
756 INT i;
757 UINT status;
758 NX_TCP_SOCKET *tcp_socket_ptr;
759 NX_UDP_SOCKET *udp_socket_ptr;
760 VOID *socket_memory = NX_NULL;
761 NX_BSD_SOCKET *bsd_socket_ptr;
762
763 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
764 UINT index;
765 #else
766
767 NX_PARAMETER_NOT_USED(protocol);
768 #endif
769
770 /* Check for a supported protocol family. */
771 #ifndef NX_DISABLE_IPV4
772 if (protocolFamily == AF_INET)
773 {
774 }
775 else
776 #endif /* NX_DISABLE_IPV4 */
777 #ifdef FEATURE_NX_IPV6
778 if (protocolFamily == AF_INET6)
779 {
780 }
781 else
782 #endif /* FEATURE_NX_IPV6 */
783 #if defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)
784 if (protocolFamily == AF_PACKET)
785 {
786 }
787 else
788 #endif /* defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT) */
789 {
790
791 /* Set the socket error. */
792 nx_bsd_set_errno(EAFNOSUPPORT);
793
794 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
795 return(NX_SOC_ERROR);
796 }
797
798 /* Check for a supported socket type. */
799 #if defined(NX_ENABLE_IP_RAW_PACKET_FILTER) || defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT)
800 if ((type != SOCK_STREAM) && (type != SOCK_DGRAM) && (type != SOCK_RAW))
801 #else
802 if ((type != SOCK_STREAM) && (type != SOCK_DGRAM))
803 #endif
804 {
805
806 /* Set the socket error. */
807 nx_bsd_set_errno(EPROTOTYPE);
808
809 /* Invalid type. */
810 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
811 return(NX_SOC_ERROR);
812 }
813
814 #if defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)
815 /* An extra check when BSD RAW Packet type is enabled:
816 Only RAW_SOCKET type is supported in AF_PACKET family. */
817 if((protocolFamily == AF_PACKET) && (type != SOCK_RAW))
818 {
819 /* Set the socket error. */
820 nx_bsd_set_errno(EPROTOTYPE);
821
822 /* Invalid type. */
823 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
824 return(NX_SOC_ERROR);
825 }
826 #endif /* defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT) */
827
828
829 /* Obtain the BSD protection socket. */
830 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
831
832 /* Check the status. */
833 if (status)
834 {
835
836 /* Set the socket error. */
837 nx_bsd_set_errno(EACCES);
838
839 /* Error getting the protection mutex. */
840 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
841 return(NX_SOC_ERROR);
842 }
843
844 /* Check whether IP fast timer is created or not. */
845 if ((nx_bsd_ip_fast_periodic_timer_entry == NX_NULL) ||
846 (nx_bsd_default_ip -> nx_ip_fast_periodic_timer.tx_timer_internal.tx_timer_internal_timeout_function != _nx_bsd_fast_periodic_timer_entry))
847 {
848
849 /* BSD socket requires a fast periodic timer to calculate wait option in recv() function. */
850 /* Create IP fast periodic timer. */
851 _nx_ip_fast_periodic_timer_create(nx_bsd_default_ip);
852
853 /* Replace timer expiration function entry. */
854 nx_bsd_ip_fast_periodic_timer_entry = nx_bsd_default_ip -> nx_ip_fast_periodic_timer.tx_timer_internal.tx_timer_internal_timeout_function;
855 nx_bsd_default_ip -> nx_ip_fast_periodic_timer.tx_timer_internal.tx_timer_internal_timeout_function = _nx_bsd_fast_periodic_timer_entry;
856 }
857
858 /* Now find a free slot in the BSD socket array. */
859 for (i = 0; i < NX_BSD_MAX_SOCKETS; i++)
860 {
861
862 /* See if this entry is available. Check the in use flag. */
863 if (!(nx_bsd_socket_array[nx_bsd_socket_array_index].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
864 {
865
866 /* Yes, Ok to use this socket. */
867
868 /* Clear the entire structure. */
869 memset((VOID*) &nx_bsd_socket_array[nx_bsd_socket_array_index], 0, sizeof(NX_BSD_SOCKET));
870 nx_bsd_socket_array[nx_bsd_socket_array_index].nx_bsd_socket_id = (INT)nx_bsd_socket_array_index;
871
872 /* Mark this socket as in-use. */
873 nx_bsd_socket_array[nx_bsd_socket_array_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_IN_USE;
874
875 /* Get out of the loop. */
876 break;
877 }
878 else
879 {
880
881 /* Try the next socket. */
882 nx_bsd_socket_array_index++;
883
884 /* Check if we need to wrap around to the start of the socket table. */
885 if (nx_bsd_socket_array_index >= NX_BSD_MAX_SOCKETS)
886 {
887
888 /* Reset the index to 0. */
889 nx_bsd_socket_array_index = 0;
890 }
891 }
892 }
893
894 /* Check if a free socket was found. */
895 if (i >= NX_BSD_MAX_SOCKETS)
896 {
897
898 /* No, set the error status and return. */
899
900 /* Set the socket error. */
901 nx_bsd_set_errno(ENFILE);
902
903 /* Release the mutex. */
904 tx_mutex_put(nx_bsd_protection_ptr);
905
906 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
907 return(NX_SOC_ERROR);
908 }
909
910 /* Mark the location of the free socket. */
911 i = (INT)nx_bsd_socket_array_index;
912
913 /* Update the socket index to the next entry. */
914 nx_bsd_socket_array_index++;
915
916 /* Check if we need to wrap around to the start of the table. */
917 if (nx_bsd_socket_array_index >= NX_BSD_MAX_SOCKETS)
918 {
919
920 /* Reset the index to 0. */
921 nx_bsd_socket_array_index = 0;
922 }
923
924 /* Set up a pointer to the BSD socket to use. */
925 bsd_socket_ptr = &nx_bsd_socket_array[i];
926
927 /* For TCP or UDP sockets we need to allocate memory to create the NetX Duo socket
928 (not necessary for raw socket). */
929
930 if ((type == SOCK_STREAM) || (type == SOCK_DGRAM))
931 {
932
933 /* Allocate a socket from the block pool. */
934 status = tx_block_allocate(&nx_bsd_socket_block_pool, &socket_memory, NX_BSD_TIMEOUT);
935
936 /* Check for error status. */
937 if (status != TX_SUCCESS)
938 {
939
940 /* Set the socket error. */
941 nx_bsd_set_errno(ENOMEM);
942
943 /* Clear the allocated internal BSD socket. */
944 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_IN_USE);
945
946 /* Release the mutex. */
947 tx_mutex_put(nx_bsd_protection_ptr);
948
949 /* Error getting NetX socket memory. */
950 NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
951 return(NX_SOC_ERROR);
952 }
953
954 /* Clear the socket memory. */
955 memset((VOID*) socket_memory, 0, sizeof(NX_TCP_SOCKET));
956
957 }
958
959 /* Is this a stream socket e.g. TCP? */
960 if (type == SOCK_STREAM)
961 {
962 bsd_socket_ptr -> nx_bsd_socket_protocol = NX_PROTOCOL_TCP;
963
964 /* Mark the master/secondary socket id as invalid. */
965 (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id = NX_BSD_MAX_SOCKETS;
966 (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = NX_BSD_MAX_SOCKETS;
967
968 /* Yes, allocate memory for a TCP socket. */
969 tcp_socket_ptr = (NX_TCP_SOCKET *) socket_memory;
970
971 /* Create a NetX TCP socket. */
972 /* Note that the nx_bsd_tcp_socket_disconnect_notify is invoked when an
973 established connection is disconnected.
974 The disconnect_complete_notify is called for all types of disconnect,
975 including the ones covered by tcp_socket_disconnect_notify. */
976
977 status = nx_tcp_socket_create(nx_bsd_default_ip, tcp_socket_ptr, "NetX BSD TCP Socket",
978 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, NX_BSD_TCP_WINDOW, NX_NULL,
979 nx_bsd_tcp_socket_disconnect_notify);
980
981 /* Check for a successful status. */
982 if (status == NX_SUCCESS)
983 {
984
985 /* Register a receive notify callback. */
986 status = nx_tcp_socket_receive_notify(tcp_socket_ptr, nx_bsd_tcp_receive_notify);
987
988 /* Check for invalid input. */
989 if (status != NX_SUCCESS)
990 {
991
992 /* Set the socket error if extended socket options enabled. */
993 nx_bsd_set_errno(EINVAL);
994
995 /* Release the allocated socket memory block. */
996 tx_block_release(socket_memory);
997
998 /* Release the mutex. */
999 tx_mutex_put(nx_bsd_protection_ptr);
1000
1001 /* Error getting NetX socket memory. */
1002 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1003 return(NX_SOC_ERROR);
1004 }
1005
1006 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
1007
1008 /* Set the SYN received notify function */
1009 tcp_socket_ptr -> nx_tcp_socket_syn_received_notify = nx_bsd_tcp_syn_received_notify;
1010 #endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */
1011
1012 #ifdef NX_ENABLE_TCP_KEEPALIVE
1013 /* Set the keep alive feature to disabled. */
1014 tcp_socket_ptr -> nx_tcp_socket_keepalive_enabled = NX_FALSE;
1015 #endif /* NX_ENABLE_TCP_KEEPALIVE */
1016
1017 /* Set the socket reuse feature to enabled. This is the default NetX socket behavior. */
1018 bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR;
1019
1020 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
1021 /* Register an establish notify callback for the specified server socket with NetX. */
1022 nx_tcp_socket_establish_notify(tcp_socket_ptr, nx_bsd_tcp_establish_notify);
1023
1024 /* Register a disconnect complete notify callback for the specified server socket with NetX. */
1025 /* The callback function is the same as the one used for TCP disconnect callback. */
1026 status += nx_tcp_socket_disconnect_complete_notify(tcp_socket_ptr, nx_bsd_tcp_socket_disconnect_notify);
1027 #endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */
1028
1029 /* Return successful completion. */
1030
1031 /* Save the TCP pointer in the appropriate place. */
1032 bsd_socket_ptr -> nx_bsd_socket_tcp_socket = tcp_socket_ptr;
1033
1034 /* Set up pointer in the NetX socket back to the BSD socket. */
1035 tcp_socket_ptr -> nx_tcp_socket_reserved_ptr = (VOID *) i;
1036
1037
1038 }
1039 }
1040 else if (type == SOCK_DGRAM)
1041 {
1042
1043 bsd_socket_ptr -> nx_bsd_socket_protocol = NX_PROTOCOL_UDP;
1044
1045 /* Make a double circular list. */
1046 bsd_socket_ptr -> nx_bsd_socket_next = bsd_socket_ptr;
1047 bsd_socket_ptr -> nx_bsd_socket_previous = bsd_socket_ptr;
1048
1049 /* Allocate memory for a UDP socket. */
1050 udp_socket_ptr = (NX_UDP_SOCKET *) socket_memory;
1051
1052 /* Create a NetX UDP socket */
1053 status = nx_udp_socket_create(nx_bsd_default_ip, udp_socket_ptr, "NetX BSD UDP Socket",
1054 NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE,
1055 (nx_bsd_default_packet_pool -> nx_packet_pool_total)/8+1);
1056
1057 /* Check for successful result. */
1058 if (status == NX_SUCCESS)
1059 {
1060
1061 /* Register a receive notify callback. */
1062 status = nx_udp_socket_receive_notify(udp_socket_ptr, nx_bsd_udp_receive_notify);
1063
1064 /* Check for errors. */
1065 if (status != NX_SUCCESS)
1066 {
1067
1068 /* Release the allocated socket memory block. */
1069 tx_block_release(socket_memory);
1070
1071 /* Release the mutex. */
1072 tx_mutex_put(nx_bsd_protection_ptr);
1073
1074 /* Set the socket error if extended socket options enabled. */
1075 nx_bsd_set_errno(EINVAL);
1076
1077 /* Error getting NetX socket memory. */
1078 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1079 return(NX_SOC_ERROR);
1080 }
1081
1082 /* Save the UDP pointer in the BSD socket. */
1083 bsd_socket_ptr -> nx_bsd_socket_udp_socket = udp_socket_ptr;
1084
1085 /* Set the reserved UDP socket pointer back to the BSD socket. */
1086 udp_socket_ptr -> nx_udp_socket_reserved_ptr = (VOID *) (i + 0x00010000);
1087 }
1088 }
1089 #if defined(NX_ENABLE_IP_RAW_PACKET_FILTER) || defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT)
1090 else if (type == SOCK_RAW)
1091 {
1092
1093 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
1094 /* Check if raw sockets are enabled in NetX Duo. */
1095 if (((protocolFamily == AF_INET) ||
1096 (protocolFamily == AF_INET6)) &&
1097 (nx_bsd_default_ip -> nx_ip_raw_ip_processing == NX_NULL))
1098 {
1099 /* No, Enable raw socket handling in NetX Duo. */
1100 status = nx_ip_raw_packet_enable(nx_bsd_default_ip);
1101
1102 if (status != NX_SUCCESS)
1103 {
1104
1105 /* Release the mutex. */
1106 tx_mutex_put(nx_bsd_protection_ptr);
1107
1108 nx_bsd_set_errno(EPROTONOSUPPORT);
1109
1110 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1111 return NX_SOC_ERROR;
1112 }
1113 }
1114
1115 /* Check if we set the packet filter already. */
1116 if (((protocolFamily == AF_INET) ||
1117 (protocolFamily == AF_INET6)) &&
1118 (nx_bsd_default_ip -> nx_ip_raw_packet_filter == NX_NULL))
1119 {
1120
1121 /* We have not. Do so now. Set the raw packet filter to the IP instance. */
1122 status = nx_ip_raw_packet_filter_set(nx_bsd_default_ip, nx_bsd_raw_packet_filter);
1123
1124 /* Has a raw packet filter been successfully set? */
1125 if (status != NX_SUCCESS)
1126 {
1127
1128 /* Release the mutex. */
1129 tx_mutex_put(nx_bsd_protection_ptr);
1130
1131 nx_bsd_set_errno(EPROTONOSUPPORT);
1132
1133 /* No, return error status. */
1134 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1135 return NX_SOC_ERROR;
1136 }
1137 }
1138
1139 /* For IPv6 raw socket, by default the header is not included in the received packet. */
1140 if(protocolFamily == AF_INET6)
1141 {
1142 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_RX_NO_HDR;
1143 }
1144
1145 /* Set the raw socket protocol to the BSD raw socket. */
1146 bsd_socket_ptr -> nx_bsd_socket_protocol = (USHORT)protocol;
1147 bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_RAW_SOCKET;
1148
1149 /* Calculate the hash index in the raw socket protocol table. */
1150 index = (UINT) ((protocol + (protocol >> 8)) & NX_BSD_SOCKET_RAW_PROTOCOL_TABLE_MASK);
1151
1152 /* Determine if the list is NULL. */
1153 if(nx_bsd_socket_raw_protocol_table[index])
1154 {
1155 /* There are already sockets on the list... just add this one to the end. */
1156 bsd_socket_ptr -> nx_bsd_socket_next = nx_bsd_socket_raw_protocol_table[index];
1157 bsd_socket_ptr -> nx_bsd_socket_previous = (nx_bsd_socket_raw_protocol_table[index]) -> nx_bsd_socket_previous;
1158 ((nx_bsd_socket_raw_protocol_table[index]) -> nx_bsd_socket_previous) -> nx_bsd_socket_next = bsd_socket_ptr;
1159 (nx_bsd_socket_raw_protocol_table[index]) -> nx_bsd_socket_previous = bsd_socket_ptr;
1160 }
1161 else
1162 {
1163 /* Nothing is on the list. Add this one to an empty list. */
1164 bsd_socket_ptr -> nx_bsd_socket_next = bsd_socket_ptr;
1165 bsd_socket_ptr -> nx_bsd_socket_previous = bsd_socket_ptr;
1166 nx_bsd_socket_raw_protocol_table[index] = bsd_socket_ptr;
1167 }
1168 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
1169
1170 if(protocolFamily == AF_PACKET)
1171 {
1172 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
1173 bsd_socket_ptr -> nx_bsd_socket_create_id = nx_bsd_socket_create_id;
1174 nx_bsd_socket_create_id++;
1175 #elif defined(NX_BSD_RAW_SUPPORT)
1176 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
1177 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
1178 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
1179 }
1180
1181 }
1182 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER || NX_BSD_RAW_PPPOE_SUPPORT || NX_BSD_RAW_SUPPORT */
1183
1184 else
1185 {
1186 /* Not a supported socket type. */
1187 nx_bsd_set_errno(EOPNOTSUPP);
1188
1189 /* Invalid type. */
1190 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1191 return(NX_SOC_ERROR);
1192 }
1193
1194 /* Set the protocol family: AF_INET or AF_INET6. */
1195 bsd_socket_ptr -> nx_bsd_socket_family = (ULONG)protocolFamily;
1196
1197 /* For UDP and RAW sockets, set the maximum receive queue depth. */
1198 if(bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
1199 {
1200
1201 bsd_socket_ptr -> nx_bsd_socket_received_packet_count_max = NX_BSD_SOCKET_QUEUE_MAX;
1202 }
1203
1204 /* Check for error creating the NetX Duo socket. */
1205 if (status != NX_SUCCESS)
1206 {
1207
1208 /* Release the BSD protection. */
1209
1210 /* Clear the BSD socket in use flag. */
1211 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_IN_USE);
1212
1213 if ((type == SOCK_DGRAM) || (type == SOCK_STREAM))
1214 {
1215 /* Release the socket memory block allocated for TCP or UDP socket. */
1216 tx_block_release(socket_memory);
1217 }
1218
1219 /* Release the mutex. */
1220 tx_mutex_put(nx_bsd_protection_ptr);
1221
1222 /* Set the socket error if extended socket options enabled. */
1223 nx_bsd_set_errno(EINVAL);
1224
1225 /* Error present, return error code. */
1226 NX_BSD_ERROR(status, __LINE__);
1227 return(NX_SOC_ERROR);
1228 }
1229
1230 /* Release the mutex. */
1231 tx_mutex_put(nx_bsd_protection_ptr);
1232
1233 /* Return success! */
1234 return(i + NX_BSD_SOCKFD_START);
1235 }
1236
1237
1238 /**************************************************************************/
1239 /* */
1240 /* FUNCTION RELEASE */
1241 /* */
1242 /* connect PORTABLE C */
1243 /* 6.3.0 */
1244 /* AUTHOR */
1245 /* */
1246 /* Yuxin Zhou, Microsoft Corporation */
1247 /* */
1248 /* DESCRIPTION */
1249 /* */
1250 /* Establishes a connection between a client socket and a remote server*/
1251 /* socket associated with the remote address, if any. Upon returning */
1252 /* successfully, the given socket's local and remote IP address and */
1253 /* port information are filled in. If the socket was not previously */
1254 /* bound to a local port, one is assigned randomly. */
1255 /* */
1256 /* For TCP sockets, connect() completes with a connection handshake is */
1257 /* complete, or if an error occurs. A TCP negotiation is performed */
1258 /* to open a connection and success implies the existence of a reliable*/
1259 /* channel to that socket. */
1260 /* */
1261 /* For UDP sockets, the connection is established simply by setting the*/
1262 /* supplied destination (remote) IP address and port for the remote */
1263 /* host. */
1264 /* */
1265 /* For non blocking sockets, the function returns immediately if a */
1266 /* connection is not possible. The socket thread error is set to */
1267 /* EINPROGRESS to distinguish from blocking sockets. */
1268 /* */
1269 /* INPUT */
1270 /* */
1271 /* sockID Socket descriptor */
1272 /* *remoteAddress Remote address structure */
1273 /* addressLength Address structure length */
1274 /* */
1275 /* OUTPUT */
1276 /* */
1277 /* NX_SOC_OK (0) If success */
1278 /* NX_SOC_ERROR (-1) If failure or if called with */
1279 /* an UDP socket */
1280 /* */
1281 /* CALLS */
1282 /* */
1283 /* nx_ip_status_check Check to make sure link is up */
1284 /* nx_tcp_client_socket_bind Bind a TCP socket to a port */
1285 /* nxd_tcp_client_socket_connect Connect to a TCP server */
1286 /* tx_mutex_get Get protection */
1287 /* tx_mutex_put Release protection */
1288 /* tx_thread_identify Get current thread pointer */
1289 /* */
1290 /* CALLED BY */
1291 /* */
1292 /* Application Code */
1293 /* */
1294 /* RELEASE HISTORY */
1295 /* */
1296 /* DATE NAME DESCRIPTION */
1297 /* */
1298 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1299 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1300 /* resulting in version 6.1 */
1301 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
1302 /* used new API/structs naming,*/
1303 /* resulting in version 6.3.0 */
1304 /* */
1305 /**************************************************************************/
nx_bsd_connect(INT sockID,struct nx_bsd_sockaddr * remoteAddress,INT addressLength)1306 INT nx_bsd_connect(INT sockID, struct nx_bsd_sockaddr *remoteAddress, INT addressLength)
1307 {
1308 UINT status;
1309 NX_TCP_SOCKET *tcp_socket_ptr;
1310 NX_UDP_SOCKET *udp_socket_ptr;
1311 NX_BSD_SOCKET *bsd_socket_ptr;
1312 ULONG timeout;
1313 ULONG actual_status;
1314
1315 /* Check for a valid socket ID. */
1316 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
1317 {
1318
1319 /* Set the socket error. */
1320 nx_bsd_set_errno(EBADF);
1321
1322 /* Return an error. */
1323 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1324 return(NX_SOC_ERROR);
1325 }
1326
1327 /* Adjust the sockID to index into the BSD socket table. */
1328 sockID = sockID - NX_BSD_SOCKFD_START;
1329
1330 /* Ensure the IP instance has been initialized. */
1331 status = nx_ip_status_check(nx_bsd_default_ip, NX_IP_INITIALIZE_DONE, &actual_status, NX_BSD_TIMEOUT);
1332
1333 /* Check the status. */
1334 if (status != NX_SUCCESS)
1335 {
1336
1337 /* Set the socket error. */
1338 nx_bsd_set_errno(EFAULT);
1339
1340 /* Return an error. */
1341 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1342 return(NX_SOC_ERROR);
1343 }
1344
1345 /* Set a pointer to the BSD socket. */
1346 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
1347
1348 /* Make sure the socket is valid. */
1349 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
1350 {
1351
1352 /* Socket is no longer in use. */
1353
1354 /* Set the socket error if extended socket options enabled. */
1355 nx_bsd_set_errno(EBADF);
1356
1357 /* Return an error. */
1358 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1359 return(NX_SOC_ERROR);
1360 }
1361
1362 /* Obtain the BSD protection. */
1363 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
1364
1365 /* Check the status. */
1366 if (status != NX_SUCCESS)
1367 {
1368
1369 /* Set the socket error if extended socket options enabled. */
1370 nx_bsd_set_errno(EACCES);
1371
1372 /* Return an error. */
1373 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
1374 return(NX_SOC_ERROR);
1375 }
1376
1377 /* Check whether supplied address structure and length is valid */
1378 if (remoteAddress == NX_NULL )
1379 {
1380
1381 /* For UDP socket or RAW socket, a NULL remoteAddress dis-associate
1382 a remote address bound to the socket. */
1383 if (bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
1384 {
1385 memset(&bsd_socket_ptr -> nx_bsd_socket_peer_ip, 0, sizeof(NXD_ADDRESS));
1386 bsd_socket_ptr -> nx_bsd_socket_peer_port = 0;
1387
1388 /* Clear the connect flag. */
1389 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTED);
1390
1391 /* All done. Return. */
1392
1393 /* Release the mutex. */
1394 tx_mutex_put(nx_bsd_protection_ptr);
1395
1396 return(NX_SOC_OK);
1397
1398 }
1399 else
1400 {
1401 /* For TCP socket, each socket can only be connected once, and
1402 the remote address must be set correctly. */
1403
1404 /* Release the mutex. */
1405 tx_mutex_put(nx_bsd_protection_ptr);
1406 /* Set the socket error if extended socket options enabled. */
1407 nx_bsd_set_errno(EAFNOSUPPORT);
1408
1409 /* Return an error. */
1410 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1411 return(NX_SOC_ERROR);
1412 }
1413 }
1414
1415
1416 /* Check if the remote address family matches the local BSD socket address family. */
1417 if((remoteAddress -> sa_family != bsd_socket_ptr -> nx_bsd_socket_family) ||
1418 ((remoteAddress -> sa_family == AF_INET) && (addressLength != sizeof(struct nx_bsd_sockaddr_in))) ||
1419 ((remoteAddress -> sa_family == AF_INET6) && (addressLength != sizeof(struct nx_bsd_sockaddr_in6))))
1420 {
1421
1422 /* Mismatch! */
1423
1424 /* Release the mutex. */
1425 tx_mutex_put(nx_bsd_protection_ptr);
1426
1427 /* Set the socket error if extended socket options enabled. */
1428 nx_bsd_set_errno(EAFNOSUPPORT);
1429
1430 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1431 return(ERROR);
1432 }
1433
1434 #ifndef NX_DISABLE_IPV4
1435 /* Check the socket family type. */
1436 if(remoteAddress -> sa_family == AF_INET)
1437 {
1438
1439 /* This is an IPv4 socket type. */
1440
1441 /* Set the UDP remote host IP address and port for the UDP 'connection'; for NetX Duo
1442 set the IP version. */
1443 /* NetX API expects multi byte values to be in host byte order.
1444 Therefore ntohl/s are used to make the conversion. */
1445 bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_version = NX_IP_VERSION_V4;
1446 bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v4 = htonl(((struct nx_bsd_sockaddr_in *) remoteAddress ) -> sin_addr.s_addr);
1447 bsd_socket_ptr -> nx_bsd_socket_peer_port = htons(((struct nx_bsd_sockaddr_in *) remoteAddress ) -> sin_port);
1448 }
1449 else
1450 #endif /* NX_DISABLE_IPV4 */
1451
1452 #ifdef FEATURE_NX_IPV6
1453 if(remoteAddress -> sa_family == AF_INET6)
1454 {
1455
1456 /* This is an IPv6 enabled socket family type). */
1457 bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_version = NX_IP_VERSION_V6;
1458 /* NetX API expects multi byte values to be in host byte order.
1459 Therefore ntohl/s are used to make the conversion. */
1460 /* Get remote address and port. */
1461 bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[0] = htonl(((struct nx_bsd_sockaddr_in6*)remoteAddress) -> sin6_addr._S6_un._S6_u32[0]);
1462 bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[1] = htonl(((struct nx_bsd_sockaddr_in6*)remoteAddress) -> sin6_addr._S6_un._S6_u32[1]);
1463 bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[2] = htonl(((struct nx_bsd_sockaddr_in6*)remoteAddress) -> sin6_addr._S6_un._S6_u32[2]);
1464 bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[3] = htonl(((struct nx_bsd_sockaddr_in6*)remoteAddress) -> sin6_addr._S6_un._S6_u32[3]);
1465
1466 bsd_socket_ptr -> nx_bsd_socket_peer_port = htons(((struct nx_bsd_sockaddr_in6 *) remoteAddress ) -> sin6_port);
1467
1468 }
1469 else
1470 #endif /* FEATURE_NX_IPV6 */
1471 {
1472
1473 /* Address family not supported. */
1474
1475 /* Release the mutex. */
1476 tx_mutex_put(nx_bsd_protection_ptr);
1477
1478 /* Set the socket error if extended socket options enabled. */
1479 nx_bsd_set_errno(EAFNOSUPPORT);
1480
1481 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1482 return(ERROR);
1483 }
1484
1485
1486 /* Handle the UDP 'connection' request. */
1487 if (bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
1488 {
1489
1490 udp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_udp_socket;
1491
1492 /* Check to see if the UDP socket is already bound. */
1493 if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND))
1494 {
1495
1496 /* Not yet, bind to a randomly selected available free port. */
1497 status = nx_udp_socket_bind(udp_socket_ptr, NX_ANY_PORT, NX_BSD_TIMEOUT);
1498
1499 /* Check for error. */
1500 if (status != NX_SUCCESS)
1501 {
1502
1503 /* Release the mutex. */
1504 tx_mutex_put(nx_bsd_protection_ptr);
1505
1506 /* Set the socket error based on NetX error status return. */
1507 nx_bsd_set_error_code(bsd_socket_ptr, status);
1508
1509 /* Return an error. */
1510 NX_BSD_ERROR(ERROR, __LINE__);
1511 return(ERROR);
1512 }
1513
1514 /* Bind is successful. Obtain the port number. */
1515 bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)udp_socket_ptr -> nx_udp_socket_port;
1516 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
1517 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
1518 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
1519 }
1520
1521 /* Mark the socket as connected. */
1522 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
1523
1524 /* Release the mutex. */
1525 tx_mutex_put(nx_bsd_protection_ptr);
1526
1527 /* Return successful status. */
1528 return(NX_SOC_OK);
1529 }
1530 else if (bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
1531 {
1532
1533 /* This is not UDP or TCP socket. So it must be raw socket. */
1534 /* We treat raw socket the same as UDP socket. For connec, raw socket
1535 associates the remote address as its default destination address when
1536 transmit, and also limit the reception of data from that remote address. */
1537
1538 /* Mark the socket as connected. */
1539 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
1540
1541 /* Release the mutex. */
1542 tx_mutex_put(nx_bsd_protection_ptr);
1543
1544 /* Return successful status. */
1545 return(NX_SOC_OK);
1546 }
1547
1548 /* This is a TCP BSD socket. */
1549
1550 /* If the socket is already connected. */
1551 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
1552 {
1553
1554 /* If INPROGRESS is set, clear the INPROGRESS flag and return OK.
1555 The INPROGRESS flag needs to be cleared so the next connect call would return EISCONN */
1556 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_INPROGRESS)
1557 {
1558
1559 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
1560
1561 /* Release the protection mutex. */
1562 tx_mutex_put(nx_bsd_protection_ptr);
1563
1564 return(NX_SOC_OK);
1565 }
1566
1567 /* Already connected. */
1568 nx_bsd_set_errno(EISCONN);
1569
1570 tx_mutex_put(nx_bsd_protection_ptr);
1571
1572 /* Return an error. */
1573 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1574 return(NX_SOC_ERROR);
1575
1576 }
1577
1578 /* If the socket is marked as EINPROGRESS, return EALREADY. */
1579 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_INPROGRESS)
1580 {
1581
1582
1583 nx_bsd_set_errno(EALREADY);
1584
1585 /* Release the protection mutex. */
1586 tx_mutex_put(nx_bsd_protection_ptr);
1587
1588 /* Return an error. */
1589 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1590 return(NX_SOC_ERROR);
1591
1592 }
1593 /* If the socket has an error */
1594 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
1595 {
1596 INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
1597
1598 /* Now clear the error code. */
1599 bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
1600
1601 /* Clear the error flag. The application is expected to close the socket at this point.*/
1602 bsd_socket_ptr -> nx_bsd_socket_status_flags =
1603 bsd_socket_ptr -> nx_bsd_socket_status_flags & ((ULONG)(~NX_BSD_SOCKET_ERROR));
1604
1605 nx_bsd_set_errno(errcode);
1606
1607 /* Release the protection mutex. */
1608 tx_mutex_put(nx_bsd_protection_ptr);
1609
1610 /* Return an error. */
1611 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1612
1613 /* At this point the error flag is cleared. Application should
1614 detect and handle the error codition. This socket is still bound
1615 to the port (either the application called bind(), or a bind
1616 operation was executed as part of the connect call) is able to
1617 handle another "connect" call, or be closed. */
1618 return(NX_SOC_ERROR);
1619 }
1620
1621 /* Set a NetX tcp pointer. */
1622 tcp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
1623
1624 /* Mark this as a client TCP socket. */
1625 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CLIENT;
1626
1627 /* Is the TCP socket already bound? */
1628 if (tcp_socket_ptr -> nx_tcp_socket_port == 0)
1629 {
1630
1631 /* Not yet; bind to a randomly selected available free port. */
1632
1633 /* Call NetX TCP bind service with NX_NO_WAIT. */
1634 status = nx_tcp_client_socket_bind(tcp_socket_ptr, NX_ANY_PORT, NX_NO_WAIT);
1635
1636 /* Check for error. */
1637 if (status != NX_SUCCESS)
1638 {
1639
1640 /* Clear the client socket flag. */
1641 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CLIENT);
1642
1643 /* Set the socket error depending on NetX error status return. */
1644 nx_bsd_set_error_code(bsd_socket_ptr, status);
1645
1646 /* Return an error. */
1647 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1648
1649 /* Release the protection mutex. */
1650 tx_mutex_put(nx_bsd_protection_ptr);
1651
1652 return(NX_SOC_ERROR);
1653 }
1654
1655 /* Mark the socket as bound. */
1656 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
1657 bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)tcp_socket_ptr -> nx_tcp_socket_port;
1658 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
1659 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
1660
1661 }
1662
1663 /* Mark this BSD socket as busy. */
1664 bsd_socket_ptr -> nx_bsd_socket_busy = tx_thread_identify();
1665
1666 /* Attempt to make the connection. If the socket is non-blocking,
1667 set the timeout to 0. Otherwise, use wait-forever */
1668 if (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING)
1669 {
1670
1671 /* Yes, the socket is enabled for non blocking. Do not wait. */
1672 timeout = 0;
1673 }
1674 else
1675 {
1676 /* This call may be blocked internally. Release the mutex
1677 so the nx_tcp_client_socket_connect can suspend waiting
1678 for a connection. */
1679 timeout = NX_WAIT_FOREVER;
1680 tx_mutex_put(nx_bsd_protection_ptr);
1681 }
1682
1683 /* Make the connection. */
1684 status = nxd_tcp_client_socket_connect(tcp_socket_ptr, &(bsd_socket_ptr -> nx_bsd_socket_peer_ip), bsd_socket_ptr -> nx_bsd_socket_peer_port, timeout);
1685 if(timeout != 0)
1686 {
1687 /* The mutex was released prior to the call. Accquire the mutex
1688 again. */
1689 tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
1690
1691 /* Verify that the socket is still valid. */
1692 if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
1693 {
1694 /* The socket is no longer in use. */
1695
1696 /* Set the socket error code. */
1697 nx_bsd_set_errno(EBADF);
1698
1699 /* Release the protection mutex. */
1700 tx_mutex_put(nx_bsd_protection_ptr);
1701
1702 /* Return error code. */
1703 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1704 return(NX_SOC_ERROR);
1705 }
1706
1707 if (status == NX_NOT_CONNECTED)
1708 {
1709
1710 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR) ||
1711 (tcp_socket_ptr -> nx_tcp_socket_timeout_retries >= tcp_socket_ptr -> nx_tcp_socket_timeout_max_retries))
1712 {
1713
1714 /* Connect timeouts since NX_BSD_SOCKET_ERROR is not set or
1715 * number of timeout retry has been exceeded. */
1716 status = NX_WAIT_ABORTED;
1717 }
1718
1719 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
1720 bsd_socket_ptr -> nx_bsd_socket_error_code = ENOTCONN;
1721 }
1722 }
1723
1724 /* Check for an error. */
1725 if (status != NX_SUCCESS)
1726 {
1727
1728 /* Set the socket error depending on NetX error status return. */
1729 nx_bsd_set_error_code(bsd_socket_ptr, status);
1730
1731
1732 /* Make sure this thread is still the owner. */
1733 if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
1734 {
1735
1736 /* Clear the busy flag. */
1737 bsd_socket_ptr -> nx_bsd_socket_busy = TX_NULL;
1738 }
1739
1740 /* Release the protection mutex. */
1741 tx_mutex_put(nx_bsd_protection_ptr);
1742
1743 /* Return error code. */
1744 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1745 return(NX_SOC_ERROR);
1746 }
1747
1748 /* At this point NX TCP connect service returns success, so the connection is established. */
1749
1750 /* Mark the socket as connected. */
1751 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
1752
1753 /* Clear the CONNECTION_INPROGRESS flag. */
1754 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
1755
1756 /* Mark the connection_request flag */
1757 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_REQUEST;
1758
1759 /* Make sure thread making the bind call is the current thread. */
1760 if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
1761 {
1762
1763 /* OK to clear the busy flag. */
1764 bsd_socket_ptr -> nx_bsd_socket_busy = TX_NULL;
1765
1766 /* Check if the connect call was successful. */
1767 if (status == NX_SUCCESS)
1768 {
1769
1770 /* It was. Release the protection mutex. */
1771 tx_mutex_put(nx_bsd_protection_ptr);
1772
1773 /* Successful connection. Return the success status. */
1774 return(NX_SOC_OK);
1775 }
1776 }
1777
1778 /* Error condition: the thread that was executing connect is not the current thread. */
1779
1780 /* Clear the connected flags and peer infomration .*/
1781 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTED);
1782 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_REQUEST);
1783 memset(&bsd_socket_ptr -> nx_bsd_socket_source_ip_address, 0, sizeof(NXD_ADDRESS));
1784 bsd_socket_ptr -> nx_bsd_socket_source_port = 0;
1785
1786 /* Release the protection mutex. */
1787 tx_mutex_put(nx_bsd_protection_ptr);
1788
1789 /* Set the socket error. */
1790 nx_bsd_set_errno(EINTR);
1791
1792 /* Return an error. */
1793 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1794 return(NX_SOC_ERROR);
1795 }
1796
1797 /**************************************************************************/
1798 /* */
1799 /* FUNCTION RELEASE */
1800 /* */
1801 /* bind PORTABLE C */
1802 /* 6.3.0 */
1803 /* AUTHOR */
1804 /* */
1805 /* Yuxin Zhou, Microsoft Corporation */
1806 /* */
1807 /* DESCRIPTION */
1808 /* */
1809 /* This function binds a socket to a local port. The port in the struct*/
1810 /* in the struct sockaddr structure may be wildcarded, in which case */
1811 /* NetX will select a port number. */
1812 /* */
1813 /* To wildcard the port, set the sin_port field of the address to 0. */
1814 /* */
1815 /* INPUT */
1816 /* */
1817 /* sockID Socket descriptor */
1818 /* *localAddress Populated socket address */
1819 /* addressLength Socket address length */
1820 /* */
1821 /* OUTPUT */
1822 /* */
1823 /* NX_SOC_OK (0) If success */
1824 /* NX_SOC_ERROR (-1) If failure */
1825 /* */
1826 /* CALLS */
1827 /* */
1828 /* nx_ip_status_check Check for link up */
1829 /* nx_tcp_client_socket_bind Binds a TCP socket to a port */
1830 /* nx_udp_client_socket_bind Binds a UDP socket to a port */
1831 /* tx_mutex_get Get protection */
1832 /* tx_mutex_put Release protection */
1833 /* tx_thread_identify Gets the current thread */
1834 /* */
1835 /* CALLED BY */
1836 /* */
1837 /* Application Code */
1838 /* */
1839 /* RELEASE HISTORY */
1840 /* */
1841 /* DATE NAME DESCRIPTION */
1842 /* */
1843 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
1844 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
1845 /* resulting in version 6.1 */
1846 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
1847 /* used new API/structs naming,*/
1848 /* resulting in version 6.3.0 */
1849 /* */
1850 /**************************************************************************/
nx_bsd_bind(INT sockID,const struct nx_bsd_sockaddr * localAddress,INT addressLength)1851 INT nx_bsd_bind(INT sockID, const struct nx_bsd_sockaddr *localAddress, INT addressLength)
1852 {
1853
1854 INT local_port = 0;
1855 UINT status;
1856 NX_TCP_SOCKET *tcp_socket_ptr;
1857 NX_UDP_SOCKET *udp_socket_ptr;
1858 NX_BSD_SOCKET *bsd_socket_ptr;
1859 INT i;
1860 INT address_conflict;
1861
1862
1863 /* Check for invalid socket ID. */
1864 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
1865 {
1866
1867 /* Set the socket error. */
1868 nx_bsd_set_errno(EBADF);
1869
1870 /* Error, invalid socket ID. */
1871 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1872 return(NX_SOC_ERROR);
1873 }
1874
1875 /* Check for a valid input local address and address length input buffer. */
1876 if ((localAddress == NX_NULL ) || (addressLength == 0))
1877 {
1878
1879 /* Set the socket error if extended socket options enabled. */
1880 nx_bsd_set_errno(EFAULT);
1881
1882 /* Error, invalid local address. */
1883 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1884 return(NX_SOC_ERROR);
1885 }
1886
1887 if (((localAddress -> sa_family == AF_INET) && (addressLength != sizeof(struct nx_bsd_sockaddr_in))) ||
1888 ((localAddress -> sa_family == AF_INET6) && (addressLength != sizeof(struct nx_bsd_sockaddr_in6))))
1889 {
1890 nx_bsd_set_errno(EAFNOSUPPORT);
1891
1892 /* Return an error. */
1893 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1894 return(NX_SOC_ERROR);
1895 }
1896
1897 /* Normalize the socket ID. */
1898 sockID = sockID - NX_BSD_SOCKFD_START;
1899
1900 /* Get the protection mutex. */
1901 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
1902
1903 /* Check the status. */
1904 if (status != NX_SUCCESS)
1905 {
1906
1907 /* Set the socket error if extended socket options enabled. */
1908 nx_bsd_set_errno(EACCES);
1909
1910 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
1911 return(NX_SOC_ERROR);
1912 }
1913
1914 /* Set up a pointer to the BSD socket. */
1915 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
1916
1917 /* See if the socket is still in use. */
1918 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
1919 {
1920
1921 /* Socket is no longer in use. */
1922
1923 /* Release the protection mutex. */
1924 tx_mutex_put(nx_bsd_protection_ptr);
1925
1926 /* Set the socket error if extended socket options enabled. */
1927 nx_bsd_set_errno(EBADF);
1928
1929 /* Return an error. */
1930 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1931 return(NX_SOC_ERROR);
1932 }
1933
1934 /* If the socket has an error */
1935 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
1936 {
1937
1938 /* Clear the error flag. The application is expected to close the socket at this point.*/
1939 bsd_socket_ptr -> nx_bsd_socket_status_flags =
1940 bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
1941
1942 nx_bsd_set_errno(bsd_socket_ptr -> nx_bsd_socket_error_code);
1943
1944 /* Clear the error code. */
1945 bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
1946
1947 /* Release the protection mutex. */
1948 tx_mutex_put(nx_bsd_protection_ptr);
1949
1950 /* Return an error. */
1951 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1952
1953 /* At this point the error flag is cleared. Application should
1954 detect and handle the error codition. This socket is still bound
1955 to the port (either the application called bind(), or a bind
1956 operation was executed as part of the connect call) is able to
1957 handle another "connect" call, or be closed. */
1958 return(NX_SOC_ERROR);
1959 }
1960
1961 /* Check the address family. */
1962 if (bsd_socket_ptr -> nx_bsd_socket_family != localAddress -> sa_family)
1963 {
1964 nx_bsd_set_errno(EAFNOSUPPORT);
1965 /* Release the protection mutex. */
1966 tx_mutex_put(nx_bsd_protection_ptr);
1967
1968 /* Return an error. */
1969 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1970 return(NX_SOC_ERROR);
1971 }
1972
1973 /* Check to see if the socket is already bound. */
1974 if (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND)
1975 {
1976
1977 /* It is. */
1978
1979 /* Set the socket error if extended socket options enabled. */
1980 nx_bsd_set_errno(EINVAL);
1981
1982 /* Release the protection mutex. */
1983 tx_mutex_put(nx_bsd_protection_ptr);
1984
1985 /* Return an error. */
1986 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
1987 return(NX_SOC_ERROR);
1988 }
1989
1990 /* Zero out the local bind info */
1991 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = 0;
1992
1993 #ifndef NX_DISABLE_IPV4
1994 if(localAddress -> sa_family == AF_INET)
1995 {
1996
1997 ULONG local_addr;
1998 INT if_index;
1999
2000 /* Pickup the local port. */
2001 local_port = ntohs(((struct nx_bsd_sockaddr_in *) localAddress) -> sin_port);
2002
2003 /* Pick up the local IP address */
2004 local_addr = ntohl(((struct nx_bsd_sockaddr_in*)localAddress) -> sin_addr.s_addr);
2005
2006 if(local_addr == INADDR_ANY)
2007 {
2008
2009 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
2010 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
2011 }
2012 else
2013 {
2014
2015 for(if_index = 0; if_index < NX_MAX_IP_INTERFACES; if_index++)
2016 {
2017
2018 if((nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_valid) &&
2019 (nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_ip_address == local_addr))
2020 {
2021
2022 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = (ULONG)(&nx_bsd_default_ip -> nx_ip_interface[if_index]);
2023 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = (UINT)if_index;
2024 break;
2025 }
2026 }
2027 }
2028 }
2029 #endif /* NX_DISABLE_IPV4 */
2030 #ifdef FEATURE_NX_IPV6
2031 if(localAddress -> sa_family == AF_INET6)
2032 {
2033
2034 ULONG ipv6_addr[4];
2035 INT if_index;
2036
2037 /* Pickup the local port. */
2038 local_port = ntohs(((struct nx_bsd_sockaddr_in6 *) localAddress) -> sin6_port);
2039
2040 ipv6_addr[0] = ntohl((((struct nx_bsd_sockaddr_in6*)localAddress)) -> sin6_addr._S6_un._S6_u32[0]);
2041 ipv6_addr[1] = ntohl((((struct nx_bsd_sockaddr_in6*)localAddress)) -> sin6_addr._S6_un._S6_u32[1]);
2042 ipv6_addr[2] = ntohl((((struct nx_bsd_sockaddr_in6*)localAddress)) -> sin6_addr._S6_un._S6_u32[2]);
2043 ipv6_addr[3] = ntohl((((struct nx_bsd_sockaddr_in6*)localAddress)) -> sin6_addr._S6_un._S6_u32[3]);
2044
2045 if((ipv6_addr[0] | ipv6_addr[1] | ipv6_addr[2] | ipv6_addr[3]) == 0)
2046 {
2047
2048 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
2049 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
2050 }
2051 else
2052 {
2053
2054 for(if_index = 0; if_index < NX_MAX_IPV6_ADDRESSES; if_index++)
2055 {
2056
2057 if((nx_bsd_default_ip -> nx_ipv6_address[if_index].nxd_ipv6_address[0] == ipv6_addr[0]) &&
2058 (nx_bsd_default_ip -> nx_ipv6_address[if_index].nxd_ipv6_address[1] == ipv6_addr[1]) &&
2059 (nx_bsd_default_ip -> nx_ipv6_address[if_index].nxd_ipv6_address[2] == ipv6_addr[2]) &&
2060 (nx_bsd_default_ip -> nx_ipv6_address[if_index].nxd_ipv6_address[3] == ipv6_addr[3]))
2061 {
2062
2063 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = (ULONG)(&nx_bsd_default_ip -> nx_ipv6_address[if_index]);
2064
2065 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = (UINT)if_index;
2066 break;
2067 }
2068 }
2069 }
2070 }
2071 #endif
2072 #ifdef NX_BSD_RAW_SUPPORT
2073 if ((localAddress -> sa_family == AF_PACKET) && (addressLength == sizeof(struct nx_bsd_sockaddr_ll)))
2074 {
2075 UINT if_index;
2076
2077 if_index = (UINT)(((struct nx_bsd_sockaddr_ll *)localAddress) -> sll_ifindex);
2078 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = (ULONG)(&nx_bsd_default_ip -> nx_ip_interface[if_index]);
2079 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = if_index;
2080 }
2081 #endif /* NX_BSD_RAW_SUPPORT */
2082
2083 /* Check if the bind information is correctly set. */
2084 if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == 0)
2085 {
2086
2087 /* Release the protection mutex. */
2088 tx_mutex_put(nx_bsd_protection_ptr);
2089
2090 /* Set the socket error if extended socket options enabled. */
2091 nx_bsd_set_errno(EADDRNOTAVAIL);
2092
2093 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
2094 return(NX_SOC_ERROR);
2095 }
2096
2097 /* At this point the local bind interface and port are known.
2098 If port number is specified, we need to go through the existing sockets
2099 and make sure there is no conflict. */
2100 address_conflict = 0;
2101
2102 if(local_port)
2103 {
2104
2105 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
2106 {
2107
2108 /* Skip its own entry. */
2109 if((i == sockID) ||
2110 /* Skip invalid entries. */
2111 (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE)) ||
2112 /* Skip the entries with different protocol ID */
2113 (nx_bsd_socket_array[i].nx_bsd_socket_protocol != bsd_socket_ptr -> nx_bsd_socket_protocol) ||
2114 /* Skip the unbound entries */
2115 (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND)))
2116 {
2117
2118 continue;
2119 }
2120
2121 /* Check for port number and interface ID */
2122 if(nx_bsd_socket_array[i].nx_bsd_socket_local_port == (USHORT)local_port)
2123 {
2124
2125 address_conflict = 1;
2126
2127 if((nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface == bsd_socket_ptr -> nx_bsd_socket_local_bind_interface) &&
2128 (nx_bsd_socket_array[i].nx_bsd_socket_family == bsd_socket_ptr -> nx_bsd_socket_family))
2129 {
2130
2131 /* This is completely duplicate binding. */
2132
2133 /* If it is a TCP non-listen socket (in other words a TCP server socket that is
2134 already in connection, and the REUSEADDR is set, it is OK. */
2135 if((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED) &&
2136 (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CLIENT)) &&
2137 (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR))
2138 {
2139
2140 address_conflict = 0;
2141 }
2142 }
2143 else
2144 {
2145
2146 /* If the REUSEADDR option is set, the socket can be bound to its specififed local address. */
2147 if(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR)
2148 {
2149
2150 address_conflict = 0;
2151
2152 if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
2153 {
2154
2155 UINT counter;
2156
2157 /* For UDP socket, it needs to share the underlying NetX UDP socket. */
2158 nx_udp_socket_delete(bsd_socket_ptr -> nx_bsd_socket_udp_socket);
2159
2160 /* Free the memory. */
2161 memset((VOID*)bsd_socket_ptr -> nx_bsd_socket_udp_socket, 0, sizeof(NX_UDP_SOCKET));
2162
2163 tx_block_release((VOID*)bsd_socket_ptr -> nx_bsd_socket_udp_socket);
2164
2165 /* Add this bsd udp socket to the list that map to the same NetX udp socket. */
2166
2167 /* See if this is the only bsd udp socket on the list. */
2168 if ((&nx_bsd_socket_array[i]) == nx_bsd_socket_array[i].nx_bsd_socket_next)
2169 {
2170
2171 /* Yes, the only bsd udp socket on the list. */
2172 /* Update the list. */
2173 bsd_socket_ptr -> nx_bsd_socket_next = &nx_bsd_socket_array[i];
2174 bsd_socket_ptr -> nx_bsd_socket_previous = &nx_bsd_socket_array[i];
2175 nx_bsd_socket_array[i].nx_bsd_socket_next = bsd_socket_ptr;
2176 nx_bsd_socket_array[i].nx_bsd_socket_previous = bsd_socket_ptr;
2177
2178 }
2179 else
2180 {
2181
2182 /* At least one more bsd udp socket on this list. */
2183 /* Update the list. */
2184 bsd_socket_ptr -> nx_bsd_socket_next = nx_bsd_socket_array[i].nx_bsd_socket_next;
2185 bsd_socket_ptr -> nx_bsd_socket_previous = &nx_bsd_socket_array[i];
2186 (nx_bsd_socket_array[i].nx_bsd_socket_next) -> nx_bsd_socket_previous = bsd_socket_ptr;
2187 nx_bsd_socket_array[i].nx_bsd_socket_next = bsd_socket_ptr;
2188 }
2189
2190
2191 bsd_socket_ptr -> nx_bsd_socket_udp_socket = nx_bsd_socket_array[i].nx_bsd_socket_udp_socket;
2192
2193 /* Increase the counter. */
2194 counter = (UINT)bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_reserved_ptr;
2195 counter = ((counter & 0xFFFF0000) + 0x00010000 + (counter & 0x0000FFFF)) & 0xFFFFFFFF;
2196
2197 bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_reserved_ptr = (VOID*)counter;
2198
2199 bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)local_port;
2200 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
2201
2202 /* Release the protection mutex. */
2203 tx_mutex_put(nx_bsd_protection_ptr);
2204
2205 return(NX_SOC_OK);
2206 }
2207 else if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
2208 {
2209
2210 /* Just point this BSD TCP socket to the same secondary socket. */
2211 (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id;
2212
2213 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
2214
2215 bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)local_port;
2216 #if defined(__PRODUCT_NETXDUO__) && !defined(NX_DISABLE_IPV4)
2217 /* Handle client sockets differently. Share the port here for sockets with different IP/IPv6 addresses. */
2218 if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_client_type == NX_TRUE)
2219 {
2220
2221 /* Handle client sockets differently. Share the port here for sockets with different IP/IPv6 addresses. */
2222 if (((bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6) && (nx_bsd_socket_array[i].nx_bsd_socket_family == AF_INET)) ||
2223 ((bsd_socket_ptr -> nx_bsd_socket_family == AF_INET) && (nx_bsd_socket_array[i].nx_bsd_socket_family == AF_INET6)))
2224
2225 {
2226
2227 NX_IP *ip_ptr = nx_bsd_default_ip;
2228 NX_TCP_SOCKET *socket_ptr = bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
2229
2230
2231 /* Calculate the hash index in the TCP port array of the associated IP instance. */
2232 UINT index = (UINT) ((local_port + (local_port >> 8)) & NX_TCP_PORT_TABLE_MASK);
2233
2234 /* This non server socket needs to share a port with the other client socket. */
2235 socket_ptr -> nx_tcp_socket_port = (UINT)local_port;
2236
2237
2238 tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
2239
2240 /* Add this socket to the list of bound sockets. */
2241 socket_ptr -> nx_tcp_socket_bound_next = ip_ptr -> nx_ip_tcp_port_table[index];
2242 socket_ptr -> nx_tcp_socket_bound_previous = (ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous;
2243 ((ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous) -> nx_tcp_socket_bound_next = socket_ptr;
2244 (ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous = socket_ptr;
2245
2246
2247 tx_mutex_put(&ip_ptr -> nx_ip_protection);
2248 }
2249 }
2250 #endif
2251
2252 /* Release the protection mutex. */
2253 tx_mutex_put(nx_bsd_protection_ptr);
2254
2255 return(NX_SOC_OK);
2256 }
2257 }
2258 }
2259
2260 if(address_conflict)
2261 {
2262
2263 break; /* Break out of the for loop */
2264 }
2265 }
2266 }
2267 }
2268
2269 #ifdef NX_BSD_RAW_SUPPORT
2270 if (localAddress -> sa_family == AF_PACKET)
2271 {
2272 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
2273 {
2274
2275 /* Skip its own entry. */
2276 if((i == sockID) ||
2277 /* Skip invalid entries. */
2278 (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE)) ||
2279 /* Skip the entries with different protocol ID */
2280 (nx_bsd_socket_array[i].nx_bsd_socket_protocol != bsd_socket_ptr -> nx_bsd_socket_protocol) ||
2281 /* Skip the entries with different address family. */
2282 (nx_bsd_socket_array[i].nx_bsd_socket_family != bsd_socket_ptr -> nx_bsd_socket_family) ||
2283 /* Skip the unbound entries */
2284 (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND)))
2285 {
2286
2287 continue;
2288 }
2289
2290 if (nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface_index == bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index)
2291 {
2292
2293 /* Bind to same interface. */
2294 address_conflict = 1;
2295 break;
2296 }
2297
2298 if (nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface_index == NX_BSD_LOCAL_IF_INADDR_ANY)
2299 {
2300
2301 /* A socket is bound to any interface. */
2302 address_conflict = 1;
2303 break;
2304 }
2305 }
2306 }
2307 #endif /* NX_BSD_RAW_SUPPORT */
2308
2309 if(address_conflict)
2310 {
2311
2312 /* Release the protection mutex. */
2313 tx_mutex_put(nx_bsd_protection_ptr);
2314
2315 /* Set the socket error if extended socket options enabled. */
2316 nx_bsd_set_errno(EADDRINUSE);
2317
2318 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
2319 return(NX_SOC_ERROR);
2320 }
2321
2322 /* Mark this BSD socket as busy. */
2323 bsd_socket_ptr -> nx_bsd_socket_busy = tx_thread_identify();
2324
2325 /* Determine what type of bind is required. */
2326 if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
2327 {
2328
2329 /* Setup TCP socket pointer. */
2330 tcp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
2331
2332 /* Call NetX to bind the client socket. */
2333 status = nx_tcp_client_socket_bind(tcp_socket_ptr, (UINT)local_port, NX_NO_WAIT);
2334
2335 /* Update the port. */
2336 if((status == NX_SUCCESS) && (local_port == 0))
2337 local_port = (INT)(tcp_socket_ptr -> nx_tcp_socket_port);
2338
2339 }
2340 else if (bsd_socket_ptr -> nx_bsd_socket_udp_socket)
2341 {
2342
2343 /* Set up a pointer to the UDP socket. */
2344 udp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_udp_socket;
2345
2346 /* Bind the UDP socket to the specified port in NetX. */
2347 status = nx_udp_socket_bind(udp_socket_ptr, (UINT)local_port, NX_BSD_TIMEOUT);
2348
2349 /* Update the port. */
2350 if((status == NX_SUCCESS) && (local_port == 0))
2351 local_port = (INT)(udp_socket_ptr -> nx_udp_socket_port);
2352 }
2353 else
2354 {
2355
2356 /* Raw socket. All done. Just need to set status = NX_SUCCESS and continue. */
2357 status = NX_SUCCESS;
2358 }
2359
2360
2361 /* Check if we were able to bind the port. */
2362 if (status == NX_SUCCESS)
2363 {
2364
2365 bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)local_port;
2366 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
2367
2368
2369 /* Make sure this thread is still the owner. */
2370 if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
2371 {
2372
2373 /* Clear the busy flag. */
2374 bsd_socket_ptr -> nx_bsd_socket_busy = TX_NULL;
2375 }
2376
2377 /* Release the protection mutex. */
2378 tx_mutex_put(nx_bsd_protection_ptr);
2379
2380 /* Return successful status. */
2381 return(NX_SOC_OK);
2382
2383 }
2384
2385 /* Release the protection mutex. */
2386 tx_mutex_put(nx_bsd_protection_ptr);
2387
2388 /* Set the socket error, if extended socket options enabled, depending on the status returned by NetX. */
2389 nx_bsd_set_error_code(bsd_socket_ptr, status);
2390
2391 /* Return an error, unsuccessful socket bind call. */
2392 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2393 return(NX_SOC_ERROR);
2394
2395 }
2396
2397
2398 /**************************************************************************/
2399 /* */
2400 /* FUNCTION RELEASE */
2401 /* */
2402 /* listen PORTABLE C */
2403 /* 6.3.0 */
2404 /* AUTHOR */
2405 /* */
2406 /* Yuxin Zhou, Microsoft Corporation */
2407 /* */
2408 /* DESCRIPTION */
2409 /* */
2410 /* This function sets the given socket ready to accept incoming client */
2411 /* connections. The socket must already be associated with a local port*/
2412 /* which means the bind() must have been called previously. */
2413 /* After this call, incoming TCP connections requests addressed to the */
2414 /* local port (and IP address, if specified previously) will be */
2415 /* completed & queued until they are passed to the program via accept()*/
2416 /* */
2417 /* INPUT */
2418 /* */
2419 /* sockID socket descriptor */
2420 /* backlog Maximum number of new */
2421 /* connections queued */
2422 /* */
2423 /* */
2424 /* OUTPUT */
2425 /* */
2426 /* NX_SOC_OK (0) If success */
2427 /* NX_SOC_ERROR (-1) If failure. */
2428 /* */
2429 /* CALLS */
2430 /* */
2431 /* socket Create a server socket */
2432 /* nx_tcp_server_socket_listen Enable a server socket listen */
2433 /* tx_mutex_get Get protection */
2434 /* tx_mutex_put Release protection */
2435 /* */
2436 /* */
2437 /* CALLED BY */
2438 /* */
2439 /* Application Code */
2440 /* */
2441 /* RELEASE HISTORY */
2442 /* */
2443 /* DATE NAME DESCRIPTION */
2444 /* */
2445 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2446 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
2447 /* resulting in version 6.1 */
2448 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
2449 /* used new API/structs naming,*/
2450 /* resulting in version 6.3.0 */
2451 /* */
2452 /**************************************************************************/
nx_bsd_listen(INT sockID,INT backlog)2453 INT nx_bsd_listen(INT sockID, INT backlog)
2454 {
2455
2456 UINT status;
2457 NX_BSD_SOCKET *bsd_socket_ptr;
2458 NX_BSD_SOCKET *bsd_secondary_socket;
2459 INT secondary_sockID;
2460 INT ret;
2461
2462
2463 /* Check whether supplied socket ID is valid. */
2464 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
2465 {
2466
2467 /* Set the socket error if extended socket options enabled. */
2468 nx_bsd_set_errno(EBADF);
2469
2470 /* Return an error. */
2471 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2472 return(NX_SOC_ERROR);
2473 }
2474
2475 /* Normalize the socket ID. */
2476 sockID = sockID - NX_BSD_SOCKFD_START;
2477
2478 /* Get the protection mutex. */
2479 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
2480
2481 /* Check the status. */
2482 if (status)
2483 {
2484
2485 /* Set the socket error if extended socket options enabled. */
2486 nx_bsd_set_errno(EACCES);
2487
2488 /* Return an error. */
2489 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
2490 return(NX_SOC_ERROR);
2491 }
2492
2493 /* Set up a pointer to the BSD socket. */
2494 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
2495
2496 /* Determine if the socket is a UDP socket or raw */
2497 if (bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
2498 {
2499
2500 /* The underlying protocol is not TCP, therefore it does not support the listen operation. */
2501 nx_bsd_set_errno(EOPNOTSUPP);
2502
2503 /* Release the protection mutex. */
2504 tx_mutex_put(nx_bsd_protection_ptr);
2505
2506 /* Return an error code. */
2507 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2508 return(NX_SOC_ERROR);
2509 }
2510
2511 /* Is the socket still in use? */
2512 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
2513 {
2514
2515 /* Set the socket error if extended socket options enabled. */
2516 nx_bsd_set_errno(EBADF);
2517
2518 /* Release the protection mutex. */
2519 tx_mutex_put(nx_bsd_protection_ptr);
2520
2521 /* Return error code. */
2522 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2523 return(NX_SOC_ERROR);
2524 }
2525
2526 /* Check if the socket has an error */
2527 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
2528 {
2529 INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
2530
2531 /* Now clear the error code. */
2532 bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
2533
2534 /* Clear the error flag. The application is expected to close the socket at this point.*/
2535 bsd_socket_ptr -> nx_bsd_socket_status_flags =
2536 bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
2537
2538 nx_bsd_set_errno(errcode);
2539
2540 /* Release the protection mutex. */
2541 tx_mutex_put(nx_bsd_protection_ptr);
2542
2543 /* Return an error. */
2544 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2545
2546 /* At this point the error flag is cleared. Application should
2547 detect and handle the error codition. This socket is still bound
2548 to the port (either the application called bind(), or a bind
2549 operation was executed as part of the connect call) is able to
2550 handle another "connect" call, or be closed. */
2551 return(NX_SOC_ERROR);
2552 }
2553
2554 /* Have we already started listening? */
2555 if (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN)
2556 {
2557
2558 /* Error, socket is already listening. */
2559
2560 /* Release the protection mutex. */
2561 tx_mutex_put(nx_bsd_protection_ptr);
2562
2563 /* Set the socket error if extended socket options enabled. */
2564 nx_bsd_set_errno(EINVAL);
2565
2566 /* Return error code. */
2567 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2568 return(NX_SOC_ERROR);
2569 }
2570
2571 /* Check if this is a secondary server socket. */
2572 if (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET)
2573 {
2574
2575 /* Error, socket is a secondary server socket. */
2576
2577 /* Release the protection mutex. */
2578 tx_mutex_put(nx_bsd_protection_ptr);
2579
2580 /* Set the socket error if extended socket options enabled. */
2581 nx_bsd_set_errno(EOPNOTSUPP);
2582
2583 /* Return error code. */
2584 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2585 return(NX_SOC_ERROR);
2586 }
2587
2588 /* Check if bound to a port. */
2589 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND))
2590 {
2591
2592 /* Release the protection mutex. */
2593 tx_mutex_put(nx_bsd_protection_ptr);
2594
2595 /* Set the socket error code. */
2596 nx_bsd_set_errno(EDESTADDRREQ);
2597
2598 /* Return error code. */
2599 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2600 return(NX_SOC_ERROR);
2601 }
2602
2603 /* Check if this master (listening) socket's secondary socket is not marked invalid. If not, it means this socket will
2604 share the secondary socket with another master socket. */
2605 if((bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id != NX_BSD_MAX_SOCKETS)
2606 {
2607
2608 /* It is set. */
2609
2610 secondary_sockID = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id;
2611
2612 bsd_secondary_socket = &nx_bsd_socket_array[secondary_sockID];
2613
2614 /* Now check if the other master socket is in listen mode. */
2615 if(bsd_secondary_socket -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN)
2616 {
2617
2618 /* It is ready.. we are ready to listen on this socket. */
2619
2620 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ENABLE_LISTEN;
2621 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET);
2622 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_client_type = NX_FALSE;
2623 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_SERVER_MASTER_SOCKET;
2624
2625 /* Release the protection mutex. */
2626 tx_mutex_put(nx_bsd_protection_ptr);
2627
2628 return(NX_SOC_OK);
2629 }
2630 }
2631
2632 if(backlog < NX_BSD_TCP_LISTEN_MIN_BACKLOG)
2633 {
2634 backlog = NX_BSD_TCP_LISTEN_MIN_BACKLOG;
2635 }
2636
2637 /* We need to set up this socket as a listen socket. */
2638 ret = nx_bsd_tcp_create_listen_socket(sockID, backlog);
2639
2640 /* Release the mutex protection. */
2641 tx_mutex_put(nx_bsd_protection_ptr);
2642
2643 /* Return success. */
2644 return(ret);
2645 }
2646
2647
2648 /**************************************************************************/
2649 /* */
2650 /* FUNCTION RELEASE */
2651 /* */
2652 /* accept PORTABLE C */
2653 /* 6.3.0 */
2654 /* AUTHOR */
2655 /* */
2656 /* Yuxin Zhou, Microsoft Corporation */
2657 /* */
2658 /* DESCRIPTION */
2659 /* */
2660 /* This function blocks while waiting for connections addressed to the */
2661 /* IP address and port to which this socket is bound. A listen() must */
2662 /* previously have been called on this given socket. */
2663 /* */
2664 /* When a connection arrives and the TCP handshake is successfully */
2665 /* completed, this function returns with a new socket with local and */
2666 /* remote address and port numbers filled in. */
2667 /* */
2668 /* For non blocking sockets, this function returns immediately. */
2669 /* */
2670 /* INPUT */
2671 /* */
2672 /* sockID socket descriptor */
2673 /* clientAddress Originating socket IP address */
2674 /* and port. */
2675 /* addressLength Length of sockaddr buffer (in)*/
2676 /* returned address (out) */
2677 /* */
2678 /* OUTPUT */
2679 /* */
2680 /* socket id Socket ID for new connection */
2681 /* NX_SOC_ERROR (-1) If failure */
2682 /* */
2683 /* CALLS */
2684 /* */
2685 /* memset Clears memory */
2686 /* socket Create a server socket */
2687 /* nx_tcp_server_socket_relisten Relisten with a new TCP soc */
2688 /* nx_tcp_server_socket_accept Accept a client connection */
2689 /* tx_mutex_get Get protection */
2690 /* tx_mutex_put Release protection */
2691 /* tx_thread_identify Gets the current thread */
2692 /* */
2693 /* CALLED BY */
2694 /* */
2695 /* Application Code */
2696 /* */
2697 /* RELEASE HISTORY */
2698 /* */
2699 /* DATE NAME DESCRIPTION */
2700 /* */
2701 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
2702 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
2703 /* verified memcpy use cases, */
2704 /* resulting in version 6.1 */
2705 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
2706 /* used new API/structs naming,*/
2707 /* resulting in version 6.3.0 */
2708 /* */
2709 /**************************************************************************/
nx_bsd_accept(INT sockID,struct nx_bsd_sockaddr * ClientAddress,INT * addressLength)2710 INT nx_bsd_accept(INT sockID, struct nx_bsd_sockaddr *ClientAddress, INT *addressLength)
2711 {
2712 /* Define the accept function if NetX BSD accept() is not set to asynchronous (on automatic callback). */
2713
2714 UINT status;
2715 NX_BSD_SOCKET *bsd_socket_ptr;
2716 NX_BSD_SOCKET *bsd_secondary_socket;
2717 INT sec_sock_id;
2718 INT ret = 0;
2719 INT connected = 0;
2720 ULONG requested_events;
2721 INT secondary_socket_id = 0;
2722 #ifndef NX_DISABLE_IPV4
2723 struct nx_bsd_sockaddr_in
2724 peer4_address;
2725 #endif /* NX_DISABLE_IPV4 */
2726 #ifdef FEATURE_NX_IPV6
2727 struct nx_bsd_sockaddr_in6
2728 peer6_address;
2729 #endif
2730
2731
2732 /* Check for valid socket ID. */
2733 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
2734 {
2735
2736 /* Set the socket error if extended socket options enabled. */
2737 nx_bsd_set_errno(EBADF);
2738
2739 /* Return an error.*/
2740 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2741 return(NX_SOC_ERROR);
2742 }
2743
2744 /* Normalize the socket ID. */
2745 sockID = sockID - NX_BSD_SOCKFD_START;
2746
2747 /* Setup pointer to the BSD socket. */
2748 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
2749
2750 /* Get the protection mutex. */
2751 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
2752
2753 /* Check the status. */
2754 if (status != NX_SUCCESS)
2755 {
2756
2757 /* Set the socket error if extended socket options enabled. */
2758 nx_bsd_set_errno(EACCES);
2759
2760 /* Return an error.*/
2761 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
2762 return(NX_SOC_ERROR);
2763 }
2764
2765 /* Is the socket still in use? */
2766 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
2767 {
2768
2769 /* Release the protection mutex. */
2770 tx_mutex_put(nx_bsd_protection_ptr);
2771
2772 /* Set the socket error if extended socket options enabled. */
2773 nx_bsd_set_errno(EBADF);
2774
2775 /* Return an error. */
2776 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2777 return(NX_SOC_ERROR);
2778 }
2779
2780 /* If the socket has an error */
2781 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
2782 {
2783
2784 INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
2785
2786 /* Now clear the error code. */
2787 bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
2788
2789 /* Clear the error flag. The application is expected to close the socket at this point.*/
2790 bsd_socket_ptr -> nx_bsd_socket_status_flags =
2791 bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
2792
2793 nx_bsd_set_errno(errcode);
2794
2795 /* Release the protection mutex. */
2796 tx_mutex_put(nx_bsd_protection_ptr);
2797
2798 /* Return an error. */
2799 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2800
2801 /* At this point the error flag is cleared. Application should
2802 detect and handle the error codition. This socket is still bound
2803 to the port (either the application called bind(), or a bind
2804 operation was executed as part of the connect call) is able to
2805
2806 handle another "connect" call, or be closed. */
2807 return(NX_SOC_ERROR);
2808 }
2809
2810 /* Determine if the socket is a UDP socket. */
2811 if (bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
2812 {
2813
2814 /* Error, UDP or raw sockets do not perform listen. */
2815
2816 /* Release the protection mutex. */
2817 tx_mutex_put(nx_bsd_protection_ptr);
2818
2819 /* Set the socket error if extended socket options enabled. */
2820 nx_bsd_set_errno(EOPNOTSUPP);
2821
2822 /* Return error code. */
2823 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2824 return(NX_SOC_ERROR);
2825 }
2826
2827 /* Has listening been enabled on this socket? */
2828 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN))
2829 {
2830
2831 /* No, this socket is not ready to accept TCP connections. */
2832
2833 /* Release the protection mutex. */
2834 tx_mutex_put(nx_bsd_protection_ptr);
2835
2836 /* Set the socket error if extended socket options enabled. */
2837 nx_bsd_set_errno(EINVAL);
2838
2839 /* Return error code. */
2840 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2841 return(NX_SOC_ERROR);
2842 }
2843
2844 /* Make sure the accept call operates on the master socket. */
2845 if((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) == 0)
2846 {
2847 /* This is not a master socket.
2848 BSD accept is only allowed on the master socket.
2849 Return. */
2850
2851 /* Release the protection mutex. */
2852 tx_mutex_put(nx_bsd_protection_ptr);
2853
2854 /* Set the socket error if extended socket options enabled. */
2855 nx_bsd_set_errno(EBADF);
2856
2857 /* Return error code. */
2858 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2859 return(NX_SOC_ERROR);
2860 }
2861
2862 /* Validate the secondary server socket. */
2863 if ((bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id >= NX_BSD_MAX_SOCKETS)
2864 {
2865
2866 /* This secondary socket is not available yet. This could happen if the
2867 previous accept call fails to allocate a new secondary socket. */
2868 ret = nx_bsd_tcp_create_listen_socket(sockID, 0);
2869
2870 if(ret < 0)
2871 {
2872
2873 /* Failed to allocate a secondary socket, release the protection mutex. */
2874 tx_mutex_put(nx_bsd_protection_ptr);
2875
2876 /* Errno is already set inside nx_bsd_tcp_create_listen_socket. Therefore
2877 there is no need to set errno here. */
2878
2879 /* Return an error. */
2880 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2881 return(NX_SOC_ERROR);
2882 }
2883 }
2884
2885 /* At this point, we have found and marked a secondary server socket for the connection request. */
2886
2887 /* Set up a pointer to the secondary server socket. */
2888 sec_sock_id = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id;
2889 bsd_secondary_socket = &nx_bsd_socket_array[sec_sock_id];
2890
2891 /* Mark this BSD socket as busy. */
2892 bsd_socket_ptr -> nx_bsd_socket_busy = tx_thread_identify();
2893
2894 /* If the master socket is marked as non-blocking, we just need to check if the
2895 secondary socket has a connection already. */
2896 while(!connected)
2897 {
2898
2899 secondary_socket_id = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id;
2900
2901 if((secondary_socket_id < NX_BSD_MAX_SOCKETS) &&
2902 (nx_bsd_socket_array[secondary_socket_id].nx_bsd_socket_union_id.nx_bsd_socket_master_socket_id == sockID) &&
2903 (nx_bsd_socket_array[secondary_socket_id].nx_bsd_socket_status_flags & (NX_BSD_SOCKET_CONNECTED | NX_BSD_SOCKET_ERROR)))
2904 {
2905
2906 connected = 1;
2907 bsd_secondary_socket = &nx_bsd_socket_array[secondary_socket_id];
2908 bsd_secondary_socket -> nx_bsd_socket_family = bsd_socket_ptr -> nx_bsd_socket_family;
2909 bsd_secondary_socket -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
2910
2911 }
2912 else
2913 {
2914
2915 if(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING)
2916 {
2917
2918 /* No connection yet. Return EWOULDBLOCK */
2919
2920 tx_mutex_put(nx_bsd_protection_ptr);
2921
2922 /* Set the socket error if extended socket options enabled. */
2923 nx_bsd_set_errno(EWOULDBLOCK);
2924
2925 /* Return an error. */
2926 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2927
2928 if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
2929 {
2930 bsd_socket_ptr -> nx_bsd_socket_busy = NX_NULL;
2931 }
2932 return(NX_SOC_ERROR);
2933 }
2934
2935 tx_mutex_put(nx_bsd_protection_ptr);
2936 tx_event_flags_get(&nx_bsd_events, NX_BSD_RECEIVE_EVENT, TX_OR_CLEAR, &requested_events, TX_WAIT_FOREVER);
2937 tx_mutex_get(nx_bsd_protection_ptr, TX_WAIT_FOREVER);
2938
2939 /* Verify the socket is still valid. */
2940 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
2941 {
2942 /* The socket is no longer in use. */
2943
2944 /* Set the socket error code. */
2945 nx_bsd_set_errno(EBADF);
2946
2947 /* Release the protection mutex. */
2948 tx_mutex_put(nx_bsd_protection_ptr);
2949
2950 /* Return error code. */
2951 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2952 return(NX_SOC_ERROR);
2953 }
2954 }
2955 }
2956
2957 /* If we get here, we should have a valid connection, or an error occured. */
2958 if(bsd_secondary_socket -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
2959 {
2960 INT errcode = bsd_secondary_socket -> nx_bsd_socket_error_code;
2961
2962 /* Now clear the error code. */
2963 bsd_secondary_socket -> nx_bsd_socket_error_code = 0;
2964
2965 /* Clear the error flag. The application is expected to close the socket at this point.*/
2966 bsd_secondary_socket -> nx_bsd_socket_status_flags =
2967 bsd_secondary_socket -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
2968
2969 nx_bsd_set_errno(errcode);
2970
2971 /* Return an error. */
2972 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
2973
2974 /* Release the protection mutex. */
2975 tx_mutex_put(nx_bsd_protection_ptr);
2976
2977 /* At this point the error flag is cleared. Application should
2978 detect and handle the error codition. This socket is still bound
2979 to the port (either the application called bind(), or a bind
2980 operation was executed as part of the connect call) is able to
2981 handle another "connect" call, or be closed. */
2982 return(NX_SOC_ERROR);
2983 }
2984
2985 /* Update the BSD socket source port and sender IP address. */
2986 status = nxd_tcp_socket_peer_info_get(bsd_secondary_socket -> nx_bsd_socket_tcp_socket,
2987 &bsd_secondary_socket -> nx_bsd_socket_source_ip_address,
2988 (ULONG *)(&bsd_secondary_socket -> nx_bsd_socket_source_port));
2989
2990 memcpy(&bsd_secondary_socket -> nx_bsd_socket_peer_ip, &bsd_secondary_socket -> nx_bsd_socket_source_ip_address, sizeof(NXD_ADDRESS)); /* Use case of memcpy is verified. */
2991
2992 bsd_secondary_socket -> nx_bsd_socket_peer_port = (USHORT)(bsd_secondary_socket -> nx_bsd_socket_source_port);
2993
2994 /* Record the peer information. */
2995 #ifndef NX_DISABLE_IPV4
2996 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
2997 {
2998
2999 bsd_secondary_socket -> nx_bsd_socket_source_ip_address.nxd_ip_address.v4 =
3000 bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v4;
3001 }
3002 #endif /* NX_DISABLE_IPV4 */
3003 #ifdef FEATURE_NX_IPV6
3004 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
3005 {
3006
3007 bsd_secondary_socket -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[0] = bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[0];
3008 bsd_secondary_socket -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[1] = bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[1];
3009 bsd_secondary_socket -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[2] = bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[2];
3010 bsd_secondary_socket -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[3] = bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[3];
3011 }
3012 #endif
3013
3014 /* Attempt to obtain peer address if ClientAddress is not NULL. */
3015 if(ClientAddress && addressLength != 0)
3016 {
3017
3018 #ifndef NX_DISABLE_IPV4
3019 /* Handle the IPv4 socket type. */
3020 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
3021 {
3022
3023 /* Update the Client address with socket family, remote host IPv4 address and port. */
3024 peer4_address.sin_family = AF_INET;
3025 peer4_address.sin_addr.s_addr = ntohl(bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v4);
3026 peer4_address.sin_port = ntohs((USHORT)bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_port);
3027
3028 /* Copy the peer address/port info to the ClientAddress. Truncate if
3029 addressLength is smaller than the size of struct sockaddr_in */
3030 if(*addressLength > (INT)sizeof(struct nx_bsd_sockaddr_in))
3031 {
3032
3033 memcpy(ClientAddress, &peer4_address, sizeof(struct nx_bsd_sockaddr_in)); /* Use case of memcpy is verified. */
3034 *addressLength = sizeof(struct nx_bsd_sockaddr_in);
3035 }
3036 else
3037 {
3038 memcpy(ClientAddress, &peer4_address, (UINT)(*addressLength)); /* Use case of memcpy is verified. */
3039 }
3040 }
3041 else
3042 #endif /* NX_DISABLE_IPV4 */
3043
3044 #ifdef FEATURE_NX_IPV6
3045 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
3046 {
3047
3048 /* Update the Client address with socket family, remote host IPv6 address and port. */
3049 peer6_address.sin6_family = AF_INET6;
3050
3051 peer6_address.sin6_addr._S6_un._S6_u32[0] = ntohl(bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[0]);
3052 peer6_address.sin6_addr._S6_un._S6_u32[1] = ntohl(bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[1]);
3053 peer6_address.sin6_addr._S6_un._S6_u32[2] = ntohl(bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[2]);
3054 peer6_address.sin6_addr._S6_un._S6_u32[3] = ntohl(bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[3]);
3055
3056 peer6_address.sin6_port = ntohs((USHORT)bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_port);
3057
3058 if((*addressLength) > (INT)sizeof(peer6_address))
3059 {
3060
3061 memcpy(ClientAddress, &peer6_address, sizeof(peer6_address)); /* Use case of memcpy is verified. */
3062 *addressLength = sizeof(peer6_address);
3063 }
3064 else
3065 {
3066 memcpy(ClientAddress, &peer6_address, (UINT)(*addressLength)); /* Use case of memcpy is verified. */
3067 }
3068 }
3069 else
3070 #endif /* !FEATURE_NX_IPV6 */
3071 {
3072
3073 /* Release the protection mutex. */
3074 tx_mutex_put(nx_bsd_protection_ptr);
3075
3076 /* Set the socket error if extended socket options enabled. */
3077 nx_bsd_set_errno(EINVAL);
3078
3079 /* Make sure this thread is still the owner. */
3080 if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
3081 {
3082
3083 /* Clear the busy flag. */
3084 bsd_socket_ptr -> nx_bsd_socket_busy = TX_NULL;
3085 }
3086
3087 /* Error, IPv6 support is not enabled. */
3088 NX_BSD_ERROR(ERROR, __LINE__);
3089 return(ERROR);
3090 }
3091 }
3092
3093 /* Mark the sock_id field in both the master and secondary socket invalid. */
3094 (bsd_secondary_socket -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id = NX_BSD_MAX_SOCKETS;
3095
3096 /* Clear the master socket connect flags. */
3097 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTED);
3098 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_REQUEST);
3099
3100 /* Reset the master_socket_id */
3101 ret = nx_bsd_tcp_create_listen_socket(sockID, 0);
3102
3103 if(ret < 0)
3104 {
3105 (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = NX_BSD_MAX_SOCKETS;
3106 }
3107
3108 /* Make sure this thread is still the owner. */
3109 if (bsd_socket_ptr -> nx_bsd_socket_busy == tx_thread_identify())
3110 {
3111
3112 /* Clear the busy flag. */
3113 bsd_socket_ptr -> nx_bsd_socket_busy = TX_NULL;
3114 }
3115
3116 /* Release the protection mutex. */
3117 tx_mutex_put(nx_bsd_protection_ptr);
3118
3119 return(secondary_socket_id + NX_BSD_SOCKFD_START);
3120
3121 }
3122
3123 /**************************************************************************/
3124 /* */
3125 /* FUNCTION RELEASE */
3126 /* */
3127 /* nx_bsd_send_internal PORTABLE C */
3128 /* 6.3.0 */
3129 /* AUTHOR */
3130 /* */
3131 /* Yuxin Zhou, Microsoft Corporation */
3132 /* */
3133 /* DESCRIPTION */
3134 /* */
3135 /* This is sends a message to a given destination address/port */
3136 /* */
3137 /* INPUT */
3138 /* */
3139 /* sockID BSD Socket ID */
3140 /* msg Pointer to the outgoing */
3141 /* message */
3142 /* msgLength The Size of the message */
3143 /* flags Control flags, support */
3144 /* MSG_DONTWAIT */
3145 /* dst_address The Destination Address */
3146 /* dst_port The Destination Port */
3147 /* local_inteterface_index The local outgoing interface */
3148 /* to use */
3149 /* */
3150 /* OUTPUT */
3151 /* */
3152 /* data_sent */
3153 /* */
3154 /* CALLS */
3155 /* */
3156 /* set_errno Sets the BSD errno */
3157 /* nx_packet_allocate Allocate a packet */
3158 /* nx_packet_data_append Append data to the packet */
3159 /* tx_mutex_get Get Mutex protection */
3160 /* tx_mutex_put Release Mutex protection */
3161 /* nx_packet_release Release the packet on error */
3162 /* nx_udp_socket_send UDP packet send */
3163 /* nx_udp_socket_interface_send UDP packet send via a */
3164 /* specific interface */
3165 /* nx_tcp_socket_send TCP packet send */
3166 /* _nxd_bsd_ipv4_packet_send Raw IPv4 packet with header */
3167 /* included */
3168 /* _nxd_bsd_ipv6_packet_send Raw IPv6 packet with header */
3169 /* included */
3170 /* nxd_ip_raw_packet_interface_send Raw packet send via a */
3171 /* specific interface */
3172 /* CALLED BY */
3173 /* */
3174 /* send */
3175 /* sendto */
3176 /* */
3177 /* RELEASE HISTORY */
3178 /* */
3179 /* DATE NAME DESCRIPTION */
3180 /* */
3181 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3182 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3183 /* resulting in version 6.1 */
3184 /* 10-31-2023 Tiejun Zhou Modified comment(s), */
3185 /* supported random IP id, */
3186 /* resulting in version 6.3.0 */
3187 /* */
3188 /**************************************************************************/
nx_bsd_send_internal(INT sockID,const CHAR * msg,INT msgLength,INT flags,NXD_ADDRESS * dst_address,USHORT dst_port,UINT local_interface_index)3189 static INT nx_bsd_send_internal(INT sockID, const CHAR *msg, INT msgLength, INT flags,
3190 NXD_ADDRESS *dst_address, USHORT dst_port, UINT local_interface_index)
3191 {
3192 UINT status;
3193 NX_PACKET *packet_ptr;
3194 NX_TCP_SOCKET *tcp_socket_ptr;
3195 NX_UDP_SOCKET *udp_socket_ptr;
3196 NX_BSD_SOCKET *bsd_socket_ptr;
3197 UINT packet_type = 0;
3198 UINT wait_option;
3199 ULONG data_sent = (ULONG)msgLength;
3200
3201 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
3202
3203 #ifndef NX_DISABLE_IPV4
3204 /* Determine the socket family for allocating a packet. */
3205 if (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
3206 {
3207
3208 /* This is for an IPv4 socket. */
3209 if (bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
3210 {
3211
3212 /* Allocate an IPv4 UDP packet. */
3213 packet_type = NX_IPv4_UDP_PACKET;
3214 }
3215 else if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
3216 {
3217
3218 /* Allocate an IPv4 TCP packet. */
3219 packet_type = NX_IPv4_TCP_PACKET;
3220 }
3221 else if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE)
3222 {
3223
3224 packet_type = NX_PHYSICAL_HEADER;
3225 }
3226 else
3227 {
3228
3229 /* Raw socket. */
3230 packet_type = NX_IPv4_PACKET;
3231 }
3232 }
3233 #endif /* NX_DISABLE_IPV4 */
3234 if (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
3235 {
3236
3237 /* This is for an IPv6 socket. */
3238 if (bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
3239 {
3240
3241 /* Allocate an IPv4 UDP packet. */
3242 packet_type = NX_IPv6_UDP_PACKET;
3243 }
3244 else if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
3245 {
3246 /* Allocate an IPv4 TCP packet. */
3247 packet_type = NX_IPv6_TCP_PACKET;
3248 }
3249 else if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE)
3250 {
3251 packet_type = NX_PHYSICAL_HEADER;
3252 }
3253 else
3254 {
3255 /* Raw socket. */
3256 packet_type = NX_IPv6_PACKET;
3257 }
3258 }
3259
3260 /* Allocate the packet for sending. */
3261 if(packet_type == 0)
3262 {
3263 /* Set the socket error. */
3264 nx_bsd_set_errno(EINVAL);
3265
3266 /* Return an error status.*/
3267 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3268 return(NX_SOC_ERROR);
3269 }
3270
3271 /* Is this a non blocking socket? */
3272 if ((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING) ||
3273 (flags & MSG_DONTWAIT))
3274 {
3275
3276 /* Yes, set to wait to zero on the NetX call. */
3277 wait_option = 0 ;
3278 }
3279 /* Does this socket have a send timeout option set? */
3280 else if (bsd_socket_ptr -> nx_bsd_option_send_timeout)
3281 {
3282
3283 /* Yes, this is our wait option. */
3284 wait_option = bsd_socket_ptr -> nx_bsd_option_send_timeout;
3285 }
3286 else
3287 wait_option = TX_WAIT_FOREVER;
3288
3289 status = nx_packet_allocate(nx_bsd_default_packet_pool, &packet_ptr, packet_type, wait_option);
3290
3291 /* Check for errors. */
3292 if (status != NX_SUCCESS)
3293 {
3294
3295 /* Set the socket error. */
3296 nx_bsd_set_errno(ENOBUFS);
3297
3298 /* Return an error status.*/
3299 NX_BSD_ERROR(status, __LINE__);
3300 return(NX_SOC_ERROR);
3301 }
3302
3303 /* Now copy the data into the NetX packet. */
3304 status = nx_packet_data_append(packet_ptr, (VOID *) msg, (ULONG)msgLength, nx_bsd_default_packet_pool, wait_option);
3305
3306 /* Was the data copy successful? */
3307 if (status != NX_SUCCESS)
3308 {
3309
3310 nx_packet_release(packet_ptr);
3311
3312 /* Set the socket error. */
3313 nx_bsd_set_errno(ENOBUFS);
3314
3315 /* Return an error status.*/
3316 NX_BSD_ERROR(status, __LINE__);
3317 return(NX_SOC_ERROR);
3318 }
3319
3320
3321 /* Get the protection mutex. */
3322 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
3323
3324 /* Check the status. */
3325 if (status != NX_SUCCESS)
3326 {
3327
3328 /* Release the packet. */
3329 nx_packet_release(packet_ptr);
3330
3331 /* Set the socket error if extended socket options enabled. */
3332 nx_bsd_set_errno(EACCES);
3333
3334 /* Return an error status.*/
3335 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
3336 return(NX_SOC_ERROR);
3337 }
3338
3339
3340 /* Is the socket still in use? */
3341 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
3342 {
3343
3344 nx_packet_release(packet_ptr);
3345
3346 /* Set the socket error if extended options enabled. */
3347 nx_bsd_set_errno(EBADF);
3348
3349 /* Release the protection mutex. */
3350 tx_mutex_put(nx_bsd_protection_ptr);
3351
3352 /* Return an error status.*/
3353 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3354 return(NX_SOC_ERROR);
3355 }
3356
3357
3358 /* Determine if the socket is a UDP socket. */
3359 if (bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
3360 {
3361
3362 /* Pickup the NetX UDP socket. */
3363 udp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_udp_socket;
3364
3365 /* Send the UDP packet. */
3366 if(local_interface_index == NX_BSD_LOCAL_IF_INADDR_ANY)
3367 status = nxd_udp_socket_send(udp_socket_ptr, packet_ptr, dst_address, dst_port);
3368 else
3369 status = nxd_udp_socket_interface_send(udp_socket_ptr, packet_ptr, dst_address, dst_port, local_interface_index);
3370 }
3371 else if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
3372 {
3373
3374 /* We have a TCP socket and a packet ready to send. */
3375
3376 /* Set a pointer to the TCP BSD socket. */
3377 tcp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
3378
3379 if(wait_option != TX_NO_WAIT)
3380 {
3381 /* Release the protection mutex. */
3382 tx_mutex_put(nx_bsd_protection_ptr);
3383 }
3384
3385 /* Send the TCP packet. */
3386 status = nx_tcp_socket_send(tcp_socket_ptr, packet_ptr, wait_option);
3387
3388 /* Check partial data sent. */
3389 if (status)
3390 {
3391
3392 /* Get length of data sent. */
3393 data_sent -= packet_ptr -> nx_packet_length;
3394
3395 if (data_sent)
3396 {
3397
3398 /* Partial data sent. Mark as success. */
3399 status = NX_SUCCESS;
3400
3401 /* Release the packet. */
3402 nx_packet_release(packet_ptr);
3403 }
3404 }
3405
3406 if(wait_option != TX_NO_WAIT)
3407 {
3408 /* Obtain the protection mutex. */
3409 tx_mutex_get(nx_bsd_protection_ptr, TX_WAIT_FOREVER);
3410 }
3411 }
3412 else
3413 {
3414 /* Is this BSD socket configured to append the IP header? */
3415 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE)
3416 {
3417
3418 /* Yes it is. Make sure the packet source and destination interface are set. */
3419 ULONG *ip_addr_ptr;
3420 UINT src_interface;
3421
3422 #ifndef NX_DISABLE_IPV4
3423 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
3424 {
3425
3426 ip_addr_ptr = (ULONG*)(packet_ptr -> nx_packet_prepend_ptr + 12);
3427
3428 src_interface = (UINT)nx_bsd_find_interface_by_source_addr(AF_INET, ip_addr_ptr);
3429
3430 if(src_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
3431 src_interface = 0;
3432
3433 packet_ptr -> nx_packet_address.nx_packet_interface_ptr = &(nx_bsd_default_ip -> nx_ip_interface[src_interface]);
3434
3435 /* If the IP ID field is non-zero, the current nx_ip_packet_id
3436 value is modified */
3437 if((*(packet_ptr -> nx_packet_prepend_ptr + 4) == 0) &&
3438 (*(packet_ptr -> nx_packet_prepend_ptr + 5) == 0))
3439 {
3440
3441 #ifdef NX_ENABLE_IP_ID_RANDOMIZATION
3442 ULONG rand_id = (ULONG)NX_RAND();
3443 *(packet_ptr -> nx_packet_prepend_ptr + 4) = (UCHAR)((rand_id & 0xFFFF) >> 8);
3444 *(packet_ptr -> nx_packet_prepend_ptr + 5) = (UCHAR)(rand_id & 0xFF);
3445 #else
3446 *(packet_ptr -> nx_packet_prepend_ptr + 4) = (UCHAR)(((nx_bsd_default_ip -> nx_ip_packet_id) & 0xFFFF) >> 8);
3447 *(packet_ptr -> nx_packet_prepend_ptr + 5) = (UCHAR)((nx_bsd_default_ip -> nx_ip_packet_id) & 0xFF);
3448 #endif /* NX_ENABLE_IP_ID_RANDOMIZATION */
3449 }
3450
3451 /* Clear the checksum field. */
3452 *(packet_ptr -> nx_packet_prepend_ptr + 10) = 0;
3453 *(packet_ptr -> nx_packet_prepend_ptr + 11) = 0;
3454
3455 _nxd_bsd_ipv4_packet_send(packet_ptr);
3456
3457 status = NX_SUCCESS;
3458 }
3459 #endif /* NX_DISABLE_IPV4 */
3460 #ifdef FEATURE_NX_IPV6
3461 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
3462 {
3463
3464 ip_addr_ptr = (ULONG*)(packet_ptr -> nx_packet_prepend_ptr + 8);
3465 src_interface = (UINT)nx_bsd_find_interface_by_source_addr(AF_INET6, ip_addr_ptr);
3466
3467 if(src_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
3468 {
3469 status = NX_NOT_SUCCESSFUL;
3470 }
3471
3472 else
3473 {
3474
3475 NX_IPV6_HEADER *ipv6_header;
3476 ULONG src_addr[4], dest_addr[4];
3477
3478 packet_ptr -> nx_packet_ip_header = packet_ptr -> nx_packet_prepend_ptr;
3479
3480 packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr = &nx_bsd_default_ip -> nx_ipv6_address[src_interface];
3481
3482 ipv6_header = (NX_IPV6_HEADER*)packet_ptr -> nx_packet_ip_header;
3483
3484 /* Set up source / Destination IP */
3485 COPY_IPV6_ADDRESS(ipv6_header -> nx_ip_header_destination_ip, dest_addr);
3486 COPY_IPV6_ADDRESS(ipv6_header -> nx_ip_header_source_ip, src_addr);
3487 NX_IPV6_ADDRESS_CHANGE_ENDIAN(dest_addr);
3488 NX_IPV6_ADDRESS_CHANGE_ENDIAN(src_addr);
3489
3490
3491 _nxd_bsd_ipv6_packet_send(packet_ptr, src_addr, dest_addr);
3492
3493 status = NX_SUCCESS;
3494 }
3495 }
3496 #endif
3497 }
3498 else
3499 {
3500
3501 /* Raw socket without any IP header appended yet. We can send this directly to the NetX Duo IP packet handler. */
3502 if(local_interface_index == NX_BSD_LOCAL_IF_INADDR_ANY)
3503 local_interface_index = 0;
3504
3505 status = nxd_ip_raw_packet_interface_send(nx_bsd_default_ip, packet_ptr, dst_address,
3506 local_interface_index, bsd_socket_ptr -> nx_bsd_socket_protocol,
3507 NX_IP_TIME_TO_LIVE, NX_IP_NORMAL);
3508 }
3509 }
3510
3511 /* Was the packet send successful? */
3512 if (status != NX_SUCCESS)
3513 {
3514
3515 /* No, release the packet. */
3516 nx_packet_release(packet_ptr);
3517
3518 /* Set the socket error. */
3519
3520 /* Set the socket error according to the NetX error status returned. */
3521 switch (status)
3522 {
3523
3524 case NX_IP_ADDRESS_ERROR:
3525 nx_bsd_set_errno(EDESTADDRREQ);
3526 break;
3527
3528 case NX_NOT_ENABLED:
3529 nx_bsd_set_errno(EPROTONOSUPPORT);
3530 break;
3531
3532 case NX_NOT_CONNECTED:
3533 nx_bsd_set_errno(ENOTCONN);
3534 break;
3535
3536 case NX_NO_PACKET:
3537 case NX_UNDERFLOW:
3538 nx_bsd_set_errno(ENOBUFS);
3539 break;
3540
3541 case NX_WINDOW_OVERFLOW:
3542 case NX_WAIT_ABORTED:
3543 case NX_TX_QUEUE_DEPTH:
3544 if ((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING) ||
3545 (flags & MSG_DONTWAIT))
3546 nx_bsd_set_errno( EWOULDBLOCK);
3547 else
3548 nx_bsd_set_errno(ETIMEDOUT);
3549 break;
3550
3551 default:
3552 /* NX_NOT_BOUND */
3553 /* NX_PTR_ERROR */
3554 /* NX_INVALID_PACKET */
3555 nx_bsd_set_errno(EINVAL);
3556 break;
3557 }
3558
3559 /* Return an error status. */
3560 NX_BSD_ERROR(status, __LINE__);
3561
3562 /* Release the protection mutex. */
3563 tx_mutex_put(nx_bsd_protection_ptr);
3564
3565 return(NX_SOC_ERROR);
3566 }
3567
3568 /* Release the protection mutex. */
3569 tx_mutex_put(nx_bsd_protection_ptr);
3570
3571 return((INT)data_sent);
3572 }
3573
3574 /**************************************************************************/
3575 /* */
3576 /* FUNCTION RELEASE */
3577 /* */
3578 /* send PORTABLE C */
3579 /* 6.3.0 */
3580 /* AUTHOR */
3581 /* */
3582 /* Yuxin Zhou, Microsoft Corporation */
3583 /* */
3584 /* DESCRIPTION */
3585 /* */
3586 /* This function sends a packet out the given socket. */
3587 /* When the call returns, the data has been queued for transmission */
3588 /* over the connection. The return value indicates the number of byes */
3589 /* actually transmitted. */
3590 /* */
3591 /* The flags argument is provided for consistency with the BSD send */
3592 /* service. It allows various protocol features, such as out-of-bound */
3593 /* out-of-bound data, to be accessed. However, none of these features */
3594 /* are implemented. */
3595 /* */
3596 /* If packets are being sent out a UDP socket which is not bound to a */
3597 /* local port, this function find an available free port to bind to the*/
3598 /* socket. For TCP sockets, the socket must already by connected (so */
3599 /* also bound to port) */
3600 /* */
3601 /* Note: send() does not support raw sockets. Use the sendto() service */
3602 /* to transmit raw packets. */
3603 /* */
3604 /* INPUT */
3605 /* */
3606 /* sockID Socket */
3607 /* msg Data to be transmitted */
3608 /* msgLength Number of bytes to be sent */
3609 /* flags Control flags, support */
3610 /* MSG_DONTWAIT */
3611 /* */
3612 /* OUTPUT */
3613 /* */
3614 /* number of bytes sent If successful */
3615 /* NX_SOC_ERROR (-1) If failure */
3616 /* */
3617 /* CALLS */
3618 /* */
3619 /* nx_tcp_socket_send Send a packet */
3620 /* nx_packet_allocate Get a free packet */
3621 /* nx_packet_data_append Copy data into packet */
3622 /* nx_packet_release Free a packet used to send */
3623 /* tx_mutex_get Get protection */
3624 /* tx_mutex_put Release protection */
3625 /* */
3626 /* CALLED BY */
3627 /* */
3628 /* Application Code */
3629 /* */
3630 /* RELEASE HISTORY */
3631 /* */
3632 /* DATE NAME DESCRIPTION */
3633 /* */
3634 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3635 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3636 /* resulting in version 6.1 */
3637 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
3638 /* used new API/structs naming,*/
3639 /* resulting in version 6.3.0 */
3640 /* */
3641 /**************************************************************************/
nx_bsd_send(INT sockID,const CHAR * msg,INT msgLength,INT flags)3642 INT nx_bsd_send(INT sockID, const CHAR *msg, INT msgLength, INT flags)
3643 {
3644
3645 NX_BSD_SOCKET *bsd_socket_ptr;
3646
3647
3648 /* Check for invalid socket IDd. */
3649 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
3650 {
3651
3652 /* Set the socket error if extended options enabled. */
3653 nx_bsd_set_errno(EBADF);
3654
3655 /* Return an error status.*/
3656 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3657 return(NX_SOC_ERROR);
3658 }
3659
3660 /* Normalize the socket ID. */
3661 sockID = sockID - NX_BSD_SOCKFD_START;
3662
3663 /* Set up a pointer to the BSD socket. */
3664 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
3665
3666 /* If the socket has an error */
3667 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
3668 {
3669 INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
3670
3671 /* Now clear the error code. */
3672 bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
3673
3674 /* Clear the error flag. The application is expected to close the socket at this point.*/
3675 bsd_socket_ptr -> nx_bsd_socket_status_flags =
3676 bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
3677
3678 nx_bsd_set_errno(errcode);
3679
3680 /* Return an error. */
3681 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3682
3683 /* At this point the error flag is cleared. Application should
3684 detect and handle the error codition. This socket is still bound
3685 to the port (either the application called bind(), or a bind
3686 operation was executed as part of the connect call) is able to
3687 handle another "connect" call, or be closed. */
3688 return(NX_SOC_ERROR);
3689 }
3690
3691 /* Send() requires the socket be connected. A connected socket implies the socket is bound.*/
3692 if((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED) == 0)
3693 {
3694
3695 /* For AF_PACKET family, the socket should be bound. */
3696 #if defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)
3697 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
3698 {
3699 struct nx_bsd_sockaddr_ll sockaddr_dest;
3700
3701 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND))
3702 {
3703
3704 /* Set the socket error code. */
3705 nx_bsd_set_errno(EDESTADDRREQ);
3706
3707 /* Return error code. */
3708 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3709 return(NX_SOC_ERROR);
3710 }
3711
3712 sockaddr_dest.sll_family = AF_PACKET;
3713 sockaddr_dest.sll_ifindex = (INT)bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index;
3714 return(_nx_bsd_hardware_internal_sendto(bsd_socket_ptr, (CHAR *)msg, msgLength, flags, (struct nx_bsd_sockaddr*)&sockaddr_dest, sizeof(struct nx_bsd_sockaddr_ll)));
3715 }
3716
3717 #endif /* defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT) */
3718
3719 /* However if the socket is raw socket and HDR_INCLUDE is set, it is OK. */
3720 if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE))
3721 {
3722 /* Set the socket error */
3723 nx_bsd_set_errno(ENOTCONN);
3724
3725 /* Return an error status.*/
3726 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3727 return(NX_SOC_ERROR);
3728 }
3729 }
3730
3731 return nx_bsd_send_internal(sockID, msg, msgLength, flags,
3732 &bsd_socket_ptr -> nx_bsd_socket_peer_ip,
3733 bsd_socket_ptr -> nx_bsd_socket_peer_port,
3734 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index);
3735
3736 }
3737
3738
3739 /**************************************************************************/
3740 /* */
3741 /* FUNCTION RELEASE */
3742 /* */
3743 /* sendto PORTABLE C */
3744 /* 6.3.0 */
3745 /* AUTHOR */
3746 /* */
3747 /* Yuxin Zhou, Microsoft Corporation */
3748 /* */
3749 /* DESCRIPTION */
3750 /* */
3751 /* This function sends a packet out the given socket. */
3752 /* When the call returns, the data has been queued for transmission */
3753 /* over the connection. To use sendto on a TCP BSD socket, the */
3754 /* socket must already be in connected state. */
3755 /* */
3756 /* The flags argument is provided for consistency with the BSD send */
3757 /* service. It allows various protocol features, such as out-of-bound */
3758 /* out-of-bound data, to be accessed. However, none of these features */
3759 /* are implemented. */
3760 /* */
3761 /* INPUT */
3762 /* */
3763 /* sockID Socket (must be connected). */
3764 /* msg Data to transmit. */
3765 /* msgLength Number of bytes to send */
3766 /* flags Control flags, support */
3767 /* MSG_DONTWAIT */
3768 /* sockaddr Destination address */
3769 /* destAddrLen Length of destination address */
3770 /* */
3771 /* OUTPUT */
3772 /* */
3773 /* Number of bytes sent If no error occurs */
3774 /* NX_SOC_ERROR (-1) In case of socket error */
3775 /* */
3776 /* CALLS */
3777 /* */
3778 /* bind Bind NetX UDP sockets */
3779 /* nx_packet_allocate Get a free packet */
3780 /* nx_packet_data_append Copy data into packet */
3781 /* nx_packet_release Free the nx_packet used */
3782 /* nx_tcp_socket_send Send packet over a TCP Socket */
3783 /* nx_udp_socket_send Send packet over a UDP Socket */
3784 /* tx_mutex_get Get protection */
3785 /* tx_mutex_put Release protection */
3786 /* */
3787 /* CALLED BY */
3788 /* */
3789 /* Application Code */
3790 /* */
3791 /* RELEASE HISTORY */
3792 /* */
3793 /* DATE NAME DESCRIPTION */
3794 /* */
3795 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
3796 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
3797 /* resulting in version 6.1 */
3798 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
3799 /* used new API/structs naming,*/
3800 /* resulting in version 6.3.0 */
3801 /* */
3802 /**************************************************************************/
nx_bsd_sendto(INT sockID,CHAR * msg,INT msgLength,INT flags,struct nx_bsd_sockaddr * destAddr,INT destAddrLen)3803 INT nx_bsd_sendto(INT sockID, CHAR *msg, INT msgLength, INT flags, struct nx_bsd_sockaddr *destAddr, INT destAddrLen)
3804 {
3805 UINT status;
3806 NX_BSD_SOCKET *bsd_socket_ptr;
3807 NXD_ADDRESS peer_ip_address;
3808 USHORT peer_port = 0;
3809
3810 /* Check for a valid socket ID. */
3811 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
3812 {
3813
3814 /* Set the socket error if extended options enabled. */
3815 nx_bsd_set_errno(EBADF);
3816
3817 /* Return an error status. */
3818 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3819 return(NX_SOC_ERROR);
3820 }
3821
3822 /* Set up a socket pointer to the BSD socket. */
3823 bsd_socket_ptr = &nx_bsd_socket_array[sockID - NX_BSD_SOCKFD_START];
3824
3825 /* If the socket has an error */
3826 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
3827 {
3828 INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
3829
3830 /* Now clear the error code. */
3831 bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
3832
3833 /* Clear the error flag. The application is expected to close the socket at this point.*/
3834 bsd_socket_ptr -> nx_bsd_socket_status_flags =
3835 bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
3836
3837 nx_bsd_set_errno(errcode);
3838
3839 /* Return an error. */
3840 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3841
3842 /* At this point the error flag is cleared. Application should
3843 detect and handle the error codition. This socket is still bound
3844 to the port (either the application called bind(), or a bind
3845 operation was executed as part of the connect call) is able to
3846 handle another "connect" call, or be closed. */
3847 return(NX_SOC_ERROR);
3848 }
3849 /* For TCP, make sure the socket is already connected. */
3850 if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP)
3851 {
3852 if((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED) == 0)
3853 {
3854 nx_bsd_set_errno(ENOTCONN);
3855
3856 /* Return an error. */
3857 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3858
3859 return(NX_SOC_ERROR);
3860 }
3861 return nx_bsd_send_internal((sockID - NX_BSD_SOCKFD_START), msg, msgLength, flags, NX_NULL, 0,
3862 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index);
3863 }
3864 else
3865 {
3866
3867 /* This is a UDP or raw socket. */
3868
3869 /* Check whther or not the socket is AF_PACKET family. */
3870 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
3871 {
3872
3873 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
3874 /* nx_bsd_pppoe_internal_sendto shall returns */
3875 status = (UINT)nx_bsd_pppoe_internal_sendto(bsd_socket_ptr, msg, msgLength, flags, destAddr, destAddrLen);
3876 #elif defined(NX_BSD_RAW_SUPPORT)
3877 /* _nx_bsd_hardware_internal_sendto shall returns */
3878 status = (UINT)_nx_bsd_hardware_internal_sendto(bsd_socket_ptr, msg, msgLength, flags, destAddr, destAddrLen);
3879 #else
3880 NX_PARAMETER_NOT_USED(destAddrLen);
3881 status = (UINT)NX_SOC_ERROR;
3882 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
3883 return((INT)status);
3884
3885 }
3886
3887 /* Perform error checkings on the remote address if the socket is
3888 not raw socket, or HDRINCL is not set for the raw socket. */
3889 if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_TX_HDR_INCLUDE))
3890 {
3891
3892 /* Check for an invalid destination. */
3893 if (destAddr == NX_NULL)
3894 {
3895
3896 /* Set the socket error if extended socket options enabled. */
3897 nx_bsd_set_errno(EINVAL);
3898
3899 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3900 return(NX_SOC_ERROR);
3901 }
3902
3903 /* Validate the destination address. */
3904 if(bsd_socket_ptr -> nx_bsd_socket_family != destAddr -> sa_family)
3905 {
3906 nx_bsd_set_errno(EAFNOSUPPORT);
3907
3908 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3909
3910 return(NX_SOC_ERROR);
3911 }
3912 }
3913
3914 /* For UDP socket, make sure the socket is bound. */
3915 if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
3916 {
3917 if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND))
3918 {
3919 status = nx_udp_socket_bind(bsd_socket_ptr -> nx_bsd_socket_udp_socket, NX_ANY_PORT, NX_NO_WAIT);
3920 if((status != NX_SUCCESS) && (status != NX_ALREADY_BOUND))
3921 {
3922 nx_bsd_set_errno(EINVAL);
3923
3924 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
3925
3926 return(NX_SOC_ERROR);
3927 }
3928
3929 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface = NX_BSD_LOCAL_IF_INADDR_ANY;
3930 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index = NX_BSD_LOCAL_IF_INADDR_ANY;
3931 bsd_socket_ptr -> nx_bsd_socket_local_port = (USHORT)(bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_port);
3932 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
3933 }
3934
3935 }
3936
3937
3938
3939 if(destAddr)
3940 {
3941 /* Get the destination IP and port for this UDP socket. */
3942 #ifndef NX_DISABLE_IPV4
3943 if (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
3944 {
3945
3946 /* This is for an IPv4 packet. */
3947 peer_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
3948 peer_ip_address.nxd_ip_address.v4 = htonl(((struct nx_bsd_sockaddr_in *) destAddr) -> sin_addr.s_addr);
3949 peer_port = htons(((struct nx_bsd_sockaddr_in *) destAddr) -> sin_port);
3950
3951 /* Local interface ID is set to invalid value, so the send routine needs to
3952 find the best interface to send the packet based on destination IP address. */
3953
3954 }
3955 #endif /* NX_DISABLE_IPV4 */
3956 #ifdef FEATURE_NX_IPV6
3957 if (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
3958 {
3959
3960 /* This is for an IPv6 packet. Set the NetX Duo IP address version. */
3961 peer_ip_address.nxd_ip_version = NX_IP_VERSION_V6;
3962
3963 peer_ip_address.nxd_ip_address.v6[0] = ntohl(((struct nx_bsd_sockaddr_in6*)destAddr) -> sin6_addr._S6_un._S6_u32[0]);
3964 peer_ip_address.nxd_ip_address.v6[1] = ntohl(((struct nx_bsd_sockaddr_in6*)destAddr) -> sin6_addr._S6_un._S6_u32[1]);
3965 peer_ip_address.nxd_ip_address.v6[2] = ntohl(((struct nx_bsd_sockaddr_in6*)destAddr) -> sin6_addr._S6_un._S6_u32[2]);
3966 peer_ip_address.nxd_ip_address.v6[3] = ntohl(((struct nx_bsd_sockaddr_in6*)destAddr) -> sin6_addr._S6_un._S6_u32[3]);
3967
3968 peer_port = htons(((struct nx_bsd_sockaddr_in6 *) destAddr) -> sin6_port);
3969
3970 }
3971 #endif
3972 }
3973
3974 /* Call the internal send routine to finish the send process. */
3975 /* Local interface ID is set to a special marker, so the send routine needs to
3976 find the best interface to send the packet based on destination IP address. */
3977 return nx_bsd_send_internal((sockID - NX_BSD_SOCKFD_START), msg, msgLength, flags,
3978 &peer_ip_address, peer_port,
3979 bsd_socket_ptr -> nx_bsd_socket_local_bind_interface_index);
3980
3981 }
3982 }
3983
3984
3985 /**************************************************************************/
3986 /* */
3987 /* FUNCTION RELEASE */
3988 /* */
3989 /* recv PORTABLE C */
3990 /* 6.3.0 */
3991 /* AUTHOR */
3992 /* */
3993 /* Yuxin Zhou, Microsoft Corporation */
3994 /* */
3995 /* DESCRIPTION */
3996 /* */
3997 /* This function copies up to a specified number of bytes received on */
3998 /* the socket into specified location. The given socket must be in the */
3999 /* connected state. Normally, the call blocks until either at least one*/
4000 /* byte is returned or the connection closes.The return value indicates*/
4001 /* the number of bytes actually copied into the buffer starting at the */
4002 /* specified location. */
4003 /* */
4004 /* For a stream socket, the bytes are delivered in the same order as */
4005 /* they were transmitted, without omissions. For a datagram socket, */
4006 /* each recv() returns the data from at most one send(), and order is */
4007 /* not necessarily preserved. */
4008 /* */
4009 /* For non blocking sockets, a receive status of NX_NO_PACKET from NetX*/
4010 /* results in an error status returned from BSD, and the socket error */
4011 /* set to EWOULDBLOCK (if BSD extended socket features are enabled. */
4012 /* */
4013 /* Likewise, an event flag status of TX_NO_EVENTS returned from ThreadX*/
4014 /* on a non blocking socket sets the socket error to EWOULDBLOCK. */
4015 /* */
4016 /* INPUT */
4017 /* */
4018 /* sockID Socket (must be connected). */
4019 /* rcvBuffer Pointer to put data received. */
4020 /* bufferLength Maximum bytes in buffer */
4021 /* flags Control flags, support */
4022 /* MSG_PEEK and MSG_DONTWAIT */
4023 /* */
4024 /* OUTPUT */
4025 /* */
4026 /* Number of bytes received If success */
4027 /* NX_SOC_ERROR (-1) If failure */
4028 /* 0 socket disconnected */
4029 /* */
4030 /* CALLS */
4031 /* */
4032 /* nx_bsd_recv_internal Actual receive function */
4033 /* */
4034 /* CALLED BY */
4035 /* */
4036 /* Application Code */
4037 /* */
4038 /* RELEASE HISTORY */
4039 /* */
4040 /* DATE NAME DESCRIPTION */
4041 /* */
4042 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4043 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
4044 /* verified memcpy use cases, */
4045 /* resulting in version 6.1 */
4046 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
4047 /* used new API/structs naming,*/
4048 /* resulting in version 6.3.0 */
4049 /* */
4050 /**************************************************************************/
nx_bsd_recv(INT sockID,VOID * rcvBuffer,INT bufferLength,INT flags)4051 INT nx_bsd_recv(INT sockID, VOID *rcvBuffer, INT bufferLength, INT flags)
4052 {
4053
4054 struct nx_bsd_iovec iov;
4055
4056 iov.iov_base = rcvBuffer;
4057 iov.iov_len = (size_t)bufferLength;
4058
4059 /* Call the recv_internal() function. */
4060 return nx_bsd_recv_internal(sockID, &iov, 1, flags, NX_NULL, NX_NULL);
4061 }
4062
4063
4064 /**************************************************************************/
4065 /* */
4066 /* FUNCTION RELEASE */
4067 /* */
4068 /* recvfrom PORTABLE C */
4069 /* 6.4.0 */
4070 /* AUTHOR */
4071 /* */
4072 /* Yuxin Zhou, Microsoft Corporation */
4073 /* */
4074 /* DESCRIPTION */
4075 /* */
4076 /* This function copies up to a specified number of bytes, received on */
4077 /* the socket into a specified location. To use recvfrom() on a TCP */
4078 /* socket requires the socket to be in the connected state. */
4079 /* */
4080 /* This function is identical to recv() except for returning the sender*/
4081 /* address and length if non null arguments are supplied. */
4082 /* */
4083 /* INPUT */
4084 /* */
4085 /* sockID Socket(must be connected) */
4086 /* buffer Pointer to hold data received */
4087 /* bufferSize Maximum number of bytes */
4088 /* flags Control flags, support */
4089 /* MSG_PEEK and MSG_DONTWAIT */
4090 /* fromAddr Address data of sender */
4091 /* fromAddrLen Length of address structure */
4092 /* */
4093 /* OUTPUT */
4094 /* */
4095 /* number of bytes received If no error occurs */
4096 /* NX_SOC_ERROR (-1) In case of any error */
4097 /* */
4098 /* CALLS */
4099 /* */
4100 /* nx_bsd_recv_internal Actual receive function */
4101 /* */
4102 /* CALLED BY */
4103 /* */
4104 /* Application Code */
4105 /* */
4106 /* RELEASE HISTORY */
4107 /* */
4108 /* DATE NAME DESCRIPTION */
4109 /* */
4110 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4111 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
4112 /* verified memcpy use cases, */
4113 /* resulting in version 6.1 */
4114 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
4115 /* used new API/structs naming,*/
4116 /* resulting in version 6.3.0 */
4117 /* 12-31-2023 Yanwu Cai Modified comment(s), and */
4118 /* added nx_bsd_recv_internal, */
4119 /* resulting in version 6.4.0 */
4120 /* */
4121 /**************************************************************************/
nx_bsd_recvfrom(INT sockID,CHAR * rcvBuffer,INT bufferLength,INT flags,struct nx_bsd_sockaddr * fromAddr,INT * fromAddrLen)4122 INT nx_bsd_recvfrom(INT sockID, CHAR *rcvBuffer, INT bufferLength, INT flags, struct nx_bsd_sockaddr *fromAddr, INT *fromAddrLen)
4123 {
4124 struct nx_bsd_iovec iov;
4125
4126 iov.iov_base = rcvBuffer;
4127 iov.iov_len = (size_t)bufferLength;
4128
4129 /* Call the recv_internal() function. */
4130 return nx_bsd_recv_internal(sockID, &iov, 1, flags, fromAddr, fromAddrLen);
4131 }
4132
4133 /**************************************************************************/
4134 /* */
4135 /* FUNCTION RELEASE */
4136 /* */
4137 /* recvmsg PORTABLE C */
4138 /* 6.4.0 */
4139 /* AUTHOR */
4140 /* */
4141 /* Yanwu Cai, Microsoft Corporation */
4142 /* */
4143 /* DESCRIPTION */
4144 /* */
4145 /* This function copies up to a specified number of bytes, received on */
4146 /* the socket into a specified location. To use recvmsg() on a TCP */
4147 /* socket requires the socket to be in the connected state. */
4148 /* */
4149 /* INPUT */
4150 /* */
4151 /* sockID Socket(must be connected) */
4152 /* msg Pointer to hold msghdr struct */
4153 /* flags Control flags, support */
4154 /* MSG_PEEK and MSG_DONTWAIT */
4155 /* */
4156 /* OUTPUT */
4157 /* */
4158 /* number of bytes received If no error occurs */
4159 /* NX_SOC_ERROR (-1) In case of any error */
4160 /* */
4161 /* CALLS */
4162 /* */
4163 /* nx_bsd_recv_internal Actual receive function */
4164 /* */
4165 /* CALLED BY */
4166 /* */
4167 /* Application Code */
4168 /* */
4169 /* RELEASE HISTORY */
4170 /* */
4171 /* DATE NAME DESCRIPTION */
4172 /* */
4173 /* 12-31-2023 Yanwu Cai Initial Version 6.4.0 */
4174 /* */
4175 /**************************************************************************/
nx_bsd_recvmsg(INT sockID,struct nx_bsd_msghdr * msg,INT flags)4176 INT nx_bsd_recvmsg(INT sockID, struct nx_bsd_msghdr *msg, INT flags)
4177 {
4178 INT fromAddrLen = 0;
4179
4180 if (msg -> msg_name != NX_NULL)
4181 {
4182 fromAddrLen = (INT)(msg -> msg_namelen);
4183 }
4184
4185 return(nx_bsd_recv_internal(sockID, msg -> msg_iov, msg -> msg_iovlen, flags, (struct nx_bsd_sockaddr *)(msg -> msg_name), &fromAddrLen));
4186 }
4187
4188 /**************************************************************************/
4189 /* */
4190 /* FUNCTION RELEASE */
4191 /* */
4192 /* recv_internal PORTABLE C */
4193 /* 6.4.0 */
4194 /* AUTHOR */
4195 /* */
4196 /* Yanwu Cai, Microsoft Corporation */
4197 /* */
4198 /* DESCRIPTION */
4199 /* */
4200 /* This function copies up to a specified number of bytes received on */
4201 /* the socket into specified location. The given socket must be in the */
4202 /* connected state. Normally, the call blocks until either at least one*/
4203 /* byte is returned or the connection closes.The return value indicates*/
4204 /* the number of bytes actually copied into the buffer starting at the */
4205 /* specified location. */
4206 /* */
4207 /* For a stream socket, the bytes are delivered in the same order as */
4208 /* they were transmitted, without omissions. For a datagram socket, */
4209 /* each recv() returns the data from at most one send(), and order is */
4210 /* not necessarily preserved. */
4211 /* */
4212 /* For non blocking sockets, a receive status of NX_NO_PACKET from NetX*/
4213 /* results in an error status returned from BSD, and the socket error */
4214 /* set to EWOULDBLOCK (if BSD extended socket features are enabled. */
4215 /* */
4216 /* Likewise, an event flag status of TX_NO_EVENTS returned from ThreadX*/
4217 /* on a non blocking socket sets the socket error to EWOULDBLOCK. */
4218 /* */
4219 /* INPUT */
4220 /* */
4221 /* sockID Socket (must be connected). */
4222 /* iov Pointer to iovec struct. */
4223 /* iovlen Number of iov elements */
4224 /* flags Control flags, support */
4225 /* MSG_PEEK and MSG_DONTWAIT */
4226 /* fromAddr Address data of sender */
4227 /* fromAddrLen Length of address structure */
4228 /* */
4229 /* OUTPUT */
4230 /* */
4231 /* Number of bytes received If success */
4232 /* NX_SOC_ERROR (-1) If failure */
4233 /* 0 socket disconnected */
4234 /* */
4235 /* CALLS */
4236 /* */
4237 /* nx_tcp_socket_receive Receive a Packet */
4238 /* nx_packet_allocate Allocate packet for receive */
4239 /* nx_packet_release Free the nx_packet after use */
4240 /* nx_packet_data_extract_offset Retrieve packet data */
4241 /* tx_event_flags_get Wait for data to arrive */
4242 /* tx_mutex_get Get protection */
4243 /* tx_mutex_put Release protection */
4244 /* */
4245 /* CALLED BY */
4246 /* */
4247 /* recv */
4248 /* recvmsg */
4249 /* recvfrom */
4250 /* */
4251 /* RELEASE HISTORY */
4252 /* */
4253 /* DATE NAME DESCRIPTION */
4254 /* */
4255 /* 12-31-2023 Yanwu Cai Initial Version 6.4.0 */
4256 /* */
4257 /**************************************************************************/
nx_bsd_recv_internal(INT sockID,struct nx_bsd_iovec * iov,size_t iovlen,INT flags,struct nx_bsd_sockaddr * fromAddr,INT * fromAddrLen)4258 static INT nx_bsd_recv_internal(INT sockID, struct nx_bsd_iovec *iov, size_t iovlen, INT flags, struct nx_bsd_sockaddr *fromAddr, INT *fromAddrLen)
4259 {
4260 UINT status;
4261 NX_PACKET *packet_ptr;
4262 NX_BSD_SOCKET *bsd_socket_ptr;
4263 NX_TCP_SOCKET *tcp_socket_ptr;
4264 ULONG requested_events;
4265 ULONG bytes_received;
4266 ULONG bytes_copied;
4267 ULONG buffer_used = 0;
4268 UINT wait_option;
4269 UINT remaining_wait_option;
4270 ULONG offset;
4271 UINT header_size = 0;
4272 ULONG start_time = nx_bsd_system_clock;
4273 #ifndef NX_DISABLE_IPV4
4274 struct nx_bsd_sockaddr_in
4275 peer4_address;
4276 #endif /* NX_DISABLE_IPV4 */
4277 #ifdef FEATURE_NX_IPV6
4278 struct nx_bsd_sockaddr_in6
4279 peer6_address;
4280 #endif
4281
4282
4283 /* Check for a valid socket ID. */
4284 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
4285 {
4286
4287 /* Set the socket error if extended options enabled. */
4288 nx_bsd_set_errno(EBADF);
4289
4290 /* Return an error. */
4291 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4292
4293 return(NX_SOC_ERROR);
4294 }
4295
4296 /* Normalize the socket ID. */
4297 sockID = sockID - NX_BSD_SOCKFD_START;
4298
4299 /* Set up a pointer to the socket. */
4300 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
4301
4302 /* Set the receive wait time to FOREVER for blocking sockets. */
4303 wait_option = NX_WAIT_FOREVER;
4304
4305 /* Is this a nonblocking socket?: */
4306 if ((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING) ||
4307 (flags & MSG_DONTWAIT))
4308 {
4309
4310 /* Yes, set to receive wait option to no wait (zero). */
4311 wait_option = 0;
4312 }
4313 /* Does this socket have a receive timeout option set? */
4314 else if (bsd_socket_ptr -> nx_bsd_option_receive_timeout)
4315 {
4316
4317 /* Yes, this is our wait option. */
4318 wait_option = bsd_socket_ptr -> nx_bsd_option_receive_timeout;
4319 }
4320
4321 /* Get the protection mutex. */
4322 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
4323
4324 /* Check the status. */
4325 if (status)
4326 {
4327
4328 /* Set the socket error if extended socket options enabled. */
4329 nx_bsd_set_errno(EACCES);
4330
4331 /* Return an error. */
4332 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
4333 return(NX_SOC_ERROR);
4334 }
4335
4336 /* If the socket has an error */
4337 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
4338 {
4339
4340 INT errcode = bsd_socket_ptr -> nx_bsd_socket_error_code;
4341
4342 /* Now clear the error code. */
4343 bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
4344
4345 /* Clear the error flag. The application is expected to close the socket at this point.*/
4346 bsd_socket_ptr -> nx_bsd_socket_status_flags =
4347 bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
4348
4349 nx_bsd_set_errno(errcode);
4350
4351 /* Release the protection mutex. */
4352 tx_mutex_put(nx_bsd_protection_ptr);
4353
4354 /* Return an error. */
4355 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4356
4357 /* At this point the error flag is cleared. The application should
4358 detect and handle the error codition. This socket is still bound
4359 to the port (either the application called bind(), or a bind
4360 operation was executed as part of the connect call) and is able to
4361 handle another "connect" call, or be closed. */
4362 return(NX_SOC_ERROR);
4363 }
4364
4365 /* Set pointers to the BSD NetX Duo sockets. */
4366 tcp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
4367
4368 /* Loop to check for a received packet. */
4369 do
4370 {
4371
4372 /* Is the socket still in use? */
4373 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
4374 {
4375
4376 /* Set the socket error if extended options enabled. */
4377 nx_bsd_set_errno(EBADF);
4378
4379 /* Release the protection mutex. */
4380 tx_mutex_put(nx_bsd_protection_ptr);
4381
4382 /* Return an error. */
4383 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4384 return(NX_SOC_ERROR);
4385 }
4386
4387 /* Check if the BSD socket already has received a packet. */
4388 packet_ptr = bsd_socket_ptr -> nx_bsd_socket_received_packet;
4389
4390 if (packet_ptr)
4391 {
4392
4393 /* Got one. Break out of the loop. */
4394 break;
4395 }
4396
4397 /* Check if there is an incoming packet on this socket. */
4398 else
4399 {
4400
4401 /* Determine if this is a TCP BSD socket. */
4402 if (tcp_socket_ptr)
4403 {
4404
4405 /* It is, check the socket TCP receive queue with a zero wait option (no suspension). */
4406 status = nx_tcp_socket_receive(tcp_socket_ptr, &packet_ptr, TX_NO_WAIT);
4407
4408 /* Check for no packet on the queue. */
4409 if (status == NX_NOT_CONNECTED)
4410 {
4411
4412 /* Release the protection mutex. */
4413 tx_mutex_put(nx_bsd_protection_ptr);
4414
4415 /* Is peer shutdown orderly? */
4416 if ((tcp_socket_ptr -> nx_tcp_socket_state == NX_TCP_CLOSE_WAIT) ||
4417 (tcp_socket_ptr -> nx_tcp_socket_state >= NX_TCP_CLOSING))
4418 {
4419
4420 /* Yes. Return 0. */
4421 return(NX_SUCCESS);
4422 }
4423
4424 /* Set the socket status (not really an error). */
4425 nx_bsd_set_errno(ENOTCONN);
4426
4427 /* Return an error. */
4428 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4429 return(NX_SOC_ERROR);
4430 }
4431
4432 if (status == NX_SUCCESS)
4433 {
4434
4435 /* Increase the received count. */
4436 bsd_socket_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
4437 bsd_socket_ptr -> nx_bsd_socket_received_packet_count++;
4438 }
4439 }
4440
4441 /* Have we found a new packet? */
4442 if ((status == NX_SUCCESS) && (packet_ptr))
4443 {
4444
4445 /* Setup the bsd socket with the packet information. */
4446 bsd_socket_ptr -> nx_bsd_socket_received_packet = packet_ptr;
4447 bsd_socket_ptr -> nx_bsd_socket_received_packet_offset = 0;
4448
4449 /* Get out of the loop. */
4450 break;
4451 }
4452 }
4453
4454 /* No packet is available. */
4455
4456 /* Release the protection mutex. */
4457 tx_mutex_put(nx_bsd_protection_ptr);
4458
4459 /* Calculate remaining wait option. */
4460 remaining_wait_option = (UINT)(wait_option - (nx_bsd_system_clock - start_time));
4461 if (remaining_wait_option > wait_option)
4462 {
4463
4464 /* Wait option expired. */
4465 status = TX_NO_EVENTS;
4466 }
4467 else
4468 {
4469
4470 /* Suspend this socket on a RECEIVE event (incoming packet) for the specified wait time. */
4471 status = tx_event_flags_get(&nx_bsd_events, NX_BSD_RECEIVE_EVENT, TX_OR_CLEAR, &requested_events, remaining_wait_option);
4472 }
4473
4474 /* Check for any events. */
4475 if (status == TX_NO_EVENTS)
4476 {
4477
4478 /* No packets received. */
4479
4480 /* Set the socket error depending if this is a non blocking socket. */
4481 if ((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING) ||
4482 (wait_option == NX_WAIT_FOREVER) ||
4483 (flags & MSG_DONTWAIT))
4484 nx_bsd_set_errno(EWOULDBLOCK);
4485 else
4486 nx_bsd_set_errno(EAGAIN);
4487
4488 /* Return an error. */
4489 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4490 return(NX_SOC_ERROR);
4491 }
4492 else if (status != TX_SUCCESS)
4493 {
4494
4495 /* Set the socket error if extended socket options enabled. */
4496 nx_bsd_set_errno(EINVAL);
4497
4498 /* Return an error. */
4499 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4500 return(NX_SOC_ERROR);
4501 }
4502
4503 /* Re-obtain the protection mutex. */
4504 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
4505
4506 /* Check the status. */
4507 if (status)
4508 {
4509
4510 /* Set the socket error if extended socket options enabled. */
4511 nx_bsd_set_errno(EACCES);
4512
4513 /* Return an error. */
4514 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
4515 return(NX_SOC_ERROR);
4516 }
4517
4518 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
4519 {
4520 /* The socket is no longer in use. */
4521
4522 /* Set the socket error code. */
4523 nx_bsd_set_errno(EBADF);
4524
4525 /* Release the protection mutex. */
4526 tx_mutex_put(nx_bsd_protection_ptr);
4527
4528 /* Return error code. */
4529 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4530 return(NX_SOC_ERROR);
4531 }
4532
4533 } while (1);
4534
4535 /* At this point, the socket has received a packet. */
4536
4537
4538 /* Obtain sender information for UDP socket. */
4539 if(bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_UDP)
4540 {
4541
4542 /* Get the sender and port from the UDP packet. */
4543 nxd_udp_source_extract(packet_ptr, &bsd_socket_ptr -> nx_bsd_socket_source_ip_address, (UINT *)&bsd_socket_ptr -> nx_bsd_socket_source_port);
4544 }
4545
4546 #if defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT)
4547 else if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
4548 {
4549
4550 /* Validate the packet length. */
4551 if (packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr < 14)
4552 {
4553
4554 /* Set the socket error if extended socket options enabled. */
4555 nx_bsd_set_errno(EINVAL);
4556
4557 /* Release the protection mutex. */
4558 tx_mutex_put(nx_bsd_protection_ptr);
4559
4560 /* Release the packet. */
4561 nx_packet_release(packet_ptr);
4562
4563 /* Return an error. */
4564 NX_BSD_ERROR(status, __LINE__);
4565 return(NX_SOC_ERROR);
4566 }
4567
4568 /* Pick up the sender's MAC address. */
4569 bsd_socket_ptr -> nx_bsd_socket_sll_addr[0] = packet_ptr -> nx_packet_prepend_ptr[6];
4570 bsd_socket_ptr -> nx_bsd_socket_sll_addr[1] = packet_ptr -> nx_packet_prepend_ptr[7];
4571 bsd_socket_ptr -> nx_bsd_socket_sll_addr[2] = packet_ptr -> nx_packet_prepend_ptr[8];
4572 bsd_socket_ptr -> nx_bsd_socket_sll_addr[3] = packet_ptr -> nx_packet_prepend_ptr[9];
4573 bsd_socket_ptr -> nx_bsd_socket_sll_addr[4] = packet_ptr -> nx_packet_prepend_ptr[10];
4574 bsd_socket_ptr -> nx_bsd_socket_sll_addr[5] = packet_ptr -> nx_packet_prepend_ptr[11];
4575
4576 /* Pick up the sender's protocol */
4577 bsd_socket_ptr -> nx_bsd_socket_sll_protocol = (USHORT)((packet_ptr -> nx_packet_prepend_ptr[12] << 8) |
4578 (packet_ptr -> nx_packet_prepend_ptr[13]));
4579 if (bsd_socket_ptr -> nx_bsd_socket_sll_protocol == 0x8100)
4580 {
4581
4582 /* Skip VLAN tag. */
4583 bsd_socket_ptr -> nx_bsd_socket_sll_protocol = (USHORT)((packet_ptr -> nx_packet_prepend_ptr[16] << 8) |
4584 (packet_ptr -> nx_packet_prepend_ptr[17]));
4585 }
4586
4587 /* Find the IF Index */
4588 bsd_socket_ptr -> nx_bsd_socket_sll_ifindex = packet_ptr -> nx_packet_ip_interface -> nx_interface_index;
4589
4590 }
4591 #endif /* defined(NX_BSD_RAW_SUPPORT) || defined(NX_BSD_RAW_PPPOE_SUPPORT) */
4592
4593
4594 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4595 /* For raw socket, make sure the source address is extracted. */
4596 else if(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET)
4597 {
4598
4599 /* Get the sender IP address from the raw packet. */
4600 status = nx_bsd_raw_packet_info_extract(packet_ptr, &(bsd_socket_ptr -> nx_bsd_socket_source_ip_address), NX_NULL);
4601 }
4602 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
4603
4604 /* Pickup the current offset. */
4605 offset = bsd_socket_ptr -> nx_bsd_socket_received_packet_offset;
4606
4607 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4608 /* Perform extra processing on this packet if it processed as a raw packet. */
4609 if((bsd_socket_ptr -> nx_bsd_socket_family != AF_PACKET) &&
4610 (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET))
4611 {
4612
4613 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & (NX_BSD_SOCKET_RX_NO_HDR))
4614 {
4615 header_size = 0;
4616 }
4617 else
4618 {
4619 #ifndef NX_DISABLE_IPV4
4620 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
4621 {
4622
4623
4624 header_size = (UINT)(packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_ip_header);
4625
4626 /* Byte-Swap the basic IPv4 header. The NetX Duo IP receive process does not
4627 examine the extension header. Therefore it does not perform byte swap
4628 on extension headers. */
4629 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_word_0));
4630 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_word_1));
4631 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_word_2));
4632 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_source_ip));
4633 NX_CHANGE_ULONG_ENDIAN((((NX_IPV4_HEADER*)(packet_ptr -> nx_packet_ip_header)) -> nx_ip_header_destination_ip));
4634
4635 }
4636 #endif /* NX_DISABLE_IPV4 */
4637 #ifdef FEATURE_NX_IPV6
4638 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
4639 {
4640
4641 NX_IPV6_HEADER *ipv6_header_ptr;
4642 UCHAR next_header_type;
4643
4644 header_size = (UINT)(packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_ip_header);
4645
4646 ipv6_header_ptr = (NX_IPV6_HEADER*)packet_ptr -> nx_packet_ip_header;
4647
4648 /* Pick up the next header. */
4649 next_header_type = (ipv6_header_ptr -> nx_ip_header_word_1 >> 8) & 0xFF;
4650
4651 NX_CHANGE_ULONG_ENDIAN(ipv6_header_ptr -> nx_ip_header_word_0);
4652 NX_CHANGE_ULONG_ENDIAN(ipv6_header_ptr -> nx_ip_header_word_1);
4653 NX_IPV6_ADDRESS_CHANGE_ENDIAN(ipv6_header_ptr -> nx_ip_header_destination_ip);
4654 NX_IPV6_ADDRESS_CHANGE_ENDIAN(ipv6_header_ptr -> nx_ip_header_source_ip);
4655
4656 /* Go through the rest of the IPv6 extension headers. */
4657 _nxd_bsd_swap_ipv6_extension_headers(packet_ptr, next_header_type);
4658 }
4659 #endif
4660 bytes_copied = 0;
4661 while(iovlen)
4662 {
4663 if(iov -> iov_len > (header_size - bytes_copied))
4664 {
4665 memcpy(iov -> iov_base, (VOID*)((UINT)(packet_ptr -> nx_packet_ip_header) + bytes_copied), (UINT)(header_size - bytes_copied)); /* Use case of memcpy is verified. */
4666 buffer_used = (header_size - bytes_copied);
4667 bytes_copied += (header_size - bytes_copied);
4668
4669 break;
4670 }
4671 else
4672 {
4673 memcpy(iov -> iov_base, (VOID*)((UINT)(packet_ptr -> nx_packet_ip_header) + bytes_copied), iov -> iov_len); /* Use case of memcpy is verified. */
4674 bytes_copied += iov -> iov_len;
4675 iovlen--;
4676 iov++;
4677 buffer_used = 0;
4678 }
4679 }
4680 header_size = bytes_copied;
4681
4682 }
4683 }
4684 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
4685
4686 bytes_copied = 0;
4687 while(iovlen)
4688 {
4689 /* Copy the packet data into the supplied buffer. */
4690 status = nx_packet_data_extract_offset(packet_ptr, offset + bytes_copied, (VOID*)((UINT)(iov -> iov_base) + buffer_used), (ULONG) (iov -> iov_len - buffer_used), &bytes_received);
4691
4692 /* Check for an error. */
4693 if (status)
4694 {
4695
4696 /* Set the socket error if extended socket options enabled. */
4697 nx_bsd_set_errno(EINVAL);
4698
4699 /* Release the protection mutex. */
4700 tx_mutex_put(nx_bsd_protection_ptr);
4701
4702 /* Release the packet. */
4703 nx_packet_release(packet_ptr);
4704
4705 /* Return an error. */
4706 NX_BSD_ERROR( status, __LINE__);
4707 return(NX_SOC_ERROR);
4708 }
4709
4710 bytes_copied += bytes_received;
4711 if (bytes_received < iov -> iov_len - buffer_used)
4712 {
4713 break;
4714 }
4715
4716 buffer_used = 0;
4717 iovlen--;
4718 iov++;
4719 }
4720
4721 if((flags & MSG_PEEK) == 0)
4722 {
4723
4724 /* Calculate the new offset. */
4725 offset = offset + bytes_copied;
4726
4727 /* Determine if all the packet data was consumed. */
4728 if(packet_ptr -> nx_packet_length <= offset)
4729 {
4730
4731 bsd_socket_ptr -> nx_bsd_socket_received_packet = packet_ptr -> nx_packet_queue_next;
4732
4733 /* Release the packet. */
4734 nx_packet_release(packet_ptr);
4735
4736 /* Clear the offset. */
4737 bsd_socket_ptr -> nx_bsd_socket_received_packet_offset = 0;
4738 }
4739 else if((bsd_socket_ptr -> nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
4740 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
4741 || (bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
4742 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
4743 )
4744 {
4745
4746 /* For UDP or raw socket, We extracted as much as can fit in the caller's buffer.
4747 We will discard the remaining bytes. */
4748 bsd_socket_ptr -> nx_bsd_socket_received_packet = packet_ptr -> nx_packet_queue_next;
4749
4750 bytes_copied = packet_ptr -> nx_packet_length;
4751
4752 /* No need to retain the packet. */
4753 nx_packet_release(packet_ptr);
4754
4755 /* Clear the offset. */
4756 bsd_socket_ptr -> nx_bsd_socket_received_packet_offset = 0;
4757 }
4758 else
4759 {
4760
4761 /* For TCP, the remaining data is saved for the next recv call.
4762 Just update the offset. */
4763 bsd_socket_ptr -> nx_bsd_socket_received_packet_offset = offset;
4764 }
4765 bsd_socket_ptr -> nx_bsd_socket_received_byte_count -= bytes_copied;
4766 bsd_socket_ptr -> nx_bsd_socket_received_packet_count--;
4767 }
4768
4769 /* Release the protection mutex. */
4770 tx_mutex_put(nx_bsd_protection_ptr);
4771
4772 /* At this point we did receive a packet. */
4773 /* Supply the sender address if valid pointer is supplied. */
4774 if(fromAddr && (*fromAddrLen != 0))
4775 {
4776
4777 #ifndef NX_DISABLE_IPV4
4778 /* Handle the IPv4 socket type. */
4779 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
4780 {
4781 /* Update the Client address with socket family, remote host IPv4 address and port. */
4782 peer4_address.sin_family = AF_INET;
4783 if(bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
4784 {
4785 peer4_address.sin_addr.s_addr = htonl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v4);
4786 peer4_address.sin_port = htons(bsd_socket_ptr -> nx_bsd_socket_peer_port);
4787 }
4788 else
4789 {
4790 peer4_address.sin_addr.s_addr = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v4);
4791
4792 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4793 if(!(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET))
4794 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
4795 peer4_address.sin_port = ntohs((USHORT)bsd_socket_ptr -> nx_bsd_socket_source_port);
4796 }
4797 /* Copy the peer address/port info to the ClientAddress. Truncate if
4798 addressLength is smaller than the size of struct sockaddr_in */
4799 if(*fromAddrLen > (INT)sizeof(struct nx_bsd_sockaddr_in))
4800 {
4801 *fromAddrLen = sizeof(struct nx_bsd_sockaddr_in);
4802 }
4803 memcpy(fromAddr, &peer4_address, (UINT)(*fromAddrLen)); /* Use case of memcpy is verified. */
4804 }
4805 else
4806 #endif /* NX_DISABLE_IPV4 */
4807
4808 #ifdef FEATURE_NX_IPV6
4809 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
4810 {
4811 /* Update the Client address with socket family, remote host IPv6 address and port. */
4812 peer6_address.sin6_family = AF_INET6;
4813
4814 if(bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
4815 {
4816 peer6_address.sin6_addr._S6_un._S6_u32[0] = ntohl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[0]);
4817 peer6_address.sin6_addr._S6_un._S6_u32[1] = ntohl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[1]);
4818 peer6_address.sin6_addr._S6_un._S6_u32[2] = ntohl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[2]);
4819 peer6_address.sin6_addr._S6_un._S6_u32[3] = ntohl(bsd_socket_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[3]);
4820 peer6_address.sin6_port = ntohs(bsd_socket_ptr -> nx_bsd_socket_peer_port);
4821 }
4822 else
4823 {
4824 peer6_address.sin6_addr._S6_un._S6_u32[0] = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[0]);
4825 peer6_address.sin6_addr._S6_un._S6_u32[1] = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[1]);
4826 peer6_address.sin6_addr._S6_un._S6_u32[2] = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[2]);
4827 peer6_address.sin6_addr._S6_un._S6_u32[3] = ntohl(bsd_socket_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[3]);
4828
4829 /* Skip the port data for raw sockets. They do not use them. */
4830 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4831 if(!(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET))
4832 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
4833 peer6_address.sin6_port = ntohs((USHORT)bsd_socket_ptr -> nx_bsd_socket_source_port);
4834 }
4835
4836 if((*fromAddrLen) > (INT)sizeof(peer6_address))
4837 {
4838 *fromAddrLen = sizeof(peer6_address);
4839 }
4840 memcpy(fromAddr, &peer6_address, (UINT)(*fromAddrLen)); /* Use case of memcpy is verified. */
4841
4842 }
4843 else
4844 #endif /* !FEATURE_NX_IPV6 */
4845 #if defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT)
4846 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
4847 {
4848 if(*fromAddrLen >= (INT)sizeof(struct nx_bsd_sockaddr_ll))
4849 {
4850 struct nx_bsd_sockaddr_ll *sockaddr = (struct nx_bsd_sockaddr_ll*)fromAddr;
4851 INT i;
4852 sockaddr -> sll_family = AF_PACKET;
4853 sockaddr -> sll_protocol = bsd_socket_ptr -> nx_bsd_socket_sll_protocol;
4854 sockaddr -> sll_ifindex = bsd_socket_ptr -> nx_bsd_socket_sll_ifindex;
4855 sockaddr -> sll_hatype = 0;
4856 sockaddr -> sll_pkttype = 0;
4857 sockaddr -> sll_halen = 6;
4858 for(i = 0; i < 6; i++)
4859 sockaddr -> sll_addr[i] = bsd_socket_ptr -> nx_bsd_socket_sll_addr[i];
4860 *fromAddrLen = sizeof(struct nx_bsd_sockaddr_ll);
4861 }
4862
4863 }
4864 else
4865 #endif
4866 {
4867
4868 /* Set the socket error if extended socket options enabled. */
4869 nx_bsd_set_errno(EINVAL);
4870
4871 /* Error, IPv6 support is not enabled. */
4872 NX_BSD_ERROR(ERROR, __LINE__);
4873 return(ERROR);
4874 }
4875 }
4876
4877 /* Successful received a packet. Return the number of bytes copied to buffer. */
4878 return((INT)bytes_copied + (INT)header_size);
4879 }
4880
4881
4882 /**************************************************************************/
4883 /* */
4884 /* FUNCTION RELEASE */
4885 /* */
4886 /* soc_close PORTABLE C */
4887 /* 6.3.0 */
4888 /* AUTHOR */
4889 /* */
4890 /* Yuxin Zhou, Microsoft Corporation */
4891 /* */
4892 /* DESCRIPTION */
4893 /* */
4894 /* This function terminates communications on the supplied BSD socket. */
4895 /* The socket is disallowed for further sends and receives. Socket */
4896 /* resources such as socket memory are returned to the system. */
4897 /* */
4898 /* If a socket is enabled with the linger option, that will be used in */
4899 /* place of the default NX_BSD TIMEOUT for blocking sockets. Sockets */
4900 /* enabled for non blocking have their timeout set for zero. Note that */
4901 /* a zero wait option results in an immediate shutdown (e.g. send RST) */
4902 /* unless the NX_DISABLE_RESET_DISCONNECT is not enabled. */
4903 /* */
4904 /* For BSD applications enabled for disconnect complete notification */
4905 /* for TCP sockets, the socket will remain open until NetX notifies us */
4906 /* that the disconnect is complete. This allows the host BSD */
4907 /* application to perform asynchronous disconnects without having to */
4908 /* wait for the disconnect to complete. */
4909 /* */
4910 /* INPUT */
4911 /* */
4912 /* socketID */
4913 /* */
4914 /* OUTPUT */
4915 /* */
4916 /* NX_SOC_OK (0) On success */
4917 /* NX_SOC_ERROR (-1) On failure */
4918 /* */
4919 /* CALLS */
4920 /* */
4921 /* memset Clear memory */
4922 /* nx_tcp_socket_disconnect Disconnect a TCP Socket */
4923 /* nx_tcp_client_socket_unbind Unbind the socket */
4924 /* nx_tcp_server_socket_unaccept Unaccept the socket */
4925 /* nx_tcp_server_socket_unlisten Unlisten on a port */
4926 /* nx_tcp_socket_delete Deletes a TCP Socket */
4927 /* nx_udp_socket_unbind Unbind a UDP Socket */
4928 /* nx_udp_socket_delete Deletes a UDP Socket */
4929 /* tx_block_release Release block for socket */
4930 /* tx_mutex_get Get protection */
4931 /* tx_mutex_put Release protection */
4932 /* */
4933 /* CALLED BY */
4934 /* */
4935 /* Application Code */
4936 /* */
4937 /* RELEASE HISTORY */
4938 /* */
4939 /* DATE NAME DESCRIPTION */
4940 /* */
4941 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
4942 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
4943 /* resulting in version 6.1 */
4944 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
4945 /* used new API/structs naming,*/
4946 /* resulting in version 6.3.0 */
4947 /* */
4948 /**************************************************************************/
nx_bsd_soc_close(INT sockID)4949 INT nx_bsd_soc_close(INT sockID)
4950 {
4951
4952 NX_BSD_SOCKET *bsd_socket_ptr;
4953 NX_TCP_SOCKET *tcp_socket_ptr;
4954 NX_UDP_SOCKET *udp_socket_ptr;
4955 NX_PACKET *packet_ptr;
4956 NX_PACKET *next_packet_ptr;
4957 ULONG timeout;
4958 INT i;
4959 UINT counter;
4960 INT delete_socket;
4961 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
4962 INT protocol;
4963 UINT index;
4964 #endif
4965
4966 /* Check for a valid socket ID. */
4967 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
4968 {
4969
4970 /* Set the socket error. */
4971 nx_bsd_set_errno(EBADF);
4972
4973 /* Error, invalid socket ID. */
4974 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
4975 return(NX_SOC_ERROR);
4976 }
4977
4978 /* Normalize the socket ID. */
4979 sockID = sockID - NX_BSD_SOCKFD_START;
4980
4981 /* Set up a pointer to the BSD socket. */
4982 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
4983
4984 /* Get the protection mutex. */
4985 tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
4986
4987 /* Is the socket already in use? */
4988 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
4989 {
4990
4991 /* No; If the NetX socket associated with this BSD socket been deleted, this is ok. */
4992 if (!bsd_socket_ptr -> nx_bsd_socket_tcp_socket && !bsd_socket_ptr -> nx_bsd_socket_udp_socket)
4993 {
4994
4995 /* Yes, no further action possible. Release the protection mutex. */
4996 tx_mutex_put(nx_bsd_protection_ptr);
4997
4998 return NX_SOC_OK;
4999 }
5000
5001 /* Otherwise, it is an error if socket not in use anymore. */
5002
5003 /* Release the protection mutex. */
5004 tx_mutex_put(nx_bsd_protection_ptr);
5005
5006 /* Set the socket error if extended socket options enabled. */
5007 nx_bsd_set_errno(EACCES);
5008
5009 /* Return error. */
5010 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5011 return(NX_SOC_ERROR);
5012 }
5013
5014 /* Set NetX socket pointers. */
5015 tcp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
5016 udp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_udp_socket;
5017
5018 /* There is. Flush the queue of all packets. */
5019 packet_ptr = bsd_socket_ptr -> nx_bsd_socket_received_packet;
5020 /* Setup packet pointer to the beginning of the queue. */
5021 while(packet_ptr)
5022 {
5023 next_packet_ptr = packet_ptr -> nx_packet_queue_next;
5024
5025 /* Mark it as allocated so it will be released. */
5026 packet_ptr -> nx_packet_queue_next = (NX_PACKET *) NX_PACKET_ALLOCATED;
5027
5028 nx_packet_release(packet_ptr);
5029
5030 /* Move to the next packet */
5031 packet_ptr = next_packet_ptr;
5032 }
5033
5034 bsd_socket_ptr -> nx_bsd_socket_received_packet = NX_NULL;
5035 bsd_socket_ptr -> nx_bsd_socket_received_packet_tail = NX_NULL;
5036 bsd_socket_ptr -> nx_bsd_socket_received_byte_count = 0;
5037 bsd_socket_ptr -> nx_bsd_socket_received_packet_count = 0;
5038 bsd_socket_ptr -> nx_bsd_socket_received_packet_count_max = 0;
5039
5040 /* Now delete the underlying TCP or UDP socket. */
5041
5042 /* Is this a TCP socket? */
5043 if (tcp_socket_ptr)
5044 {
5045
5046 /* If the socket has not been closed, disconnect it. This would be the case
5047 if NetX already closed the socket e.g. a RST packet received before the
5048 host application called this function. */
5049 if (tcp_socket_ptr -> nx_tcp_socket_state != NX_TCP_CLOSED)
5050 {
5051
5052 /* Disconnect the socket. */
5053
5054 /* If the disconnect takes more than the timeout option, NetX marks the socket as "closed"
5055 or puts it back to "listen" state. The default value is 1 to emulate an immediate
5056 socket closure without sending a RST packet. */
5057 timeout = NX_BSD_TCP_SOCKET_DISCONNECT_TIMEOUT;
5058
5059 /* Release the mutex while disconnecting. */
5060 tx_mutex_put(nx_bsd_protection_ptr);
5061
5062 nx_tcp_socket_disconnect(tcp_socket_ptr, timeout);
5063
5064 tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
5065
5066 /* Verify that the socket is still valid. */
5067 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
5068 {
5069 /* The socket is no longer in use. */
5070
5071 /* Set the socket error code. */
5072 nx_bsd_set_errno(EBADF);
5073
5074 /* Release the protection mutex. */
5075 tx_mutex_put(nx_bsd_protection_ptr);
5076
5077 /* Return error code. */
5078 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5079 return(NX_SOC_ERROR);
5080 }
5081 }
5082 /* Make sure the socket is unbound, not accepting connections and not bound to a listening port. */
5083 if(tcp_socket_ptr -> nx_tcp_socket_port)
5084 {
5085
5086 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CLIENT)
5087 {
5088 nx_tcp_client_socket_unbind(tcp_socket_ptr);
5089 }
5090 else
5091 {
5092 nx_tcp_server_socket_unaccept(tcp_socket_ptr);
5093 }
5094
5095 }
5096
5097 /* Now we can delete the NetX TCP socket. */
5098 nx_tcp_socket_delete(tcp_socket_ptr);
5099
5100 /* Clear the TCP socket structure. */
5101 memset((VOID *) tcp_socket_ptr, 0, sizeof(NX_TCP_SOCKET));
5102
5103 /* Release the NetX TCP socket. */
5104 tx_block_release((VOID *) tcp_socket_ptr);
5105
5106 /* If this is the master server socket, we need to unaccept the
5107 associated secondary socket. */
5108 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET)
5109 {
5110
5111 INT sec_soc_id = (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id;
5112
5113 if(sec_soc_id < NX_BSD_MAX_SOCKETS)
5114 {
5115
5116 /* Find whether or not this is the only master socket that is connected to this
5117 secondary socket. */
5118 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
5119 {
5120
5121 if(i == sockID)
5122 continue;
5123
5124 if((nx_bsd_socket_array[i].nx_bsd_socket_protocol == NX_PROTOCOL_TCP) &&
5125 (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) &&
5126 (nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id == sec_soc_id))
5127 {
5128 break;
5129 }
5130 }
5131
5132 if(i == NX_BSD_MAX_SOCKETS)
5133 {
5134
5135 /* Unaccept and unlisten on the socket/port */
5136 /* nx_tcp_server_socket_unaccept(tcp_socket_ptr); */
5137 /* nx_tcp_server_socket_unlisten(nx_bsd_default_ip, tcp_socket_ptr -> nx_tcp_socket_port); */
5138
5139 /* Release the secondary socket if there are no more master sockets associated
5140 with this secondary socket. */
5141
5142 tcp_socket_ptr = nx_bsd_socket_array[sec_soc_id].nx_bsd_socket_tcp_socket;
5143
5144 /* If the secondary socket has not been closed, disconnect it. This would be the case
5145 if NetX already closed the master socket. */
5146 if (tcp_socket_ptr -> nx_tcp_socket_state != NX_TCP_CLOSED)
5147 {
5148
5149 /* Disconnect the socket. */
5150
5151 /* If the disconnect takes more than the timeout option, NetX marks the socket as "closed"
5152 or puts it back to "listen" state. The default value is 1 to emulate an immediate
5153 socket closure without sending a RST packet. */
5154 timeout = NX_BSD_TCP_SOCKET_DISCONNECT_TIMEOUT;
5155
5156 /* Release the mutex while disconnecting. */
5157 tx_mutex_put(nx_bsd_protection_ptr);
5158
5159 nx_tcp_socket_disconnect(tcp_socket_ptr, timeout);
5160
5161 tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
5162
5163 /* Verify that the socket is still valid. */
5164 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
5165 {
5166 /* The socket is no longer in use. */
5167
5168 /* Set the socket error code. */
5169 nx_bsd_set_errno(EBADF);
5170
5171 /* Release the protection mutex. */
5172 tx_mutex_put(nx_bsd_protection_ptr);
5173
5174 /* Return error code. */
5175 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5176 return(NX_SOC_ERROR);
5177 }
5178 }
5179
5180 /* Unaccept on the secondary socket. */
5181 nx_tcp_server_socket_unaccept(tcp_socket_ptr);
5182 nx_tcp_server_socket_unlisten(nx_bsd_default_ip, tcp_socket_ptr -> nx_tcp_socket_port);
5183 nx_tcp_socket_delete(tcp_socket_ptr);
5184
5185 memset((VOID*)tcp_socket_ptr, 0, sizeof(NX_TCP_SOCKET));
5186 tx_block_release((VOID*)tcp_socket_ptr);
5187 memset((VOID*)&(nx_bsd_socket_array[sec_soc_id]), 0, sizeof(NX_BSD_SOCKET));
5188 }
5189 }
5190 }
5191
5192 /* Finally Clear the BSD socket structure. */
5193 memset((VOID *) bsd_socket_ptr, 0, sizeof(NX_BSD_SOCKET));
5194
5195 tx_mutex_put(nx_bsd_protection_ptr);
5196
5197 /* Return */
5198 return(NX_SOC_OK);
5199
5200 }
5201 else if (udp_socket_ptr)
5202 {
5203
5204 /* A UDP socket needs to be closed. */
5205
5206 /* Check whether this is the last BSD socket attached to the NX_UDP_SOCKET */
5207 counter = (UINT)udp_socket_ptr -> nx_udp_socket_reserved_ptr;
5208
5209 delete_socket = NX_TRUE;
5210 /* Decrease the counter value. */
5211 if(counter & 0xFFFF0000)
5212 {
5213
5214 counter = ((counter & 0xFFFF0000) - 0x00010000 + (counter & 0x0000FFFF)) & 0xFFFFFFFF;
5215
5216 udp_socket_ptr -> nx_udp_socket_reserved_ptr = (VOID*)counter;
5217
5218 if(counter & 0xFFFF0000)
5219 {
5220
5221 /* Do not delete this socket. */
5222 delete_socket = NX_FALSE;
5223
5224 /* If the underlying NX_UDP_SOCKET points to this UDP socket, we need to
5225 reassign a BSD socket to the NX UDP socket. */
5226 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
5227 {
5228
5229 if((nx_bsd_socket_array[i].nx_bsd_socket_udp_socket == udp_socket_ptr) &&
5230 (i != sockID))
5231 {
5232
5233 counter = (counter & 0xFFFF0000) + (UINT)i;
5234 udp_socket_ptr -> nx_udp_socket_reserved_ptr = (VOID*)counter;
5235 break;
5236 }
5237 }
5238
5239 if(i == NX_BSD_MAX_SOCKETS)
5240 {
5241 delete_socket = NX_TRUE;
5242 }
5243 }
5244 }
5245
5246 if(delete_socket == NX_TRUE)
5247 {
5248
5249 if(udp_socket_ptr -> nx_udp_socket_bound_next)
5250 {
5251 nx_udp_socket_unbind(udp_socket_ptr);
5252 }
5253
5254 /* Socket successfully unbound. Now delete the UDP socket. */
5255 nx_udp_socket_delete(udp_socket_ptr);
5256
5257 /* Clear the UDP socket block. */
5258 memset((VOID *) udp_socket_ptr, 0, sizeof(NX_UDP_SOCKET));
5259
5260 /* Release the NetX UDP socket memory. */
5261 tx_block_release((VOID *) udp_socket_ptr);
5262 }
5263 else
5264 {
5265 /* Remove this bsd udp socket from the list. */
5266 (bsd_socket_ptr -> nx_bsd_socket_next) -> nx_bsd_socket_previous = bsd_socket_ptr -> nx_bsd_socket_previous;
5267 (bsd_socket_ptr -> nx_bsd_socket_previous) -> nx_bsd_socket_next = bsd_socket_ptr -> nx_bsd_socket_next;
5268 }
5269
5270 /* Clear the BSD socket block. */
5271 memset((VOID *) bsd_socket_ptr, 0, sizeof(NX_BSD_SOCKET));
5272
5273 /* Release the protection mutex. */
5274 tx_mutex_put(nx_bsd_protection_ptr);
5275
5276 return(NX_SOC_OK);
5277 }
5278
5279 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
5280 else if (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET)
5281 {
5282
5283 /* There is no native NetX Duo raw socket to delete or
5284 port to unbind. So just release the BSD socket memory. */
5285
5286 /* Remove this socket from the list. */
5287 protocol = bsd_socket_ptr -> nx_bsd_socket_protocol;
5288
5289 /* Calculate the hash index in the raw socket protocol table. */
5290 index = (UINT) ((protocol + (protocol >> 8)) & NX_BSD_SOCKET_RAW_PROTOCOL_TABLE_MASK);
5291
5292 /* Determine if this is the only socket on this list. */
5293 if(bsd_socket_ptr -> nx_bsd_socket_next == bsd_socket_ptr)
5294 {
5295 /* Yes, this is the only socket on the list. */
5296
5297 /* Clear the list head pointer. */
5298 nx_bsd_socket_raw_protocol_table[index] = NX_NULL;
5299 }
5300 else
5301 {
5302 /* Remove this bsd udp socket from the list. */
5303 (bsd_socket_ptr -> nx_bsd_socket_next) -> nx_bsd_socket_previous = bsd_socket_ptr -> nx_bsd_socket_previous;
5304 (bsd_socket_ptr -> nx_bsd_socket_previous) -> nx_bsd_socket_next = bsd_socket_ptr -> nx_bsd_socket_next;
5305
5306 /* Determine if the head of the list points to the socket being removed.
5307 If so, we need to move the head pointer. */
5308 if(nx_bsd_socket_raw_protocol_table[index] == bsd_socket_ptr)
5309 {
5310 /* Yes, we need to move the list head pointer. */
5311 nx_bsd_socket_raw_protocol_table[index] = bsd_socket_ptr -> nx_bsd_socket_next;
5312 }
5313 }
5314
5315 /* Clear the BSD socket block. */
5316 memset((VOID *) bsd_socket_ptr, 0, sizeof(NX_BSD_SOCKET));
5317
5318 /* Release the protection mutex. */
5319 tx_mutex_put(nx_bsd_protection_ptr);
5320
5321 return(NX_SOC_OK);
5322
5323 }
5324 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
5325 #if defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT)
5326 else if(bsd_socket_ptr -> nx_bsd_socket_family == AF_PACKET)
5327 {
5328 /* There is no native NetX Duo raw socket to delete or
5329 port to unbind. So just release the BSD socket memory. */
5330
5331 /* Clear the BSD socket block. */
5332 memset((VOID *) bsd_socket_ptr, 0, sizeof(NX_BSD_SOCKET));
5333
5334 /* Release the protection mutex. */
5335 tx_mutex_put(nx_bsd_protection_ptr);
5336
5337 return(NX_SOC_OK);
5338 }
5339
5340 #endif /* defined(NX_BSD_RAW_PPPOE_SUPPORT) || defined(NX_BSD_RAW_SUPPORT) */
5341
5342
5343
5344
5345 /* Unknown socket type or invalid socket. */
5346
5347 /* Release the protection mutex. */
5348 tx_mutex_put(nx_bsd_protection_ptr);
5349
5350 /* Set the socket error if extended socket options enabled. */
5351 nx_bsd_set_errno(EINVAL);
5352
5353 /* Return error. */
5354 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5355 return(NX_SOC_ERROR);
5356
5357
5358
5359 }
5360
5361 /**************************************************************************/
5362 /* */
5363 /* FUNCTION RELEASE */
5364 /* */
5365 /* fcntl PORTABLE C */
5366 /* 6.3.0 */
5367 /* AUTHOR */
5368 /* */
5369 /* Yuxin Zhou, Microsoft Corporation */
5370 /* */
5371 /* DESCRIPTION */
5372 /* */
5373 /* This function performs the requested operation on the file (e.g. */
5374 /* socket) descriptor set. This implementation supports only the set */
5375 /* or get flag, and only sets (or clears) the non blocking option. */
5376 /* */
5377 /* INPUT */
5378 /* */
5379 /* sockID socket descriptor */
5380 /* flag_type File description request */
5381 /* f_options Option(s) to set on the */
5382 /* specified file (socket) */
5383 /* */
5384 /* OUTPUT */
5385 /* */
5386 /* NX_SOC_ERROR Errors with request */
5387 /* (file descriptor flags) File descriptor flags */
5388 /* */
5389 /* CALLS */
5390 /* */
5391 /* tx_mutex_get Get protection */
5392 /* tx_mutex_put Release protection */
5393 /* */
5394 /* CALLED BY */
5395 /* */
5396 /* Application Code */
5397 /* */
5398 /* RELEASE HISTORY */
5399 /* */
5400 /* DATE NAME DESCRIPTION */
5401 /* */
5402 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5403 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5404 /* resulting in version 6.1 */
5405 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
5406 /* used new API/structs naming,*/
5407 /* resulting in version 6.3.0 */
5408 /* */
5409 /**************************************************************************/
nx_bsd_fcntl(INT sockID,UINT flag_type,UINT f_options)5410 INT nx_bsd_fcntl(INT sockID, UINT flag_type, UINT f_options)
5411 {
5412
5413 NX_BSD_SOCKET *bsd_socket_ptr;
5414
5415 /* Check for invalid socket ID. */
5416 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
5417 {
5418
5419 /* Set the socket error if extended options enabled. */
5420 nx_bsd_set_errno(EBADF);
5421
5422 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5423
5424 /* Return error status. */
5425 return NX_SOC_ERROR;
5426 }
5427
5428 /* Normalize the socket ID to our array. */
5429 sockID = sockID - NX_BSD_SOCKFD_START;
5430
5431 /* Build pointer to BSD socket structure. */
5432 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
5433
5434 if(flag_type == F_SETFL)
5435 {
5436 /* Set the FD flag. */
5437 bsd_socket_ptr -> nx_bsd_file_descriptor_flags = (INT)f_options;
5438
5439
5440 /* Are there flags to clear? */
5441 if ((f_options & O_NONBLOCK) == 0)
5442 {
5443 /* Disable the socket for non blocking. */
5444 bsd_socket_ptr -> nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING);
5445 }
5446 else
5447 {
5448 /* Enable the socket for non blocking. */
5449 bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING;
5450 }
5451
5452 /* All done. Return 0 */
5453 return(0);
5454 }
5455 else if(flag_type == F_GETFL)
5456 {
5457 return(bsd_socket_ptr -> nx_bsd_file_descriptor_flags);
5458 }
5459 /* Flag_type is not the one we support */
5460
5461 /* Set the socket error if extended socket options enabled. */
5462 nx_bsd_set_errno(EINVAL);
5463
5464 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5465
5466 /* Return error status. */
5467 return NX_SOC_ERROR;
5468
5469
5470
5471 }
5472
5473
5474 /**************************************************************************/
5475 /* */
5476 /* FUNCTION RELEASE */
5477 /* */
5478 /* ioctl PORTABLE C */
5479 /* 6.4.0 */
5480 /* AUTHOR */
5481 /* */
5482 /* Yuxin Zhou, Microsoft Corporation */
5483 /* */
5484 /* DESCRIPTION */
5485 /* */
5486 /* This function carries out a socket IO service specified by the */
5487 /* command. */
5488 /* */
5489 /* INPUT */
5490 /* */
5491 /* sockID Socket (must be connected). */
5492 /* command IO command for ioctl function */
5493 /* result data returned (value) */
5494 /* */
5495 /* OUTPUT */
5496 /* */
5497 /* Number of bytes received If success */
5498 /* NX_SOC_ERROR (-1) Error during socket opration */
5499 /* NX_SOC_OK (0) Successful completion */
5500 /* */
5501 /* CALLS */
5502 /* */
5503 /* nx_tcp_socket_bytes_available Retreive number of bytes on */
5504 /* the specified TCP socket */
5505 /* nx_udp_socket_bytes_available Retreive number of bytes on */
5506 /* the specified UDP socket */
5507 /* tx_mutex_get Get protection */
5508 /* tx_mutex_put Release protection */
5509 /* */
5510 /* CALLED BY */
5511 /* */
5512 /* Application Code */
5513 /* */
5514 /* RELEASE HISTORY */
5515 /* */
5516 /* DATE NAME DESCRIPTION */
5517 /* */
5518 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5519 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5520 /* resulting in version 6.1 */
5521 /* 03-08-2023 Wenhui Xie Modified comment(s), corrected*/
5522 /* the result of FIONREAD, */
5523 /* resulting in version 6.2.1 */
5524 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
5525 /* used new API/structs naming,*/
5526 /* resulting in version 6.3.0 */
5527 /* 12-31-2023 Yanwu Cai Modified comment(s), and */
5528 /* added SIOCGIFINDEX and */
5529 /* SIOCGIFHWADDR commands, */
5530 /* resulting in version 6.4.0 */
5531 /* */
5532 /**************************************************************************/
nx_bsd_ioctl(INT sockID,INT command,INT * result)5533 INT nx_bsd_ioctl(INT sockID, INT command, INT *result)
5534 {
5535
5536 NX_BSD_SOCKET *bsd_socket_ptr;
5537 NX_TCP_SOCKET *tcp_socket_ptr;
5538 NX_UDP_SOCKET *udp_socket_ptr;
5539 UINT status;
5540 #ifdef NX_BSD_RAW_SUPPORT
5541 UINT i;
5542 struct nx_bsd_ifreq *ifreq;
5543 NX_INTERFACE *nx_interface;
5544 #endif
5545
5546 /* Check that the supplied socket ID is valid. */
5547 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
5548 {
5549
5550 /* Error, invalid socket ID. */
5551 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5552 return(NX_SOC_ERROR);
5553 }
5554
5555 /* Normalize the socket ID. */
5556 sockID = sockID - NX_BSD_SOCKFD_START;
5557
5558 /* Get the protection mutex. */
5559 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
5560
5561 /* Check the status. */
5562 if (status)
5563 {
5564
5565 /* Error getting the protection mutex. */
5566 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
5567 return(NX_SOC_ERROR);
5568 }
5569
5570 /* Set a pointer to the BSD socket. */
5571 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
5572
5573 /* Pick up the associated NetX socket pointers. */
5574 tcp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_tcp_socket;
5575 udp_socket_ptr = bsd_socket_ptr -> nx_bsd_socket_udp_socket;
5576
5577 /* Handle the command. */
5578 switch (command)
5579 {
5580
5581 case FIONREAD:
5582 {
5583
5584 /* Check NULL pointer. */
5585 if(result == NX_NULL)
5586 {
5587 tx_mutex_put(nx_bsd_protection_ptr);
5588
5589 nx_bsd_set_errno(EFAULT);
5590
5591 /* Error, invalid address. */
5592 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5593
5594 return(NX_SOC_ERROR);
5595 }
5596
5597 /* Determine which socket pointer to use. */
5598 if (tcp_socket_ptr)
5599 {
5600
5601 /* Extract the number of bytes on the TCP receive queue. */
5602 status = nx_tcp_socket_bytes_available(tcp_socket_ptr, (ULONG *)result);
5603
5604 if (status != NX_SUCCESS)
5605 {
5606
5607 tx_mutex_put(nx_bsd_protection_ptr);
5608
5609 /* Error in the native NetX call. */
5610 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
5611 return(NX_SOC_ERROR);
5612 }
5613 else
5614 {
5615 *result += (INT)(bsd_socket_ptr -> nx_bsd_socket_received_byte_count);
5616 }
5617 }
5618 else if (udp_socket_ptr)
5619 {
5620
5621 /* Extract the number of bytes on the UDP receive queue. */
5622 *result = (INT)(bsd_socket_ptr -> nx_bsd_socket_received_byte_count);
5623 }
5624
5625 break;
5626 }
5627
5628 case FIONBIO:
5629 {
5630
5631 /* Check NULL pointer. */
5632 if(result == NX_NULL)
5633 {
5634 tx_mutex_put(nx_bsd_protection_ptr);
5635
5636 nx_bsd_set_errno(EFAULT);
5637
5638 /* Error, invalid address. */
5639 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5640
5641 return(NX_SOC_ERROR);
5642 }
5643
5644 if(*result == NX_FALSE)
5645 {
5646
5647 /* Disable the socket for non blocking. */
5648 bsd_socket_ptr -> nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING);
5649
5650 /* Update the file descriptor with the non blocking bit. */
5651 bsd_socket_ptr -> nx_bsd_file_descriptor_flags &= ~O_NONBLOCK;
5652 }
5653 else
5654 {
5655
5656 /* Enable the socket for non blocking. */
5657 bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING;
5658
5659 /* Update the file descriptor with the non blocking bit. */
5660 bsd_socket_ptr -> nx_bsd_file_descriptor_flags |= O_NONBLOCK;
5661 }
5662
5663 break;
5664 }
5665
5666 #ifdef NX_BSD_RAW_SUPPORT
5667 case SIOCGIFINDEX:
5668 {
5669 ifreq = (struct nx_bsd_ifreq*)result;
5670
5671 for (i = 0; i < NX_MAX_IP_INTERFACES; i++)
5672 {
5673 if (strncmp(ifreq->ifr_name, nx_bsd_default_ip->nx_ip_interface[i].nx_interface_name, NX_BSD_IFNAMSIZE) == 0)
5674 {
5675 break;
5676 }
5677 }
5678
5679 if (i == NX_MAX_IP_INTERFACES)
5680 {
5681 tx_mutex_put(nx_bsd_protection_ptr);
5682
5683 /* Did not find a matching interface. */
5684 nx_bsd_set_errno(EINVAL);
5685
5686 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5687 return NX_SOC_ERROR;
5688 }
5689
5690 ifreq -> ifr_ifindex = (INT)i;
5691
5692 break;
5693 }
5694
5695 case SIOCGIFHWADDR:
5696 {
5697 ifreq = (struct nx_bsd_ifreq*)result;
5698
5699 if (ifreq -> ifr_ifindex < 0 || ifreq -> ifr_ifindex >= NX_MAX_IP_INTERFACES)
5700 {
5701 tx_mutex_put(nx_bsd_protection_ptr);
5702 nx_bsd_set_errno(EINVAL);
5703 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5704 return NX_SOC_ERROR;
5705 }
5706
5707 nx_interface = &nx_bsd_default_ip -> nx_ip_interface[ifreq -> ifr_ifindex];
5708 if (!(nx_interface -> nx_interface_valid))
5709 {
5710 tx_mutex_put(nx_bsd_protection_ptr);
5711 nx_bsd_set_errno(EINVAL);
5712 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
5713 return NX_SOC_ERROR;
5714 }
5715
5716 ifreq -> ifr_hwaddr.sa_data[0] = (UCHAR)(nx_interface -> nx_interface_physical_address_msw >> 8);
5717 ifreq -> ifr_hwaddr.sa_data[1] = (UCHAR)(nx_interface -> nx_interface_physical_address_msw & 0xFF);
5718 ifreq -> ifr_hwaddr.sa_data[2] = (UCHAR)(nx_interface -> nx_interface_physical_address_lsw >> 24);
5719 ifreq -> ifr_hwaddr.sa_data[3] = (UCHAR)(nx_interface -> nx_interface_physical_address_lsw >> 16);
5720 ifreq -> ifr_hwaddr.sa_data[4] = (UCHAR)(nx_interface -> nx_interface_physical_address_lsw >> 8);
5721 ifreq -> ifr_hwaddr.sa_data[5] = (UCHAR)(nx_interface -> nx_interface_physical_address_lsw & 0xFF);
5722
5723 break;
5724 }
5725 #endif
5726
5727 default:
5728
5729 /* Unhandled command; ignore */
5730 break;
5731 }
5732
5733 tx_mutex_put(nx_bsd_protection_ptr);
5734
5735 return NX_SOC_OK;
5736 }
5737
5738 /**************************************************************************/
5739 /* */
5740 /* FUNCTION RELEASE */
5741 /* */
5742 /* inet_ntoa PORTABLE C */
5743 /* 6.3.0 */
5744 /* AUTHOR */
5745 /* */
5746 /* Yuxin Zhou, Microsoft Corporation */
5747 /* */
5748 /* DESCRIPTION */
5749 /* */
5750 /* This function converts an IP address to a string and returns a */
5751 /* pointer to the string. The caller is recommended to copy the */
5752 /* contents of the buffer to local memory since this function and */
5753 /* internal buffer can be reused. */
5754 /* */
5755 /* INPUT */
5756 /* */
5757 /* address_to_convert Struct holding IP address. */
5758 /* */
5759 /* OUTPUT */
5760 /* */
5761 /* char * Pointer to converted string */
5762 /* 0x0 Error during conversion */
5763 /* */
5764 /* CALLS */
5765 /* */
5766 /* tx_mutex_get Get mutex protection */
5767 /* bsd_number_convert Convert integer to ascii */
5768 /* */
5769 /* CALLED BY */
5770 /* */
5771 /* Application Code */
5772 /* */
5773 /* RELEASE HISTORY */
5774 /* */
5775 /* DATE NAME DESCRIPTION */
5776 /* */
5777 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5778 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5779 /* resulting in version 6.1 */
5780 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
5781 /* used new API/structs naming,*/
5782 /* resulting in version 6.3.0 */
5783 /* */
5784 /**************************************************************************/
nx_bsd_inet_ntoa(struct nx_bsd_in_addr address_to_convert)5785 CHAR *nx_bsd_inet_ntoa(struct nx_bsd_in_addr address_to_convert)
5786 {
5787 UINT status;
5788
5789 /* Because we are using global buffer space to write out the string, get the protection mutex. */
5790 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
5791
5792 if (status != NX_SUCCESS)
5793 {
5794 return NX_NULL;
5795 }
5796
5797 inet_ntoa_internal(&address_to_convert, nx_bsd_url_buffer, NX_BSD_URL_BUFSIZE);
5798
5799 tx_mutex_put(nx_bsd_protection_ptr);
5800
5801 /* Return the start of the string buffer. */
5802 return nx_bsd_url_buffer;
5803
5804 }
5805
5806 /**************************************************************************/
5807 /* */
5808 /* FUNCTION RELEASE */
5809 /* */
5810 /* bsd_number_convert PORTABLE C */
5811 /* 6.1 */
5812 /* AUTHOR */
5813 /* */
5814 /* Yuxin Zhou, Microsoft Corporation */
5815 /* */
5816 /* DESCRIPTION */
5817 /* */
5818 /* This function converts an integer to a string. */
5819 /* */
5820 /* INPUT */
5821 /* */
5822 /* number Number to convert */
5823 /* string Pointer to string buffer */
5824 /* buffer_len Size of the string buffer */
5825 /* base the base of the number, */
5826 /* 2,8,10,16 */
5827 /* */
5828 /* OUTPUT */
5829 /* */
5830 /* size Size of string buffer */
5831 /* */
5832 /* CALLS */
5833 /* */
5834 /* None */
5835 /* */
5836 /* CALLED BY */
5837 /* */
5838 /* Application Code */
5839 /* */
5840 /* RELEASE HISTORY */
5841 /* */
5842 /* DATE NAME DESCRIPTION */
5843 /* */
5844 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5845 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5846 /* resulting in version 6.1 */
5847 /* */
5848 /**************************************************************************/
bsd_number_convert(UINT number,CHAR * string,ULONG buffer_len,UINT base)5849 UINT bsd_number_convert(UINT number, CHAR *string, ULONG buffer_len, UINT base)
5850 {
5851
5852 UINT j;
5853 UINT digit;
5854 UINT size;
5855
5856
5857 /* Initialize counters. */
5858 size = 0;
5859
5860 /* Loop to convert the number to ASCII. */
5861 while (size < buffer_len)
5862 {
5863
5864 /* Shift the current digits over one. */
5865 for (j = size; j != 0; j--)
5866 {
5867
5868 /* Move each digit over one place. */
5869 string[j] = string[j-1];
5870 }
5871
5872 /* Compute the next decimal digit. */
5873 digit = number % base;
5874
5875 /* Update the input number. */
5876 number = number / base;
5877
5878 /* Store the new digit in ASCII form. */
5879 if(digit < 10)
5880 string[0] = (CHAR) (digit + 0x30);
5881 else
5882 string[0] = (CHAR) (digit + 0x57);
5883
5884 /* Increment the size. */
5885 size++;
5886
5887 /* Determine if the number is now zero. */
5888 if (number == 0)
5889 break;
5890 }
5891
5892 /* Make the string NULL terminated. */
5893 string[size] = (CHAR) NX_NULL;
5894
5895 /* Determine if there is an overflow error. */
5896 if (number)
5897 {
5898
5899 /* Error, return bad values to user. */
5900 size = 0;
5901 string[0] = '0';
5902 }
5903
5904 /* Return size to caller. */
5905 return(size);
5906 }
5907
5908 /**************************************************************************/
5909 /* */
5910 /* FUNCTION RELEASE */
5911 /* */
5912 /* inet_aton PORTABLE C */
5913 /* 6.3.0 */
5914 /* AUTHOR */
5915 /* */
5916 /* Yuxin Zhou, Microsoft Corporation */
5917 /* */
5918 /* DESCRIPTION */
5919 /* */
5920 /* This function converts hexadecimal characters into an ASCII IP */
5921 /* address representation. */
5922 /* */
5923 /* INPUT */
5924 /* */
5925 /* address_buffer_ptr String holding the IP address */
5926 /* addr Struct to store the IP address*/
5927 /* */
5928 /* OUTPUT */
5929 /* */
5930 /* NX_SUCCESS Successful conversion */
5931 /* NX_SOC_ERROR Error during conversion */
5932 /* */
5933 /* CALLS */
5934 /* */
5935 /* nx_bsd_isdigit Indicate char is a number */
5936 /* isspace Indicate char is a space */
5937 /* islower Indicate char is lowercase */
5938 /* htonl Convert to network byte order */
5939 /* */
5940 /* CALLED BY */
5941 /* */
5942 /* Application Code */
5943 /* */
5944 /* RELEASE HISTORY */
5945 /* */
5946 /* DATE NAME DESCRIPTION */
5947 /* */
5948 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
5949 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
5950 /* resulting in version 6.1 */
5951 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
5952 /* used new API/structs naming,*/
5953 /* resulting in version 6.3.0 */
5954 /* */
5955 /**************************************************************************/
nx_bsd_inet_aton(const CHAR * address_buffer_ptr,struct nx_bsd_in_addr * addr)5956 INT nx_bsd_inet_aton(const CHAR *address_buffer_ptr, struct nx_bsd_in_addr *addr)
5957 {
5958 ULONG value;
5959 INT base = 10, ip_address_index;
5960 UCHAR tempchar;
5961 const UCHAR *buffer_ptr;
5962 UINT ip_address_number[4]; /* Four discreet numbers in IP address representation. */
5963 UINT *ip_number_ptr; /* IP address as equivalent ULONG value. */
5964 UINT dot_flag;
5965
5966 /* Set local variables. */
5967 buffer_ptr = (const UCHAR *) address_buffer_ptr;
5968 ip_number_ptr = ip_address_number;
5969
5970 tempchar = *buffer_ptr;
5971
5972 /* Check for an invalid first character. */
5973 if (nx_bsd_isdigit(tempchar)== NX_FALSE)
5974 {
5975 return (0);
5976 }
5977
5978 dot_flag = 1;
5979
5980 /* Parse the rest of the characters from the input number. */
5981 do
5982 {
5983
5984 /* Initialize the (next) extracted IP address number to zero. */
5985 value = 0;
5986
5987 if(dot_flag== 1)
5988 {
5989 /* Initialize the numeric base to decimal unless we determine hex or octal. */
5990 base = 10;
5991
5992 /* Determine which number base the input number buffer is. */
5993 if (*buffer_ptr == '0')
5994 {
5995 /* Get the next character. */
5996 buffer_ptr++;
5997
5998 /* A leading 0 followed by an 'x' indicates this is hexidecimal. */
5999 if ((*buffer_ptr== 'x') || (*buffer_ptr == 'X'))
6000 {
6001 base = 16;
6002
6003 /* Move ahead one character past the leading '0x' */
6004 buffer_ptr++;
6005 }
6006 else
6007 {
6008 /* This is octal. */
6009 base = 8;
6010 buffer_ptr--;
6011 }
6012 }
6013 }
6014
6015 tempchar = *buffer_ptr;
6016
6017 /* Parse characters making up the next word. */
6018 while (*buffer_ptr != '\0')
6019 {
6020 /* Check if the next character is a decimal or octal digit. */
6021 if (nx_bsd_isdigit(tempchar))
6022 {
6023
6024 dot_flag = 0;
6025
6026 /* Convert the tempchar character to a number. Multiply the existing
6027 number by the base (8 or 10) and this digit to the sum. */
6028 value = (value * (ULONG)base) + (ULONG)(tempchar - '0');
6029
6030 /* Advance the IP address pointer to the next character. */
6031 buffer_ptr++;
6032
6033 /* Get the next character. */
6034 tempchar = *buffer_ptr;
6035 }
6036 /* Else check if we are expecting a hexidecimal number. */
6037 else if (nx_bsd_isxdigit(tempchar))
6038 {
6039 /* We are; Verify the base is 16. */
6040 if(base == 16)
6041 {
6042
6043 /* It is. handle upper or lower case hex digit. */
6044 CHAR c = (CHAR)(nx_bsd_islower(tempchar) ? 'a' : 'A');
6045
6046 dot_flag = 0;
6047
6048 /* Convert the hex character to a hex digit, multiply the existing word by shifting the bits,
6049 and add this hex digit to the sum. */
6050 value = (value << 4) + (ULONG)(tempchar + 10 - c);
6051
6052 buffer_ptr++;
6053
6054 /* Get the next character. */
6055 tempchar = *buffer_ptr;
6056 }
6057 else
6058 {
6059 /* Not a valid hex character. */
6060 return (0);
6061 }
6062 }
6063 else
6064 {
6065 /* We have reached a number separator or possibly end of the string. */
6066 break;
6067 }
6068 }
6069
6070 /* At the end of the current word. Is this a separator character? */
6071 if (*buffer_ptr == '.')
6072 {
6073
6074 dot_flag = 1;
6075
6076 /* Yes, check for an invalid number (cannot exceed 255 or 0xFF. */
6077 if (value > 0xff)
6078 {
6079 return (0);
6080 }
6081
6082 /* Check that the pointer to the last extracted number does not exceed the array holding the IP address numbers. */
6083 if (ip_number_ptr >= (ip_address_number + 3))
6084 {
6085 return (0);
6086 }
6087
6088 /* Copy the computed value into the IP address number buffer. */
6089 *ip_number_ptr = value;
6090
6091 /* Move the pointer to where we will store the next number extracted. */
6092 ip_number_ptr++;
6093
6094 /* Move to the next character in the IP address string. */
6095 buffer_ptr++;
6096 }
6097 /* Check for non digit or seperator character indicating (maybe) end of the buffer. */
6098 else
6099 break;
6100
6101 } while (1);
6102
6103 /* If this is not a null terminating character, check for invalid trailing characters. */
6104 if (*buffer_ptr)
6105 {
6106
6107 if((*buffer_ptr != '\0') && (!nx_bsd_isspace(*buffer_ptr)))
6108 {
6109
6110 return (0);
6111 }
6112 }
6113
6114 /* IP addresses are grouped as A, B, C, or D types. Determine which
6115 type address we have by comparing the IP address value against...*/
6116
6117 /* Determine this by substracting the pointer to beginning of the whole
6118 IP address number ip_number_ptr[4] against the pointer to the last extracted word, ip_address_number. */
6119 ip_address_index = ip_number_ptr - ip_address_number + 1;
6120
6121 /* Check for an invalid array index (assume 'the array' is indexed 1-4). */
6122 if ((ip_address_index == 0) || (ip_address_index > 4))
6123 {
6124 return (0);
6125 }
6126
6127 /* Sum each of the individual IP address numbers depending how many there were extracted. */
6128
6129 /* Most common input... */
6130 if (ip_address_index == 4)
6131 {
6132 INT i;
6133
6134 /* Three separators parsed, so the format is a.b.c.d where c is 8 bits */
6135
6136 /* Check for a computed sum greater than can be contained in 8 bits. */
6137 if (value > 0xff)
6138 return (0);
6139
6140 /* 'Add' the last extracted number by prepending the three other bytes onto the total value. */
6141 for (i = 0; i<=2; i++)
6142 {
6143 value |= ip_address_number[i] << (24 - (i*8));
6144 }
6145 }
6146 /* Most common input... */
6147 else if (ip_address_index == 1)
6148 {
6149
6150 /* We are done, this address contained one 32 bit word (no separators). */
6151 }
6152 /* Less common input... */
6153 else if (ip_address_index == 2)
6154 {
6155 /* One separator, so the format is a.b where b is 24 bits */
6156
6157 /* Check for a computed sum greater than can be contained in 24 bits. */
6158 if (value > 0xffffff)
6159 return (0);
6160
6161 /* 'Add' the last extracted number by prepending the most significant byte onto the total value. */
6162 value |= (ip_address_number[0] << 24);
6163 }
6164 else if (ip_address_index == 3)
6165 {
6166 /* Two separators parsed, so the format is a.b.c where c is 16 bits */
6167 INT i;
6168
6169 /* Check for a computed sum greater than can be contained in 16 bits. */
6170 if (value > 0xffff)
6171 return (0);
6172
6173 /* 'Add' the last extracted number by prepending the two most significant bytes onto the total value. */
6174 for (i = 0; i<=1; i++)
6175 {
6176 value |= ip_address_number[i] << (24 - (i*8));
6177 }
6178 }
6179
6180 /* Check if a return pointer for the address data is supplied. */
6181 if (addr)
6182 {
6183
6184 /* Convert the IP address data to network byte order and return the data. */
6185 addr->s_addr = htonl(value);
6186 }
6187
6188 return (1);
6189 }
6190
6191
6192 /**************************************************************************/
6193 /* */
6194 /* FUNCTION RELEASE */
6195 /* */
6196 /* inet_addr PORTABLE C */
6197 /* 6.3.0 */
6198 /* AUTHOR */
6199 /* */
6200 /* Yuxin Zhou, Microsoft Corporation */
6201 /* */
6202 /* DESCRIPTION */
6203 /* */
6204 /* This function converts an IP address string to a number. If it */
6205 /* detects an error in the conversion it returns a zero address. */
6206 /* */
6207 /* INPUT */
6208 /* */
6209 /* buffer IP address text buffer */
6210 /* address Converted address number */
6211 /* */
6212 /* OUTPUT */
6213 /* */
6214 /* NX_SUCCESS Successful conversion */
6215 /* NX_SOC_ERROR Error during conversion */
6216 /* */
6217 /* CALLS */
6218 /* */
6219 /* inet_aton Indicate char is a space */
6220 /* */
6221 /* CALLED BY */
6222 /* */
6223 /* Application Code */
6224 /* */
6225 /* RELEASE HISTORY */
6226 /* */
6227 /* DATE NAME DESCRIPTION */
6228 /* */
6229 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6230 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6231 /* resulting in version 6.1 */
6232 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
6233 /* used new API/structs naming,*/
6234 /* resulting in version 6.3.0 */
6235 /* */
6236 /**************************************************************************/
nx_bsd_inet_addr(const CHAR * buffer)6237 nx_bsd_in_addr_t nx_bsd_inet_addr(const CHAR *buffer)
6238 {
6239
6240 struct nx_bsd_in_addr ip_address;
6241 UINT status;
6242
6243 status = (UINT)nx_bsd_inet_aton(buffer, &ip_address);
6244
6245 if (status == 0)
6246 {
6247 return (0xFFFFFFFF);
6248 }
6249
6250 return(ip_address.s_addr);
6251 }
6252
6253
6254 /**************************************************************************/
6255 /* */
6256 /* FUNCTION RELEASE */
6257 /* */
6258 /* getsockopt PORTABLE C */
6259 /* 6.3.0 */
6260 /* AUTHOR */
6261 /* */
6262 /* Yuxin Zhou, Microsoft Corporation */
6263 /* */
6264 /* DESCRIPTION */
6265 /* */
6266 /* This function returns the status of the specified socket option in */
6267 /* the current BSD socket session. */
6268 /* */
6269 /* INPUT */
6270 /* */
6271 /* sockID socket descriptor */
6272 /* option_level Category of option (SOCKET) */
6273 /* option_name Socket option ID */
6274 /* option_value Pointer to option value */
6275 /* option_value Pointer to size of value */
6276 /* */
6277 /* OUTPUT */
6278 /* */
6279 /* tx_mutex_get Get protection */
6280 /* tx_mutex_put Release protection */
6281 /* */
6282 /* CALLS */
6283 /* */
6284 /* NX_SOC_OK Request processed successfully*/
6285 /* NX_SOC_ERROR Errors with request */
6286 /* (option data) Pointer to requested data */
6287 /* */
6288 /* CALLED BY */
6289 /* */
6290 /* Application Code */
6291 /* */
6292 /* RELEASE HISTORY */
6293 /* */
6294 /* DATE NAME DESCRIPTION */
6295 /* */
6296 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6297 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6298 /* resulting in version 6.1 */
6299 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
6300 /* used new API/structs naming,*/
6301 /* resulting in version 6.3.0 */
6302 /* */
6303 /**************************************************************************/
nx_bsd_getsockopt(INT sockID,INT option_level,INT option_name,VOID * option_value,INT * option_length)6304 INT nx_bsd_getsockopt(INT sockID, INT option_level, INT option_name, VOID *option_value, INT *option_length)
6305 {
6306
6307 TX_INTERRUPT_SAVE_AREA
6308
6309 INT status;
6310 NX_BSD_SOCKET *bsd_socket_ptr;
6311 struct nx_bsd_sock_errno *so_errno;
6312 struct nx_bsd_sock_keepalive *so_keepalive;
6313 struct nx_bsd_sock_reuseaddr *so_reuseaddr;
6314 struct nx_bsd_timeval *so_rcvtimeval;
6315 struct nx_bsd_sock_winsize *soc_window_size;
6316 ULONG ticks;
6317
6318
6319 /* Check for valid socket ID/descriptor. */
6320 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
6321 {
6322
6323 /* Set the socket error if extended options enabled. */
6324 nx_bsd_set_errno(EBADF);
6325
6326 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6327 return(NX_SOC_ERROR);
6328 }
6329
6330 /* Check for invalid input. */
6331 if((option_value == NX_NULL) || (option_length == NX_NULL))
6332 {
6333
6334 /* Set the socket error if extended socket options enabled. */
6335 nx_bsd_set_errno(EINVAL);
6336
6337 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6338 return NX_SOC_ERROR;
6339 }
6340
6341 if (option_level == IPPROTO_IP)
6342 {
6343
6344 if((option_name <= SO_MAX) || (option_name > IP_OPTION_MAX))
6345 {
6346
6347 /* Error, one or more invalid arguments. */
6348
6349 /* Set the socket error if extended socket options enabled. */
6350 nx_bsd_set_errno(ENOPROTOOPT);
6351
6352 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6353 return NX_SOC_ERROR;
6354 }
6355 }
6356 else if(option_level == SOL_SOCKET)
6357 {
6358
6359 if((option_name > SO_MAX) || (option_name < SO_MIN))
6360 {
6361
6362 /* Error, one or more invalid arguments. */
6363
6364 /* Set the socket error if extended socket options enabled. */
6365 nx_bsd_set_errno(ENOPROTOOPT);
6366
6367 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6368 return NX_SOC_ERROR;
6369 }
6370 }
6371 else
6372 {
6373
6374 /* Error, one or more invalid arguments. */
6375
6376 /* Set the socket error if extended socket options enabled. */
6377 nx_bsd_set_errno(EINVAL);
6378
6379 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6380 return NX_SOC_ERROR;
6381 }
6382
6383 /* Normalize the socket ID. */
6384 sockID = sockID - NX_BSD_SOCKFD_START;
6385
6386 /* Get the protection mutex. */
6387 status = (INT)tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
6388
6389 /* Check the status. */
6390 if (status)
6391 {
6392
6393 /* Set the socket error if extended socket options enabled. */
6394 nx_bsd_set_errno(EACCES);
6395
6396 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
6397 return(NX_SOC_ERROR);
6398 }
6399
6400 /* Setup pointer to socket. */
6401 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
6402
6403 status = NX_SOC_OK;
6404 switch (option_name)
6405 {
6406
6407 case SO_ERROR:
6408 {
6409
6410 /* If a valid option pointer was supplied, verify it points to a valid data size. */
6411 if (*option_length < (INT)sizeof(so_errno -> error))
6412 {
6413
6414 tx_mutex_put(nx_bsd_protection_ptr);
6415
6416 /* Set the socket error if extended socket options enabled. */
6417 nx_bsd_set_errno(EINVAL);
6418
6419 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6420 return(NX_SOC_ERROR);
6421 }
6422
6423 so_errno = (struct nx_bsd_sock_errno *)option_value;
6424
6425 TX_DISABLE
6426 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
6427 {
6428 so_errno -> error = bsd_socket_ptr -> nx_bsd_socket_error_code;
6429
6430 /* Now clear the error code. */
6431 bsd_socket_ptr -> nx_bsd_socket_error_code = 0;
6432
6433 /* Clear the error flag. The application is expected to close the socket at this point.*/
6434 bsd_socket_ptr -> nx_bsd_socket_status_flags = bsd_socket_ptr -> nx_bsd_socket_status_flags & (ULONG)(~NX_BSD_SOCKET_ERROR);
6435 }
6436 else
6437 so_errno -> error = 0;
6438 TX_RESTORE
6439
6440 /* Set the actual size of the data returned. */
6441 *option_length = sizeof(struct nx_bsd_sock_errno);
6442
6443 }
6444
6445 break;
6446
6447 case SO_KEEPALIVE:
6448
6449 /* Determine if NetX Duo supports keepalive. */
6450
6451 /* Check to make sure the size arguement is sufficient if supplied. */
6452 if (*option_length < (INT)sizeof(so_keepalive -> keepalive_enabled))
6453 {
6454
6455 tx_mutex_put(nx_bsd_protection_ptr);
6456
6457 /* Set the socket error if extended socket options enabled. */
6458 nx_bsd_set_errno(EINVAL);
6459
6460 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6461 return(NX_SOC_ERROR);
6462 }
6463
6464 so_keepalive = (struct nx_bsd_sock_keepalive *)option_value;
6465 #ifndef NX_ENABLE_TCP_KEEPALIVE
6466 so_keepalive -> keepalive_enabled = NX_FALSE;
6467 #else
6468 so_keepalive -> keepalive_enabled = (INT)(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled);
6469 #endif /* NX_ENABLE_TCP_KEEPALIVE */
6470 *option_length = sizeof(struct nx_bsd_sock_keepalive);
6471
6472 break;
6473
6474 case SO_RCVTIMEO:
6475
6476 /* Check if the receive time out is set. */
6477 if (bsd_socket_ptr -> nx_bsd_option_receive_timeout == 0)
6478 {
6479 tx_mutex_put(nx_bsd_protection_ptr);
6480
6481 /* Set the socket error if extended socket options enabled. */
6482 nx_bsd_set_errno(EINVAL);
6483
6484 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6485 return(NX_SOC_ERROR);
6486
6487 }
6488
6489 so_rcvtimeval = (struct nx_bsd_timeval *)option_value;
6490
6491 ticks = bsd_socket_ptr -> nx_bsd_option_receive_timeout;
6492
6493
6494 so_rcvtimeval -> tv_usec = (nx_bsd_suseconds_t)(ticks * NX_MICROSECOND_PER_CPU_TICK) % 1000000;
6495 so_rcvtimeval -> tv_sec = (nx_bsd_time_t)((ticks * NX_MICROSECOND_PER_CPU_TICK) / 1000000);
6496 *option_length = sizeof(so_rcvtimeval);
6497
6498 break;
6499
6500 case SO_RCVBUF:
6501
6502 soc_window_size = (struct nx_bsd_sock_winsize *)option_value;
6503 soc_window_size -> winsize = (INT)(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_default);
6504 *option_length = sizeof(soc_window_size);
6505
6506 break;
6507
6508 case SO_REUSEADDR:
6509
6510 /* Check to make sure the size arguement is sufficient if supplied. */
6511 if (*option_length < (INT)sizeof(so_reuseaddr -> reuseaddr_enabled))
6512 {
6513
6514 tx_mutex_put(nx_bsd_protection_ptr);
6515
6516 /* Set the socket error if extended socket options enabled. */
6517 nx_bsd_set_errno(EINVAL);
6518
6519 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6520 return(NX_SOC_ERROR);
6521 }
6522
6523 so_reuseaddr= (struct nx_bsd_sock_reuseaddr *)option_value;
6524 so_reuseaddr -> reuseaddr_enabled = bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR;
6525 *option_length = sizeof(struct nx_bsd_sock_reuseaddr);
6526
6527 break;
6528
6529 case IP_MULTICAST_TTL:
6530
6531 /* Validate the option length. */
6532 if(*option_length != sizeof(UCHAR))
6533 {
6534
6535 tx_mutex_put(nx_bsd_protection_ptr);
6536
6537 /* Set the socket error if extended socket options enabled. */
6538 nx_bsd_set_errno(EINVAL);
6539
6540 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6541 return NX_SOC_ERROR;
6542 }
6543
6544 /* Verify that the socket is still valid. */
6545 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
6546 {
6547
6548 tx_mutex_put(nx_bsd_protection_ptr);
6549
6550 /* Set the socket error if extended socket options enabled. */
6551 nx_bsd_set_errno(EBADF);
6552
6553 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6554 return NX_SOC_ERROR;
6555 }
6556
6557 /* Make sure socket is UDP type. */
6558 if(bsd_socket_ptr -> nx_bsd_socket_udp_socket == NX_NULL)
6559 {
6560
6561 tx_mutex_put(nx_bsd_protection_ptr);
6562
6563 /* Set the socket error if extended socket options enabled. */
6564 nx_bsd_set_errno(ENOPROTOOPT);
6565
6566 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6567 return NX_SOC_ERROR;
6568 }
6569
6570 /* Set the TTL value. */
6571 *(UCHAR*)option_value = (UCHAR)(bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_time_to_live);
6572 break;
6573
6574 default:
6575
6576 tx_mutex_put(nx_bsd_protection_ptr);
6577
6578 /* Set the socket error if extended socket options enabled. */
6579 nx_bsd_set_errno(ENOPROTOOPT);
6580
6581 /* Unsupported or unknown option. */
6582 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6583 return(NX_SOC_ERROR);
6584 }
6585
6586 /* Release the protection mutex. */
6587 tx_mutex_put(nx_bsd_protection_ptr);
6588
6589 return status;
6590 }
6591
6592 /**************************************************************************/
6593 /* */
6594 /* FUNCTION RELEASE */
6595 /* */
6596 /* setsockopt PORTABLE C */
6597 /* 6.4.0 */
6598 /* AUTHOR */
6599 /* */
6600 /* Yuxin Zhou, Microsoft Corporation */
6601 /* */
6602 /* DESCRIPTION */
6603 /* */
6604 /* This function enables the specified socket option in the current BSD*/
6605 /* socket session to the specified setting. */
6606 /* */
6607 /* INPUT */
6608 /* */
6609 /* sockID socket descriptor */
6610 /* option_level Category of option (SOCKET) */
6611 /* option_name Socket option ID */
6612 /* option_value Pointer to option value */
6613 /* option_length Size of option value data */
6614 /* */
6615 /* OUTPUT */
6616 /* */
6617 /* NX_SOC_OK Request processed successfully*/
6618 /* NX_SOC_ERROR Errors with request */
6619 /* */
6620 /* CALLS */
6621 /* */
6622 /* tx_mutex_get Get protection */
6623 /* tx_mutex_put Release protection */
6624 /* */
6625 /* CALLED BY */
6626 /* */
6627 /* Application Code */
6628 /* */
6629 /* RELEASE HISTORY */
6630 /* */
6631 /* DATE NAME DESCRIPTION */
6632 /* */
6633 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
6634 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
6635 /* resulting in version 6.1 */
6636 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
6637 /* used new API/structs naming,*/
6638 /* resulting in version 6.3.0 */
6639 /* 12-31-2023 Yanwu Cai Modified comment(s), and */
6640 /* added PACKET_ADD_MEMBERSHIP */
6641 /* and PACKET_DROP_MEMBERSHIP, */
6642 /* resulting in version 6.4.0 */
6643 /* */
6644 /**************************************************************************/
nx_bsd_setsockopt(INT sockID,INT option_level,INT option_name,const VOID * option_value,INT option_length)6645 INT nx_bsd_setsockopt(INT sockID, INT option_level, INT option_name, const VOID *option_value, INT option_length)
6646 {
6647 UINT reuse_enabled;
6648 NX_BSD_SOCKET *bsd_socket_ptr;
6649 ULONG window_size;
6650 ULONG timer_ticks;
6651 struct nx_bsd_timeval *time_val;
6652 #if defined(NX_ENABLE_IP_RAW_PACKET_FILTER) || !defined(NX_DISABLE_IPV4)
6653 INT i;
6654 #endif /* defined(NX_ENABLE_IP_RAW_PACKET_FILTER) || !defined(NX_DISABLE_IPV4) */
6655 #ifndef NX_DISABLE_IPV4
6656 struct nx_bsd_ip_mreq
6657 *mreq;
6658 UINT mcast_interface;
6659 UINT status;
6660 #endif /* NX_DISABLE_IPV4 */
6661 #if defined(NX_BSD_RAW_SUPPORT) && defined(NX_ENABLE_VLAN)
6662 struct nx_bsd_packet_mreq
6663 *pkt_mreq;
6664 ULONG physical_addr_msw;
6665 ULONG physical_addr_lsw;
6666 #endif
6667
6668
6669 /* Check for valid socket ID. */
6670 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
6671 {
6672
6673 /* Error, invalid socket ID. */
6674
6675 /* Set the socket error if extended options enabled. */
6676 nx_bsd_set_errno(EBADF);
6677
6678 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6679 return(NX_SOC_ERROR);
6680 }
6681
6682 /* Check for invalid paremters. */
6683 if((option_value == NX_NULL) || (option_length == 0))
6684 {
6685
6686 /* Error, one or more invalid arguments. */
6687
6688 /* Set the socket error if extended socket options enabled. */
6689 nx_bsd_set_errno(EINVAL);
6690
6691 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6692 return NX_SOC_ERROR;
6693 }
6694
6695 if (option_level == IPPROTO_IP)
6696 {
6697
6698 if((option_name <= SO_MAX) || (option_name > IP_OPTION_MAX))
6699 {
6700
6701 /* Error, one or more invalid arguments. */
6702
6703 /* Set the socket error if extended socket options enabled. */
6704 nx_bsd_set_errno(ENOPROTOOPT);
6705
6706 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6707 return NX_SOC_ERROR;
6708 }
6709 }
6710 else if(option_level == SOL_SOCKET)
6711 {
6712
6713 if((option_name > SO_MAX) ||
6714 (option_name < SO_MIN))
6715 {
6716 /* Error, one or more invalid arguments. */
6717
6718 /* Set the socket error if extended socket options enabled. */
6719 nx_bsd_set_errno(ENOPROTOOPT);
6720
6721 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6722 return NX_SOC_ERROR;
6723 }
6724 }
6725 else if(option_level == SOL_PACKET)
6726 {
6727 if ((option_name > PACKET_OPTION_MAX) ||
6728 (option_name < PACKET_ADD_MEMBERSHIP))
6729 {
6730 /* Error, one or more invalid arguments. */
6731
6732 /* Set the socket error if extended socket options enabled. */
6733 nx_bsd_set_errno(ENOPROTOOPT);
6734
6735 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6736 return NX_SOC_ERROR;
6737 }
6738 }
6739 else if (option_level == IPPROTO_TCP)
6740 {
6741
6742 if ((option_name > TCP_NOOPT) ||
6743 (option_name < TCP_NODELAY))
6744 {
6745 /* Error, one or more invalid arguments. */
6746
6747 /* Set the socket error if extended socket options enabled. */
6748 nx_bsd_set_errno(ENOPROTOOPT);
6749
6750 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6751 return NX_SOC_ERROR;
6752 }
6753 }
6754 else
6755 {
6756 /* Error, one or more invalid arguments. */
6757
6758 /* Set the socket error if extended socket options enabled. */
6759 nx_bsd_set_errno(EINVAL);
6760
6761 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6762 return NX_SOC_ERROR;
6763 }
6764 /* Normalize the socket ID. */
6765 sockID = sockID - NX_BSD_SOCKFD_START;
6766
6767 /* Set up pointer to the BSD socket. */
6768 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
6769
6770 /* Set the socket option status. */
6771 switch (option_name)
6772 {
6773
6774 case SO_BROADCAST:
6775
6776 /* This is the default behavior of NetX. All sockets have this capability. */
6777 break;
6778
6779 case SO_KEEPALIVE:
6780
6781 /* Only available to TCP BSD sockets. */
6782 if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
6783 {
6784
6785 /* Verify TCP keep alive is built into the NetX library or return an error. */
6786 #ifndef NX_ENABLE_TCP_KEEPALIVE
6787
6788 /* Set the socket error if extended socket options enabled. */
6789 nx_bsd_set_errno(ENOPROTOOPT);
6790
6791 /* Return an error status. */
6792 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6793 return NX_SOC_ERROR;
6794 #else
6795 /* Determine if NetX Duo supports keepalive. */
6796
6797 /* Update the BSD socket with this attribute. */
6798 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled =
6799 (UINT)(((struct nx_bsd_sock_keepalive *)option_value) -> keepalive_enabled);
6800
6801 if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled == NX_TRUE)
6802 {
6803
6804 /* Set the keep alive timeout for this socket with the NetX configurable keep alive timeout. */
6805 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_timeout = NX_TCP_KEEPALIVE_INITIAL;
6806 }
6807 else
6808 {
6809
6810 /* Clear the socket keep alive timeout. */
6811 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_timeout = 0;
6812 }
6813 #endif /* NX_ENABLE_TCP_KEEPALIVE */
6814 }
6815 else
6816 {
6817 /* Not a TCP socket. */
6818
6819 /* Set the socket error if extended socket options enabled. */
6820 nx_bsd_set_errno(ENOPROTOOPT);
6821
6822 /* Return an error status. */
6823 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6824 return NX_SOC_ERROR;
6825 }
6826
6827 break;
6828
6829 case SO_LINGER:
6830
6831 /* The Linger socket option is not supported in NetX Duo BSD. */
6832
6833 return NX_NOT_ENABLED;
6834
6835 case SO_SNDTIMEO:
6836
6837 time_val = (struct nx_bsd_timeval *)option_value;
6838
6839 /* Calculate ticks for the ThreadX Timer. */
6840 timer_ticks = (ULONG)(time_val -> tv_usec)/NX_MICROSECOND_PER_CPU_TICK + (ULONG)(time_val -> tv_sec) * NX_IP_PERIODIC_RATE;
6841
6842 bsd_socket_ptr -> nx_bsd_option_send_timeout = timer_ticks;
6843
6844 break;
6845
6846 case SO_RCVTIMEO:
6847
6848 time_val = (struct nx_bsd_timeval *)option_value;
6849
6850 /* Calculate ticks for the ThreadX Timer. */
6851 timer_ticks = (ULONG)(time_val -> tv_usec)/NX_MICROSECOND_PER_CPU_TICK + (ULONG)(time_val -> tv_sec) * NX_IP_PERIODIC_RATE;
6852
6853 bsd_socket_ptr -> nx_bsd_option_receive_timeout = timer_ticks;
6854
6855 break;
6856
6857 case SO_RCVBUF:
6858
6859 /* Only available to TCP sockets. */
6860 if (!bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
6861 {
6862
6863 /* Set the socket error if extended socket options enabled. */
6864 nx_bsd_set_errno(ENOPROTOOPT);
6865
6866 /* Return an error status. */
6867 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6868 return NX_SOC_ERROR;
6869 }
6870
6871
6872 window_size = (ULONG)(((struct nx_bsd_sock_winsize *)option_value) -> winsize);
6873
6874 #ifdef NX_ENABLE_TCP_WINDOW_SCALING
6875
6876
6877 /* If Window scaling feature is enabled, record this user-specified window size. */
6878 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_maximum = window_size;
6879 #else
6880 /* Otherwise the windows size limit is applied. */
6881 if(window_size > 65535)
6882 window_size = 65535;
6883
6884 #endif /* NX_ENABLE_TCP_WINDOW_SCALING */
6885
6886 /* Setup the sliding window information. */
6887 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_default = window_size;
6888 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_current = window_size;
6889
6890 break;
6891
6892 case SO_REUSEADDR:
6893
6894 reuse_enabled = (UINT)(((struct nx_bsd_sock_reuseaddr *)option_value) -> reuseaddr_enabled);
6895
6896 if(reuse_enabled)
6897 bsd_socket_ptr -> nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR;
6898 else
6899 bsd_socket_ptr -> nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR);
6900
6901 break;
6902
6903
6904 case TCP_NODELAY:
6905
6906 /* This is the default behavior of NetX. All sockets have this attribute. */
6907
6908 break;
6909
6910 case IP_MULTICAST_TTL:
6911
6912 /* Validate the option length. */
6913 if(option_length != sizeof(UCHAR) && option_length != sizeof(INT))
6914 {
6915
6916 /* Set the socket error if extended socket options enabled. */
6917 nx_bsd_set_errno(EINVAL);
6918
6919 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6920 return NX_SOC_ERROR;
6921 }
6922
6923 /* Verify that the socket is still valid. */
6924 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
6925 {
6926
6927 /* Set the socket error if extended socket options enabled. */
6928 nx_bsd_set_errno(EBADF);
6929
6930 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6931 return NX_SOC_ERROR;
6932 }
6933
6934 /* Make sure socket is UDP type. */
6935 if(bsd_socket_ptr -> nx_bsd_socket_udp_socket == NX_NULL)
6936 {
6937 /* Set the socket error if extended socket options enabled. */
6938 nx_bsd_set_errno(ENOPROTOOPT);
6939
6940 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6941 return NX_SOC_ERROR;
6942 }
6943
6944 /* Set the TTL value. */
6945 if (option_length == sizeof(UCHAR))
6946 {
6947 bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_time_to_live = *(UCHAR*)option_value;
6948 }
6949 else
6950 {
6951 bsd_socket_ptr -> nx_bsd_socket_udp_socket -> nx_udp_socket_time_to_live = (UCHAR)(*(INT*)option_value);
6952 }
6953 break;
6954
6955 case IP_MULTICAST_LOOP:
6956
6957 /* This is not supported yet. */
6958
6959 break;
6960
6961 case IP_MULTICAST_IF:
6962
6963 /* This is not supported yet. */
6964
6965 break;
6966 #if defined(NX_BSD_RAW_SUPPORT) && defined(NX_ENABLE_VLAN)
6967
6968 case PACKET_ADD_MEMBERSHIP:
6969 case PACKET_DROP_MEMBERSHIP:
6970
6971 /* Validate the option length */
6972 if (option_length != sizeof(struct nx_bsd_packet_mreq))
6973 {
6974
6975 /* Set the socket error if extended socket options enabled. */
6976 nx_bsd_set_errno(EINVAL);
6977
6978 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6979 return NX_SOC_ERROR;
6980 }
6981
6982 pkt_mreq = (struct nx_bsd_packet_mreq*)option_value;
6983
6984 if (pkt_mreq -> mr_alen != ETH_ALEN || pkt_mreq -> mr_type != PACKET_MR_MULTICAST)
6985 {
6986
6987 /* Set the socket error if extended socket options enabled. */
6988 nx_bsd_set_errno(EINVAL);
6989
6990 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
6991 return NX_SOC_ERROR;
6992 }
6993
6994 /* Verify that the socket is still valid. */
6995 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
6996 {
6997 /* Set the socket error if extended socket options enabled. */
6998 nx_bsd_set_errno(EBADF);
6999
7000 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7001 return NX_SOC_ERROR;
7002 }
7003
7004 physical_addr_msw = (pkt_mreq -> mr_address[0] << 8) | pkt_mreq->mr_address[1];
7005 physical_addr_lsw = (pkt_mreq -> mr_address[2] << 24) | (pkt_mreq->mr_address[3] << 16) |
7006 (pkt_mreq -> mr_address[4] << 8) | pkt_mreq -> mr_address[5];
7007
7008 if (option_name == PACKET_ADD_MEMBERSHIP)
7009 {
7010 status = nx_link_multicast_join(nx_bsd_default_ip, pkt_mreq -> mr_ifindex,
7011 physical_addr_msw, physical_addr_lsw);
7012 }
7013 else
7014 {
7015 status = nx_link_multicast_leave(nx_bsd_default_ip, pkt_mreq -> mr_ifindex,
7016 physical_addr_msw, physical_addr_lsw);
7017 }
7018
7019 if (status != NX_SUCCESS)
7020 {
7021
7022 nx_bsd_set_errno(EINVAL);
7023
7024 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7025 return NX_SOC_ERROR;
7026 }
7027
7028 break;
7029 #endif
7030
7031 case IP_RAW_RX_NO_HEADER:
7032
7033 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
7034 i = *(INT*)option_value;
7035
7036 if((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET) &&
7037 ((bsd_socket_ptr -> nx_bsd_socket_family == AF_INET) || (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)))
7038 {
7039
7040 if(i)
7041 {
7042
7043 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_RX_NO_HDR;
7044 }
7045 else
7046 {
7047
7048 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_RX_NO_HDR);
7049 }
7050 }
7051 else
7052 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
7053 {
7054
7055 nx_bsd_set_errno(EINVAL);
7056
7057 /* Return an error status. */
7058 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7059
7060 return NX_SOC_ERROR;
7061 }
7062 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
7063 break;
7064 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
7065
7066 case IP_RAW_IPV6_HDRINCL:
7067
7068 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
7069 i = *(INT*)option_value;
7070
7071 /* Is this an IPv6 socket? */
7072 if((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET) &&
7073 (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6))
7074 {
7075
7076 /* Should the No Header feature be enabled (NX_TRUE)? */
7077 if(i)
7078 {
7079
7080 /* Yes, set the flag for no header. */
7081 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_TX_HDR_INCLUDE;
7082 }
7083 else
7084 {
7085
7086 /* No, clear the flag for no header. */
7087 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_TX_HDR_INCLUDE);
7088 }
7089 }
7090 else
7091 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
7092 {
7093
7094 nx_bsd_set_errno(EINVAL);
7095
7096 /* Return an error status. */
7097 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7098
7099 return NX_SOC_ERROR;
7100 }
7101 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
7102 break;
7103 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
7104
7105
7106 #ifndef NX_DISABLE_IPV4
7107 case IP_ADD_MEMBERSHIP:
7108 case IP_DROP_MEMBERSHIP:
7109
7110 /* Validate the option length */
7111 if(option_length != sizeof(struct nx_bsd_ip_mreq))
7112 {
7113
7114 /* Set the socket error if extended socket options enabled. */
7115 nx_bsd_set_errno(EINVAL);
7116
7117 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7118 return NX_SOC_ERROR;
7119 }
7120
7121 mreq = (struct nx_bsd_ip_mreq*)option_value;
7122
7123 /* Make sure the multicast group address is valid. */
7124 if((mreq -> imr_multiaddr.s_addr & ntohl(NX_IP_CLASS_D_TYPE)) != ntohl(NX_IP_CLASS_D_TYPE))
7125 {
7126 /* Set the socket error if extended socket options enabled. */
7127 nx_bsd_set_errno(EINVAL);
7128
7129 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7130 return NX_SOC_ERROR;
7131 }
7132
7133 /* Verify that the socket is still valid. */
7134 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
7135 {
7136 /* Set the socket error if extended socket options enabled. */
7137 nx_bsd_set_errno(EBADF);
7138
7139 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7140 return NX_SOC_ERROR;
7141 }
7142
7143 /* Make sure socket is UDP type. */
7144 if(bsd_socket_ptr -> nx_bsd_socket_udp_socket == NX_NULL)
7145 {
7146 /* Set the socket error if extended socket options enabled. */
7147 nx_bsd_set_errno(ENOPROTOOPT);
7148
7149 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7150 return NX_SOC_ERROR;
7151 }
7152
7153 /* Validate that the interface is one of the local IPv4 interfaces. */
7154 /* We allow imr_interface being zero to indicate the primary interface. */
7155 mcast_interface = NX_MAX_IP_INTERFACES;
7156
7157 if(mreq -> imr_interface.s_addr == INADDR_ANY)
7158 {
7159 mcast_interface = 0;
7160 }
7161 else
7162 {
7163
7164 /* Set the socket error if extended socket options enabled. */
7165 UINT addr;
7166
7167 /* Convert the local interface value to host byte order. */
7168 addr = ntohl(mreq -> imr_interface.s_addr);
7169
7170 /* Search through the interface table for a matching one. */
7171 for(i = 0; i < NX_MAX_IP_INTERFACES; i++)
7172 {
7173
7174 if(addr == nx_bsd_default_ip -> nx_ip_interface[i].nx_interface_ip_address)
7175 {
7176
7177 mcast_interface = (UINT)i;
7178 break;
7179 }
7180 }
7181 }
7182
7183 if(mcast_interface == NX_MAX_IP_INTERFACES)
7184 {
7185
7186 /* Did not find a matching interface. */
7187 nx_bsd_set_errno(EINVAL);
7188
7189 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7190 return NX_SOC_ERROR;
7191 }
7192
7193 if(option_name == IP_ADD_MEMBERSHIP)
7194 {
7195
7196 /* Make sure the IGMP feature is enabled. */
7197 if(nx_bsd_default_ip -> nx_ip_igmp_packet_receive == NX_NULL)
7198 {
7199 nx_igmp_enable(nx_bsd_default_ip);
7200 }
7201
7202 /* Join the group. */
7203 status = nx_igmp_multicast_interface_join(nx_bsd_default_ip, ntohl(mreq -> imr_multiaddr.s_addr), mcast_interface);
7204 }
7205 else
7206 {
7207
7208 /* Leave group */
7209 status = nx_igmp_multicast_leave(nx_bsd_default_ip, ntohl(mreq -> imr_multiaddr.s_addr));
7210 }
7211
7212 if(status != NX_SUCCESS)
7213 {
7214
7215 nx_bsd_set_errno(EINVAL);
7216
7217 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7218 return NX_SOC_ERROR;
7219 }
7220
7221 break;
7222 #endif /* NX_DISABLE_IPV4 */
7223
7224 case IP_HDRINCL:
7225
7226 #if defined(NX_ENABLE_IP_RAW_PACKET_FILTER) && !defined(NX_DISABLE_IPV4)
7227 i = *(INT*)option_value;
7228 /* First verify that raw socket processing is enabled on the IP instance and that this is
7229 an IPv4 thread. */
7230 if((bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET) &&
7231 (bsd_socket_ptr -> nx_bsd_socket_family == AF_INET))
7232 {
7233
7234 /* Is the option being enabled (NX_TRUE)? */
7235 if(i)
7236 {
7237
7238 /* Yes, set the flag bit indicating BSD will append the IP header. */
7239 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_TX_HDR_INCLUDE;
7240 }
7241 else
7242 {
7243
7244 /* No, clear the flag bit indicating IP task will append the IP header. */
7245 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_TX_HDR_INCLUDE);
7246 }
7247 }
7248 else
7249 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
7250 {
7251
7252 nx_bsd_set_errno(EINVAL);
7253
7254 /* Return an error status. */
7255 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7256
7257 return NX_SOC_ERROR;
7258 }
7259
7260 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
7261 break;
7262 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
7263
7264 default:
7265
7266 /* Set the socket error if extended socket options enabled. */
7267 nx_bsd_set_errno(EINVAL);
7268
7269 /* Return an error status. */
7270 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7271 return NX_SOC_ERROR;
7272 }
7273
7274 /* Socket option successfully updated. */
7275 return NX_SUCCESS;
7276 }
7277
7278
7279 /**************************************************************************/
7280 /* */
7281 /* FUNCTION RELEASE */
7282 /* */
7283 /* getsockname PORTABLE C */
7284 /* 6.3.0 */
7285 /* AUTHOR */
7286 /* */
7287 /* Yuxin Zhou, Microsoft Corporation */
7288 /* */
7289 /* DESCRIPTION */
7290 /* */
7291 /* This function returns the socket's primary interface address and */
7292 /* port. For NetX Duo environments, it returns the address at address */
7293 /* index 1 into the IP address table; this is where the primary */
7294 /* interface global IP address is normally located. */
7295 /* */
7296 /* INPUT */
7297 /* */
7298 /* sockID socket descriptor */
7299 /* localAddress sockaddr struct to return */
7300 /* the local address */
7301 /* addressLength Number of bytes in sockAddr */
7302 /* */
7303 /* OUTPUT */
7304 /* */
7305 /* NX_SOC_OK (0) On success */
7306 /* NX_SOC_ERROR (-1) On failure */
7307 /* */
7308 /* CALLS */
7309 /* */
7310 /* tx_mutex_get Get protection */
7311 /* tx_mutex_put Release protection */
7312 /* */
7313 /* CALLED BY */
7314 /* */
7315 /* Application Code */
7316 /* */
7317 /* RELEASE HISTORY */
7318 /* */
7319 /* DATE NAME DESCRIPTION */
7320 /* */
7321 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7322 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
7323 /* verified memcpy use cases, */
7324 /* resulting in version 6.1 */
7325 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
7326 /* used new API/structs naming,*/
7327 /* resulting in version 6.3.0 */
7328 /* */
7329 /**************************************************************************/
nx_bsd_getsockname(INT sockID,struct nx_bsd_sockaddr * localAddress,INT * addressLength)7330 INT nx_bsd_getsockname(INT sockID, struct nx_bsd_sockaddr *localAddress, INT *addressLength)
7331 {
7332
7333 #ifndef NX_DISABLE_IPV4
7334 struct nx_bsd_sockaddr_in soc_struct;
7335 #endif /* NX_DISABLE_IPV4 */
7336 #ifdef FEATURE_NX_IPV6
7337 struct nx_bsd_sockaddr_in6 soc6_struct;
7338 #endif
7339 UINT status;
7340 NX_BSD_SOCKET *bsd_socket_ptr;
7341
7342
7343 /* Check whether supplied socket ID is valid. */
7344 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
7345 {
7346
7347 /* Set the socket error if extended options enabled. */
7348 nx_bsd_set_errno(EBADF);
7349
7350 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7351 return(NX_SOC_ERROR);
7352 }
7353
7354 if((localAddress == NX_NULL) || (addressLength == NX_NULL) || (*addressLength == 0))
7355 {
7356
7357 /* Set the socket error if extended socket options enabled. */
7358 nx_bsd_set_errno(EINVAL);
7359
7360 /* Return error. */
7361 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7362 return(NX_SOC_ERROR);
7363 }
7364
7365 /* Normalize the socket ID. */
7366 sockID = sockID - NX_BSD_SOCKFD_START;
7367
7368 /* Setup pointer to socket. */
7369 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
7370
7371 /* Get the protection mutex. */
7372 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
7373
7374 /* Check the status. */
7375 if (status)
7376 {
7377
7378 /* Set the socket error if extended socket options enabled. */
7379 nx_bsd_set_errno(EACCES);
7380
7381 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
7382 return(NX_SOC_ERROR);
7383 }
7384
7385 /* Is the socket still in use? */
7386 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
7387 {
7388
7389 /* Set the socket error if extended options enabled. */
7390 nx_bsd_set_errno(EBADF);
7391 /* Release the protection mutex. */
7392 tx_mutex_put(nx_bsd_protection_ptr);
7393
7394 /* Return error. */
7395 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7396 return(NX_SOC_ERROR);
7397 }
7398
7399 if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND))
7400 {
7401 /* This socket is not bound yet. Just return.
7402 According to the spec, if the socket is not bound, the value stored in
7403 localAddress is unspecified. */
7404 /* Release the protection mutex. */
7405 tx_mutex_put(nx_bsd_protection_ptr);
7406
7407 /* Success! */
7408 return(NX_SOC_OK);
7409 }
7410
7411 #ifndef NX_DISABLE_IPV4
7412 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
7413 {
7414 if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
7415 {
7416 soc_struct.sin_addr.s_addr = INADDR_ANY;
7417 }
7418 else if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == 0)
7419 {
7420
7421 nx_bsd_set_errno(EINVAL);
7422
7423 /* Release the protection mutex. */
7424 tx_mutex_put(nx_bsd_protection_ptr);
7425
7426 /* Return error. */
7427 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7428 return(NX_SOC_ERROR);
7429 }
7430 else
7431 {
7432 NX_INTERFACE* local_if = (NX_INTERFACE*)(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface);
7433 soc_struct.sin_addr.s_addr = htonl(local_if -> nx_interface_ip_address);
7434 }
7435 soc_struct.sin_port = htons((USHORT)bsd_socket_ptr -> nx_bsd_socket_local_port);
7436
7437 soc_struct.sin_family = AF_INET;
7438
7439 if((*addressLength) > (INT)sizeof(struct nx_bsd_sockaddr_in))
7440 {
7441 *addressLength = sizeof(struct nx_bsd_sockaddr_in);
7442 }
7443 memcpy(localAddress, &soc_struct, (UINT)(*addressLength)); /* Use case of memcpy is verified. */
7444 }
7445 else
7446 #endif /* NX_DISABLE_IPV4 */
7447 #ifdef FEATURE_NX_IPV6
7448 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
7449 {
7450
7451
7452 if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
7453 {
7454 soc6_struct.sin6_addr._S6_un._S6_u32[0] = 0;
7455 soc6_struct.sin6_addr._S6_un._S6_u32[1] = 0;
7456 soc6_struct.sin6_addr._S6_un._S6_u32[2] = 0;
7457 soc6_struct.sin6_addr._S6_un._S6_u32[3] = 0;
7458 }
7459 else if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == 0)
7460 {
7461
7462 nx_bsd_set_errno(EINVAL);
7463
7464 /* Release the protection mutex. */
7465 tx_mutex_put(nx_bsd_protection_ptr);
7466
7467 /* Return error. */
7468 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7469 return(NX_SOC_ERROR);
7470 }
7471 else
7472 {
7473 NXD_IPV6_ADDRESS* local_v6if = (NXD_IPV6_ADDRESS*)(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface);
7474
7475 soc6_struct.sin6_addr._S6_un._S6_u32[0] = htonl(local_v6if -> nxd_ipv6_address[0]);
7476 soc6_struct.sin6_addr._S6_un._S6_u32[1] = htonl(local_v6if -> nxd_ipv6_address[1]);
7477 soc6_struct.sin6_addr._S6_un._S6_u32[2] = htonl(local_v6if -> nxd_ipv6_address[2]);
7478 soc6_struct.sin6_addr._S6_un._S6_u32[3] = htonl(local_v6if -> nxd_ipv6_address[3]);
7479 }
7480
7481 soc6_struct.sin6_port = htons((USHORT)bsd_socket_ptr -> nx_bsd_socket_local_port);
7482
7483 soc6_struct.sin6_family = AF_INET6;
7484
7485 if((*addressLength) > (INT)sizeof(struct nx_bsd_sockaddr_in6))
7486 {
7487 *addressLength = sizeof(struct nx_bsd_sockaddr_in6);
7488 }
7489 memcpy(localAddress, &soc6_struct, (UINT)(*addressLength)); /* Use case of memcpy is verified. */
7490
7491 }
7492 else
7493 #endif /* FEATURE_NX_IPV6 */
7494 {
7495
7496 /* Release the protection mutex. */
7497 tx_mutex_put(nx_bsd_protection_ptr);
7498
7499 nx_bsd_set_errno(EPROTONOSUPPORT);
7500
7501 /* Return error. */
7502 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7503 return(NX_SOC_ERROR);
7504 }
7505
7506
7507
7508 /* Release the protection mutex. */
7509 tx_mutex_put(nx_bsd_protection_ptr);
7510
7511 /* Success! */
7512 return(NX_SOC_OK);
7513 }
7514
7515
7516 /**************************************************************************/
7517 /* */
7518 /* FUNCTION RELEASE */
7519 /* */
7520 /* getpeername PORTABLE C */
7521 /* 6.3.0 */
7522 /* AUTHOR */
7523 /* */
7524 /* Yuxin Zhou, Microsoft Corporation */
7525 /* */
7526 /* DESCRIPTION */
7527 /* */
7528 /* This function returns the socket's remote address and port. */
7529 /* */
7530 /* INPUT */
7531 /* */
7532 /* sockID socket descriptor */
7533 /* localAddress sockaddr struct to return */
7534 /* the remote address */
7535 /* addressLength Number of bytes in sockAddr */
7536 /* */
7537 /* OUTPUT */
7538 /* */
7539 /* NX_SOC_OK (0) On success */
7540 /* NX_SOC_ERROR (-1) On failure */
7541 /* */
7542 /* CALLS */
7543 /* */
7544 /* tx_mutex_get Get protection */
7545 /* tx_mutex_put Release protection */
7546 /* */
7547 /* CALLED BY */
7548 /* */
7549 /* Application Code */
7550 /* */
7551 /* RELEASE HISTORY */
7552 /* */
7553 /* DATE NAME DESCRIPTION */
7554 /* */
7555 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7556 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7557 /* resulting in version 6.1 */
7558 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
7559 /* used new API/structs naming,*/
7560 /* resulting in version 6.3.0 */
7561 /* */
7562 /**************************************************************************/
nx_bsd_getpeername(INT sockID,struct nx_bsd_sockaddr * remoteAddress,INT * addressLength)7563 INT nx_bsd_getpeername(INT sockID, struct nx_bsd_sockaddr *remoteAddress, INT *addressLength)
7564 {
7565
7566 UINT status;
7567 NX_BSD_SOCKET *bsd_socket_ptr;
7568 #ifndef NX_DISABLE_IPV4
7569 struct nx_bsd_sockaddr_in *soc_struct_ptr = NX_NULL;
7570 #endif /* NX_DISABLE_IPV4 */
7571 #ifdef FEATURE_NX_IPV6
7572 struct nx_bsd_sockaddr_in6 *soc6_struct_ptr = NX_NULL;
7573 #endif
7574
7575
7576 /* Check whether supplied socket ID is valid. */
7577 if ((sockID < NX_BSD_SOCKFD_START) || (sockID >= (NX_BSD_SOCKFD_START + NX_BSD_MAX_SOCKETS)))
7578 {
7579
7580 /* Set the socket error if extended socket options enabled. */
7581 nx_bsd_set_errno(EINVAL);
7582
7583 /* Error, invalid socket ID. */
7584 NX_BSD_ERROR(ERROR, __LINE__);
7585 return(ERROR);
7586 }
7587
7588 /* Normalize the socket ID. */
7589 sockID = sockID - NX_BSD_SOCKFD_START;
7590
7591 /* Check the remote address and length pointers. */
7592 if((remoteAddress == NX_NULL) ||(addressLength == NX_NULL))
7593 {
7594
7595 /* Set the socket error if extended socket options enabled. */
7596 nx_bsd_set_errno(EINVAL);
7597
7598 /* Return error. */
7599 NX_BSD_ERROR(ERROR, __LINE__);
7600 return(ERROR);
7601 }
7602
7603
7604 /* Get the protection mutex. */
7605 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
7606
7607 /* Check the status. */
7608 if (status)
7609 {
7610
7611 /* Set the socket error if extended socket options enabled. */
7612 nx_bsd_set_errno(EACCES);
7613
7614 /* Error getting the protection mutex. */
7615 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
7616 return(ERROR);
7617 }
7618
7619 /* Setup pointer to socket. */
7620 bsd_socket_ptr = &nx_bsd_socket_array[sockID];
7621
7622 #ifndef NX_DISABLE_IPV4
7623 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
7624 {
7625
7626 /* This is an IPv4 only socket. */
7627
7628 /* Now validate the size of remoteAddress structure. */
7629 if(*addressLength < (INT)sizeof(struct nx_bsd_sockaddr_in))
7630 {
7631
7632 /* User supplied buffer is too small .*/
7633
7634 /* Release the protection mutex. */
7635 tx_mutex_put(nx_bsd_protection_ptr);
7636
7637 /* Set the socket error, if socket enabled with extended BSD features. */
7638 nx_bsd_set_errno(ESOCKTNOSUPPORT);
7639
7640 /* Return error. */
7641 NX_BSD_ERROR(ERROR, __LINE__);
7642 return(ERROR);
7643 }
7644
7645 soc_struct_ptr = (struct nx_bsd_sockaddr_in*)remoteAddress;
7646 *addressLength = sizeof(struct nx_bsd_sockaddr_in);
7647 }
7648 else
7649 #endif /* NX_DISABLE_IPV4 */
7650 #ifdef FEATURE_NX_IPV6
7651 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
7652 {
7653
7654 /* IPv6 socket */
7655
7656 /* Now validate the size of remoteAddress structure. */
7657 if(*addressLength < (INT)sizeof(struct nx_bsd_sockaddr_in6))
7658 {
7659
7660 /* User supplied buffer is too small .*/
7661
7662 /* Release the protection mutex. */
7663 tx_mutex_put(nx_bsd_protection_ptr);
7664
7665 /* Set the socket error, if socket enabled with extended BSD features. */
7666 nx_bsd_set_errno(ESOCKTNOSUPPORT);
7667
7668 /* Return error. */
7669 NX_BSD_ERROR(ERROR, __LINE__);
7670 return(ERROR);
7671 }
7672
7673 soc6_struct_ptr = (struct nx_bsd_sockaddr_in6*)remoteAddress;
7674 *addressLength = sizeof(struct nx_bsd_sockaddr_in6);
7675 }
7676 else
7677 #endif /* FEATURE_NX_IPV6 */
7678 {
7679
7680 /* Not a valid address family. */
7681 /* Release the protection mutex. */
7682 tx_mutex_put(nx_bsd_protection_ptr);
7683
7684 /* Set the socket error, if socket enabled with extended BSD features. */
7685 nx_bsd_set_errno(ESOCKTNOSUPPORT);
7686
7687 /* Return error. */
7688 NX_BSD_ERROR(ERROR, __LINE__);
7689 return(ERROR);
7690 }
7691
7692 /* Is the socket still in use? */
7693 if (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
7694 {
7695
7696 /* Error, socket not in use anymore. */
7697
7698 /* Release the protection mutex. */
7699 tx_mutex_put(nx_bsd_protection_ptr);
7700
7701 /* Set the socket error if extended options enabled. */
7702 nx_bsd_set_errno(EBADF);
7703
7704 /* Return error. */
7705 NX_BSD_ERROR(ERROR, __LINE__);
7706 return(ERROR);
7707 }
7708
7709 /* Check whether TCP or UDP */
7710 if (bsd_socket_ptr -> nx_bsd_socket_tcp_socket)
7711 {
7712
7713 #ifndef NX_DISABLE_IPV4
7714 /* TCP Socket. Determine socket family type. */
7715 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
7716 {
7717
7718 soc_struct_ptr -> sin_family = AF_INET;
7719 soc_struct_ptr -> sin_port = htons((USHORT)bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_port);
7720 soc_struct_ptr -> sin_addr.s_addr = htonl(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v4);
7721 }
7722 else
7723 #endif /* NX_DISABLE_IPV4 */
7724 #ifdef FEATURE_NX_IPV6
7725 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
7726 {
7727
7728 soc6_struct_ptr -> sin6_family = AF_INET6;
7729 soc6_struct_ptr -> sin6_port = htons((USHORT)bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_port);
7730 soc6_struct_ptr -> sin6_addr._S6_un._S6_u32[0] = htonl(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[0]);
7731 soc6_struct_ptr -> sin6_addr._S6_un._S6_u32[1] = htonl(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[1]);
7732 soc6_struct_ptr -> sin6_addr._S6_un._S6_u32[2] = htonl(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[2]);
7733 soc6_struct_ptr -> sin6_addr._S6_un._S6_u32[3] = htonl(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_connect_ip.nxd_ip_address.v6[3]);
7734 }
7735 else
7736 #endif /* FEATURE_NX_IPV6 */
7737 {
7738
7739 /* Release the protection mutex. */
7740 tx_mutex_put(nx_bsd_protection_ptr);
7741
7742 /* Set the socket error if extended options enabled. */
7743 nx_bsd_set_errno(EBADF);
7744
7745 /* Return error. */
7746 NX_BSD_ERROR(ERROR, __LINE__);
7747 return(ERROR);
7748
7749 }
7750 }
7751 else if (bsd_socket_ptr -> nx_bsd_socket_udp_socket)
7752 {
7753
7754 #ifndef NX_DISABLE_IPV4
7755 /* UDP Socket. Get Peer Name doesn't apply to UDP sockets. Only fill in AF family information.*/
7756 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET)
7757 {
7758 soc_struct_ptr -> sin_family = AF_INET;
7759 soc_struct_ptr -> sin_port = 0;
7760 soc_struct_ptr -> sin_addr.s_addr = 0;
7761 }
7762 else
7763 #endif /* NX_DISABLE_IPV4 */
7764 #ifdef FEATURE_NX_IPV6
7765 if(bsd_socket_ptr -> nx_bsd_socket_family == AF_INET6)
7766 {
7767 soc6_struct_ptr -> sin6_family = AF_INET6;
7768 soc6_struct_ptr -> sin6_port = 0;
7769 }
7770 else
7771 #endif /* FEATURE_NX_IPV6 */
7772 {
7773
7774 /* Release the protection mutex. */
7775 tx_mutex_put(nx_bsd_protection_ptr);
7776
7777 /* Set the socket error, if socket enabled with extended BSD features. */
7778 nx_bsd_set_errno(ESOCKTNOSUPPORT);
7779
7780 /* Return error. */
7781 NX_BSD_ERROR(ERROR, __LINE__);
7782 return(ERROR);
7783
7784 }
7785 }
7786 else
7787 {
7788
7789 /* Release the protection mutex. */
7790 tx_mutex_put(nx_bsd_protection_ptr);
7791
7792 /* Set the socket error, if socket enabled with extended BSD features. */
7793 nx_bsd_set_errno(ESOCKTNOSUPPORT);
7794
7795 /* Return error. */
7796 NX_BSD_ERROR(ERROR, __LINE__);
7797 return(ERROR);
7798 }
7799
7800
7801 /* Release the protection mutex. */
7802 tx_mutex_put(nx_bsd_protection_ptr);
7803
7804 /* Success! */
7805 return(NX_SOC_OK);
7806 }
7807
7808 /**************************************************************************/
7809 /* */
7810 /* FUNCTION RELEASE */
7811 /* */
7812 /* select PORTABLE C */
7813 /* 6.3.0 */
7814 /* AUTHOR */
7815 /* */
7816 /* Yuxin Zhou, Microsoft Corporation */
7817 /* */
7818 /* DESCRIPTION */
7819 /* */
7820 /* This function allows for sockets to be checked for incoming packets.*/
7821 /* nfds should be one greater than value of the largest valued socket */
7822 /* descriptor in any of the lists. If you don't wish to calculate this,*/
7823 /* use FD_SETSIZE instead.For small numbers of sockets,select() will be*/
7824 /* less efficient if FD_SETSIZE is passed.If the bit corresponding to */
7825 /* a socket in an fd_set is set,that socket will be checked for the */
7826 /* condition the fd_set corresponds to.If the condition they are */
7827 /* checked for is true, they will still be set to true when select() */
7828 /* returns (otherwise they will be set to false). */
7829 /* Note that the sets are modified by select():thus they must be reset */
7830 /* between each call to the function. */
7831 /* */
7832 /* fd_sets can be manipulated using the following macros or functions: */
7833 /* */
7834 /* FD_SET(fd, fdset) Sets socket fd in fdset to true. */
7835 /* FD_CLR(fd, fdset) Sets socket fd in fdset to false. */
7836 /* FD_ISSET(fd, fdset)Returns true if socket fd is set to true in fdset*/
7837 /* FD_ZERO(fdset) Sets all the sockets in fdset to false. */
7838 /* */
7839 /* If the input timeout is NULL, select() blocks until one of the */
7840 /* sockets receives a packet. If the timeout is non-NULL, select waits */
7841 /* for the specified time and returns regardless if any socket has */
7842 /* received a packet. Otherwise as soon as a socket receives a packet */
7843 /* this function will return immediately. */
7844 /* */
7845 /* To use select() in non-blocking mode call it with a non-null timeout*/
7846 /* input but set tv_sec and tv_usec to zero, in Unix fashion. */
7847 /* */
7848 /* select() returns the number of sockets for which the specified */
7849 /* conditions are true. If it encounters an error, it will return -1. */
7850 /* */
7851 /* NOTE: ****** When select returns NX_SOC_ERROR it won't update */
7852 /* the readfds descriptor. */
7853 /* */
7854 /* INPUT */
7855 /* */
7856 /* nfds Maximum socket descriptor # */
7857 /* fd_set *readFDs List of read ready sockets */
7858 /* fd_set *writeFDs List of write ready sockets */
7859 /* fd_set *exceptFDs List of exceptions */
7860 /* struct timeval *timeOut */
7861 /* */
7862 /* OUTPUT */
7863 /* */
7864 /* NX_SUCCESS No descriptors read */
7865 /* (successful completion) */
7866 /* status Number of descriptors read */
7867 /* (< 0 if error occurred) */
7868 /* */
7869 /* CALLS */
7870 /* */
7871 /* FD_ZERO Clear a socket ready list */
7872 /* FD_ISSET Check a socket is ready */
7873 /* FD_SET Set a socket to check */
7874 /* nx_tcp_socket_receive Receive TCP packet */
7875 /* nx_udp_source_extract Extract source IP and port */
7876 /* tx_event_flags_get Get events */
7877 /* tx_mutex_get Get protection */
7878 /* tx_mutex_put Release protection */
7879 /* tx_thread_identify Get current thread pointer */
7880 /* tx_thread_preemption_change Disable/restore preemption */
7881 /* */
7882 /* CALLED BY */
7883 /* */
7884 /* Application Code */
7885 /* */
7886 /* RELEASE HISTORY */
7887 /* */
7888 /* DATE NAME DESCRIPTION */
7889 /* */
7890 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
7891 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
7892 /* resulting in version 6.1 */
7893 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
7894 /* used new API/structs naming,*/
7895 /* resulting in version 6.3.0 */
7896 /* */
7897 /**************************************************************************/
nx_bsd_select(INT nfds,nx_bsd_fd_set * readfds,nx_bsd_fd_set * writefds,nx_bsd_fd_set * exceptfds,struct nx_bsd_timeval * timeout)7898 INT nx_bsd_select(INT nfds, nx_bsd_fd_set *readfds, nx_bsd_fd_set *writefds, nx_bsd_fd_set *exceptfds, struct nx_bsd_timeval *timeout)
7899 {
7900
7901 INT i;
7902 UINT status;
7903 NX_BSD_SOCKET_SUSPEND suspend_request;
7904 NX_PACKET *packet_ptr;
7905 nx_bsd_fd_set readfds_found;
7906 nx_bsd_fd_set writefds_found;
7907 nx_bsd_fd_set exceptfds_found;
7908 INT readfds_left;
7909 INT writefds_left;
7910 INT exceptfds_left;
7911 ULONG ticks;
7912 UINT original_threshold;
7913 TX_THREAD *current_thread_ptr;
7914 INT ret;
7915
7916
7917 /* Check for valid input parameters. */
7918 if ((readfds == NX_NULL) && (writefds == NX_NULL) && (exceptfds == NX_NULL) && (timeout == NX_NULL))
7919 {
7920
7921 /* Set the socket error if extended socket options enabled. */
7922 nx_bsd_set_errno(EINVAL);
7923
7924 /* Return an error. */
7925 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7926 return(NX_SOC_ERROR);
7927 }
7928
7929 /* Check the maximum number of file descriptors. */
7930 if((nfds < (NX_BSD_SOCKFD_START + 1)) || (nfds >= (NX_BSD_MAX_SOCKETS + NX_BSD_SOCKFD_START + 1)))
7931 {
7932
7933 /* Set the socket error */
7934 nx_bsd_set_errno(EBADF);
7935
7936 /* Return an error. */
7937 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
7938 return(NX_SOC_ERROR);
7939 }
7940
7941 /* Clear the read and the write selector set. */
7942 NX_BSD_FD_ZERO(&readfds_found);
7943 NX_BSD_FD_ZERO(&writefds_found);
7944 NX_BSD_FD_ZERO(&exceptfds_found);
7945
7946 if(readfds)
7947 readfds_left = readfds -> fd_count;
7948 else
7949 readfds_left = 0;
7950
7951 if(writefds)
7952 {
7953
7954 writefds_left = writefds -> fd_count;
7955 }
7956 else
7957 {
7958
7959 writefds_left = 0;
7960 }
7961
7962 if(exceptfds)
7963 {
7964
7965 exceptfds_left = exceptfds -> fd_count;
7966 }
7967 else
7968 {
7969
7970 exceptfds_left = 0;
7971 }
7972
7973 /* Compute the timeout for the suspension if a timeout value was supplied. */
7974 if (timeout != NX_NULL)
7975 {
7976
7977 /* Calculate ticks for the ThreadX Timer. */
7978 ticks = (ULONG)(timeout -> tv_usec)/NX_MICROSECOND_PER_CPU_TICK + (ULONG)(timeout -> tv_sec) * NX_IP_PERIODIC_RATE;
7979 }
7980 else
7981 {
7982
7983 /* If no timeout input, set the wait to 'forever.' */
7984 ticks = TX_WAIT_FOREVER;
7985 }
7986
7987 /* Get the protection mutex. */
7988 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
7989
7990 /* Check the status. */
7991 if (status != NX_SUCCESS)
7992 {
7993
7994 /* Set the socket error if extended socket options enabled. */
7995 nx_bsd_set_errno(EACCES);
7996
7997 /* Set the socket error. */
7998 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
7999 return(NX_SOC_ERROR);
8000 }
8001
8002 /* Loop through the BSD sockets to see if the read ready request can be satisfied. */
8003 for (i = 0; i < (nfds - NX_BSD_SOCKFD_START); i++)
8004 {
8005
8006 if((readfds == NX_NULL) || (readfds_left == 0))
8007 break;
8008
8009 /* Is this socket selected for read? */
8010 if (NX_BSD_FD_ISSET((i + NX_BSD_SOCKFD_START), readfds))
8011 {
8012
8013 /* Yes, decrement the number of read selectors left to search for. */
8014 readfds_left--;
8015
8016 /* Is this BSD socket in use? */
8017 if (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
8018 {
8019
8020 /* There is; add this socket to the read ready list. */
8021 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
8022 }
8023
8024 /* Check to see if there is a disconnection request pending. */
8025 else if (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_DISCONNECTION_REQUEST)
8026 {
8027
8028 /* There is; add this socket to the read ready list. */
8029 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
8030 }
8031
8032 /* Check to see if there is a receive packet pending. */
8033 else if (nx_bsd_socket_array[i].nx_bsd_socket_received_packet)
8034 {
8035
8036 /* Therer is; add this socket to the read ready list. */
8037 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
8038 }
8039 /* Is this a TCP socket? */
8040 else if (nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket)
8041 {
8042 /* Check if this is a master socket and if its associated secondary socket
8043 is connected. If it is, the master socket should be considered readable. */
8044 if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET)
8045 {
8046
8047 if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN)
8048 {
8049
8050 /* If the secondary socket does not exist, try to allocate one. */
8051 if(nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id >= NX_BSD_MAX_SOCKETS)
8052 {
8053
8054 /* This secondary socket is not avaialble yet. This could happen if the
8055 previous accept call fails to allocate a new secondary socket. */
8056 ret = nx_bsd_tcp_create_listen_socket(i, 0);
8057
8058 if(ret < 0)
8059 {
8060
8061 /* Mark the FD set so the application could be notified. */
8062 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
8063 }
8064 }
8065
8066 if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
8067 {
8068 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
8069 }
8070 }
8071 }
8072 else if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
8073 {
8074
8075 /* Yes; attempt to perform a non-blocking read. */
8076 status = nx_tcp_socket_receive(nx_bsd_socket_array[i].nx_bsd_socket_tcp_socket, &packet_ptr, TX_NO_WAIT);
8077
8078 /* Check for success. */
8079 if (status == NX_SUCCESS)
8080 {
8081
8082 /* Save the received packet in the TCP BSD socket packet pointer. */
8083 nx_bsd_socket_array[i].nx_bsd_socket_received_packet = packet_ptr;
8084
8085 /* Reset the packet offset. */
8086 nx_bsd_socket_array[i].nx_bsd_socket_received_packet_offset = 0;
8087
8088 /* Increase the received count. */
8089 nx_bsd_socket_array[i].nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
8090 nx_bsd_socket_array[i].nx_bsd_socket_received_packet_count++;
8091
8092 /* Add this socket to the read ready list. */
8093 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
8094 }
8095 }
8096 }
8097 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
8098 /* Is this a raw socket? */
8099 else if (nx_bsd_socket_array[i].nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET)
8100 {
8101
8102 /* Check the raw receive queue (by definition has a zero wait option (no suspension)). */
8103 status = nx_bsd_raw_packet_receive(&nx_bsd_socket_array[i], &packet_ptr);
8104
8105 /* Determine if we have a packet. */
8106 if ((status == NX_SUCCESS) && (packet_ptr))
8107 {
8108
8109 /* Get the sender IP address from the raw packet. */
8110 status = nx_bsd_raw_packet_info_extract(packet_ptr, &(nx_bsd_socket_array[i].nx_bsd_socket_source_ip_address), NX_NULL);
8111
8112 /* Save the received packet in the BSD socket packet pointer. */
8113 nx_bsd_socket_array[i].nx_bsd_socket_received_packet = packet_ptr;
8114
8115 /* Reset the packet offset. */
8116 nx_bsd_socket_array[i].nx_bsd_socket_received_packet_offset = 0;
8117
8118 /* Add this socket to the read ready list. */
8119 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &readfds_found);
8120 }
8121 }
8122 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
8123
8124 }
8125 }
8126 /* Loop through the BSD sockets to see if the write ready request can be satisfied. */
8127 for(i = 0; i < (nfds - NX_BSD_SOCKFD_START); i++)
8128 {
8129
8130 if((writefds == NX_NULL) || (writefds_left == 0))
8131 break;
8132
8133 /* Is this socket selected for write? */
8134 if (NX_BSD_FD_ISSET(i + NX_BSD_SOCKFD_START, writefds))
8135 {
8136
8137 /* Yes, decrement the number of read selectors left to search for. */
8138 writefds_left--;
8139
8140 /* Is this BSD socket in use? */
8141 if (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
8142 {
8143
8144 /* Yes, add this socket to the write ready list. */
8145 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &writefds_found);
8146 }
8147
8148 /* Check to see if there is a connection request pending. */
8149 else if (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_REQUEST)
8150 {
8151
8152 /* Yes, add this socket to the write ready list. */
8153 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &writefds_found);
8154 }
8155
8156 /* Check to see if there is an error.*/
8157 else if (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
8158 {
8159
8160 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &writefds_found);
8161 }
8162 }
8163 }
8164
8165 /* Loop through the BSD sockets to see if the exception request can be satisfied. */
8166 for(i = 0; i < (nfds - NX_BSD_SOCKFD_START); i++)
8167 {
8168
8169 if((exceptfds == NX_NULL) || (exceptfds_left == 0))
8170 break;
8171
8172 /* Is this socket selected for exceptions? */
8173 if (NX_BSD_FD_ISSET(i + NX_BSD_SOCKFD_START, exceptfds))
8174 {
8175
8176 /* Yes, decrement the number of read selectors left to search for. */
8177 exceptfds_left--;
8178
8179 /* Is this BSD socket in use? */
8180 if (!(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
8181 {
8182
8183 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &exceptfds_found);
8184 }
8185
8186 /* Check to see if there is an error.*/
8187 else if(nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_ERROR)
8188 {
8189
8190 NX_BSD_FD_SET(i + NX_BSD_SOCKFD_START, &exceptfds_found);
8191 }
8192 }
8193 }
8194
8195 /* Now determine if we have found anything that satisfies the select request. */
8196 if (readfds_found.fd_count || writefds_found.fd_count || exceptfds_found.fd_count)
8197 {
8198
8199 /* Yes, return what we have and we're done. */
8200
8201 /* Copy over the requested read ready fds. */
8202 if(readfds)
8203 *readfds = readfds_found;
8204
8205 if(writefds)
8206 *writefds = writefds_found;
8207
8208 if(exceptfds)
8209 *exceptfds = exceptfds_found;
8210
8211 /* Release the protection mutex. */
8212 tx_mutex_put(nx_bsd_protection_ptr);
8213
8214 /* Return the number of fds found. */
8215 return(readfds_found.fd_count + writefds_found.fd_count + exceptfds_found.fd_count);
8216 }
8217
8218 /* Otherwise, nothing is ready to be read at this point. */
8219
8220 /* Pickup the current thread. */
8221 current_thread_ptr = tx_thread_identify();
8222
8223 /* Save the fd requests in the local suspension structure. This will be used by the receive notify routines to
8224 wakeup threads on the select. */
8225 suspend_request.nx_bsd_socket_suspend_actual_flags = 0;
8226
8227 if(readfds)
8228 suspend_request.nx_bsd_socket_suspend_read_fd_set = *readfds;
8229 else
8230 NX_BSD_FD_ZERO(&suspend_request.nx_bsd_socket_suspend_read_fd_set);
8231
8232 if(writefds)
8233 suspend_request.nx_bsd_socket_suspend_write_fd_set = *writefds;
8234 else
8235 NX_BSD_FD_ZERO(&suspend_request.nx_bsd_socket_suspend_write_fd_set);
8236
8237 if(exceptfds)
8238 suspend_request.nx_bsd_socket_suspend_exception_fd_set = *exceptfds;
8239 else
8240 NX_BSD_FD_ZERO(&suspend_request.nx_bsd_socket_suspend_exception_fd_set);
8241
8242 /* Temporarily disable preemption. */
8243 tx_thread_preemption_change(current_thread_ptr, 0, &original_threshold);
8244
8245 /* Release the protection mutex. */
8246 tx_mutex_put(nx_bsd_protection_ptr);
8247
8248 status = tx_event_flags_get(&nx_bsd_events, NX_BSD_SELECT_EVENT, TX_OR_CLEAR, (ULONG *) &suspend_request, ticks);
8249
8250 /* Restore original preemption threshold. */
8251 tx_thread_preemption_change(current_thread_ptr, original_threshold, &original_threshold);
8252
8253 /* Check for an error. */
8254 if (status != NX_SUCCESS)
8255 {
8256
8257 /* If we got here, we received no packets. */
8258
8259 /* TX_NO_EVENT implies an immediate return from the flag get call.
8260 This happens if the wait option is set to zero. */
8261 if (status == TX_NO_EVENTS)
8262 {
8263
8264 /* Determine if the effected sockets are non blocking (zero ticks for the wait option). */
8265 if (ticks == 0)
8266 nx_bsd_set_errno(EWOULDBLOCK);
8267 else
8268 nx_bsd_set_errno(ETIMEDOUT);
8269
8270 /* Do not handle as an error; just a timeout so return 0. */
8271 return(0);
8272 }
8273 else
8274 {
8275
8276 /* Actual error. */
8277 /* Set the socket error if extended socket options enabled. */
8278 nx_bsd_set_errno(EINVAL);
8279
8280 /* Error getting the protection mutex. */
8281 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
8282 return(NX_SOC_ERROR);
8283 }
8284 }
8285 else
8286 {
8287
8288 /* Otherwise, a receive event has been found. Simply copy the receive events. */
8289 if(readfds)
8290 *readfds = suspend_request.nx_bsd_socket_suspend_read_fd_set;
8291 if(writefds)
8292 *writefds = suspend_request.nx_bsd_socket_suspend_write_fd_set;
8293 if(exceptfds)
8294 *exceptfds = suspend_request.nx_bsd_socket_suspend_exception_fd_set;
8295
8296 /* Return the number of fds. */
8297 return(suspend_request.nx_bsd_socket_suspend_read_fd_set.fd_count +
8298 suspend_request.nx_bsd_socket_suspend_write_fd_set.fd_count +
8299 suspend_request.nx_bsd_socket_suspend_exception_fd_set.fd_count);
8300 }
8301
8302
8303 }
8304
8305
8306
8307 /**************************************************************************/
8308 /* */
8309 /* FUNCTION RELEASE */
8310 /* */
8311 /* nx_bsd_tcp_receive_notify PORTABLE C */
8312 /* 6.1 */
8313 /* AUTHOR */
8314 /* */
8315 /* Yuxin Zhou, Microsoft Corporation */
8316 /* */
8317 /* DESCRIPTION */
8318 /* */
8319 /* This is the NetX callback function for TCP Socket receive operation */
8320 /* This function resumes all the threads suspended on the socket. */
8321 /* */
8322 /* INPUT */
8323 /* */
8324 /* *socket_ptr Pointer to the socket which */
8325 /* received the data packet */
8326 /* */
8327 /* OUTPUT */
8328 /* */
8329 /* None */
8330 /* */
8331 /* CALLS */
8332 /* */
8333 /* FD_ZERO Clear a socket ready list */
8334 /* FD_ISSET Check a socket is ready */
8335 /* FD_SET Set a socket to check */
8336 /* tx_event_flags_get Get events */
8337 /* tx_mutex_get Get protection */
8338 /* tx_mutex_put Release protection */
8339 /* tx_thread_identify Get current thread pointer */
8340 /* */
8341 /* CALLED BY */
8342 /* */
8343 /* NetX */
8344 /* */
8345 /* RELEASE HISTORY */
8346 /* */
8347 /* DATE NAME DESCRIPTION */
8348 /* */
8349 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8350 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8351 /* resulting in version 6.1 */
8352 /* */
8353 /**************************************************************************/
nx_bsd_tcp_receive_notify(NX_TCP_SOCKET * socket_ptr)8354 static VOID nx_bsd_tcp_receive_notify(NX_TCP_SOCKET *socket_ptr)
8355 {
8356 UINT bsd_socket_index;
8357
8358 /* Figure out what BSD socket this is. */
8359 bsd_socket_index = (UINT) socket_ptr -> nx_tcp_socket_reserved_ptr;
8360
8361 /* Determine if this is a good index into the BSD socket array. */
8362 if (bsd_socket_index >= NX_BSD_MAX_SOCKETS)
8363 {
8364
8365 /* Bad socket index... simply return! */
8366 return;
8367 }
8368
8369 /* Now check if the socket may have been released (e.g. socket closed) while
8370 waiting for the mutex. */
8371 if( socket_ptr -> nx_tcp_socket_id == 0 )
8372 {
8373
8374 return;
8375 }
8376
8377 /* Check the suspended socket list for one ready to receive or send packets. */
8378 nx_bsd_select_wakeup(bsd_socket_index, FDSET_READ);
8379
8380
8381 return;
8382 }
8383
8384
8385 /**************************************************************************/
8386 /* */
8387 /* FUNCTION RELEASE */
8388 /* */
8389 /* nx_bsd_tcp_establish_notify PORTABLE C */
8390 /* 6.1 */
8391 /* AUTHOR */
8392 /* */
8393 /* Yuxin Zhou, Microsoft Corporation */
8394 /* */
8395 /* DESCRIPTION */
8396 /* */
8397 /* This is the NetX callback function for TCP Server Socket listen. */
8398 /* This function resumes all the threads suspended on the socket. */
8399 /* */
8400 /* INPUT */
8401 /* */
8402 /* *socket_ptr Pointer to the socket which */
8403 /* Received the data packet */
8404 /* */
8405 /* OUTPUT */
8406 /* */
8407 /* None */
8408 /* */
8409 /* CALLS */
8410 /* */
8411 /* FD_ZERO Clear a socket ready list */
8412 /* FD_ISSET Check a socket is ready */
8413 /* FD_SET Set a socket to check */
8414 /* tx_event_flags_get Get events */
8415 /* tx_mutex_get Get protection */
8416 /* tx_mutex_put Release protection */
8417 /* tx_thread_identify Get current thread pointer */
8418 /* */
8419 /* CALLED BY */
8420 /* */
8421 /* NetX */
8422 /* */
8423 /* RELEASE HISTORY */
8424 /* */
8425 /* DATE NAME DESCRIPTION */
8426 /* */
8427 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8428 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8429 /* resulting in version 6.1 */
8430 /* */
8431 /**************************************************************************/
8432 #ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT
nx_bsd_tcp_establish_notify(NX_TCP_SOCKET * socket_ptr)8433 static VOID nx_bsd_tcp_establish_notify(NX_TCP_SOCKET *socket_ptr)
8434 {
8435 UINT bsd_socket_index;
8436 UINT master_socket_index;
8437
8438 /* Figure out what BSD socket this is. */
8439 bsd_socket_index = (UINT) socket_ptr -> nx_tcp_socket_reserved_ptr;
8440
8441 /* Determine if this is a good index into the BSD socket array. */
8442 if (bsd_socket_index >= NX_BSD_MAX_SOCKETS)
8443 {
8444
8445 /* Bad socket index... simply return! */
8446 return;
8447 }
8448
8449 /* Initialize the master socket index to an invalid value so we can check if it was actually used
8450 later. */
8451 master_socket_index = NX_BSD_MAX_SOCKETS;
8452
8453 /* Mark the socket as connected, and also clear the EINPROGRESS flag */
8454 nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
8455
8456 nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_REQUEST;
8457
8458 /* Reset the listen-enabled flag. */
8459 nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_LISTEN);
8460
8461 /* Mark the socket is bound. */
8462 nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_BOUND;
8463
8464 #ifndef NX_DISABLE_IPV4
8465 /* Find out the local address this socket is connected on. */
8466 if(nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_family == AF_INET)
8467 {
8468 /* IPv4 case */
8469 nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_local_bind_interface = (ULONG)socket_ptr -> nx_tcp_socket_connect_interface;
8470 }
8471 #endif /* NX_DISABLE_IPV4 */
8472 #ifdef FEATURE_NX_IPV6
8473 if(nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_family == AF_INET6)
8474 {
8475 /* IPv6 */
8476 nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_local_bind_interface = (ULONG)socket_ptr -> nx_tcp_socket_ipv6_addr;
8477 }
8478 #endif
8479 /* Determine if the BSD socket is server socket. */
8480
8481
8482 /* Is this a secondary socket? */
8483 if (nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET)
8484 {
8485
8486 /* Yes, get the master socket. */
8487 master_socket_index = (UINT)(nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_union_id.nx_bsd_socket_master_socket_id);
8488
8489 /* Mark the server socket as also connected. */
8490 nx_bsd_socket_array[master_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTED;
8491
8492 nx_bsd_socket_array[master_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_REQUEST;
8493
8494 /* Check on connect requests for all server sockets for this master socket. */
8495 nx_bsd_select_wakeup(master_socket_index, FDSET_READ);
8496 }
8497 else
8498 {
8499 /* This is a client socket. */
8500 nx_bsd_select_wakeup(bsd_socket_index, FDSET_WRITE);
8501 }
8502 }
8503 #endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */
8504
8505 /**************************************************************************/
8506 /* */
8507 /* FUNCTION RELEASE */
8508 /* */
8509 /* nx_bsd_tcp_socket_disconnect_notify PORTABLE C */
8510 /* 6.1 */
8511 /* AUTHOR */
8512 /* */
8513 /* Yuxin Zhou, Microsoft Corporation */
8514 /* */
8515 /* DESCRIPTION */
8516 /* */
8517 /* This is the NetX callback function for TCP Socket disconnect. */
8518 /* This function resumes all the BSD threads suspended on the socket. */
8519 /* */
8520 /* INPUT */
8521 /* */
8522 /* *socket_ptr Pointer to the socket which */
8523 /* received the data packet */
8524 /* */
8525 /* OUTPUT */
8526 /* */
8527 /* None */
8528 /* */
8529 /* CALLS */
8530 /* */
8531 /* FD_ZERO Clear a socket ready list */
8532 /* FD_ISSET Check a socket is ready */
8533 /* FD_SET Set a socket to check */
8534 /* tx_event_flags_get Get events */
8535 /* tx_mutex_get Get protection */
8536 /* tx_mutex_put Release protection */
8537 /* tx_thread_identify Get current thread pointer */
8538 /* */
8539 /* CALLED BY */
8540 /* */
8541 /* NetX */
8542 /* */
8543 /* RELEASE HISTORY */
8544 /* */
8545 /* DATE NAME DESCRIPTION */
8546 /* */
8547 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8548 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8549 /* resulting in version 6.1 */
8550 /* */
8551 /**************************************************************************/
nx_bsd_tcp_socket_disconnect_notify(NX_TCP_SOCKET * socket_ptr)8552 static VOID nx_bsd_tcp_socket_disconnect_notify(NX_TCP_SOCKET *socket_ptr)
8553 {
8554
8555 UINT bsd_socket_index;
8556 UINT master_socket_index;
8557 NX_BSD_SOCKET *bsd_socket_ptr;
8558 UINT status;
8559
8560
8561 /* Figure out what BSD socket this is. */
8562 bsd_socket_index = (UINT) socket_ptr -> nx_tcp_socket_reserved_ptr;
8563
8564 /* Determine if this is a good index into the BSD socket array. */
8565 if (bsd_socket_index >= NX_BSD_MAX_SOCKETS)
8566 {
8567 /* No good! */
8568 return;
8569 }
8570
8571 bsd_socket_ptr = &nx_bsd_socket_array[bsd_socket_index];
8572
8573 /* If the socket already received a disconnect request, no need to do anything here. */
8574 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_DISCONNECTION_REQUEST)
8575 {
8576 return;
8577 }
8578
8579 /* Mark this socket as having a disconnect request pending. */
8580 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_DISCONNECTION_REQUEST;
8581
8582 /* Is the socket trying to make a connection? */
8583 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTION_INPROGRESS)
8584 {
8585
8586 /* Yes, clear the INPROGRESS flag. */
8587 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_CONNECTION_INPROGRESS);
8588
8589 /* If this is secondary server socket, there is no need to wake up the select call. */
8590 if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET)
8591 {
8592
8593
8594 /* Instead the socket needs to be cleaned up and to perform a relisten. */
8595 if(!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED))
8596 {
8597
8598 /* Turn off the disconnection_request flag. */
8599 bsd_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_DISCONNECTION_REQUEST);
8600
8601 nx_tcp_server_socket_unaccept(bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
8602
8603 /* Check if a listen request is queued up for this socket. */
8604 nx_bsd_tcp_pending_connection(bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port,
8605 bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
8606
8607 status = nx_tcp_server_socket_relisten(nx_bsd_default_ip,
8608 bsd_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port,
8609 bsd_socket_ptr -> nx_bsd_socket_tcp_socket);
8610
8611 /* Force the socket into SYN_RECEIVED state */
8612 nx_tcp_server_socket_accept(bsd_socket_ptr -> nx_bsd_socket_tcp_socket, NX_NO_WAIT);
8613
8614 if(status == NX_CONNECTION_PENDING)
8615 {
8616
8617 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
8618 }
8619 else if(status != NX_SUCCESS)
8620 {
8621
8622 /* Failed the relisten on the secondary socket. Set the error code on the
8623 master socket, and wake it up. */
8624
8625 master_socket_index = (UINT)(bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id;
8626
8627 nx_bsd_socket_array[master_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
8628 nx_bsd_set_error_code(&nx_bsd_socket_array[master_socket_index], status);
8629
8630 nx_bsd_select_wakeup(master_socket_index, (FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION));
8631 }
8632 }
8633
8634 }
8635 else
8636 {
8637
8638 /* Set error code. */
8639 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
8640 bsd_socket_ptr -> nx_bsd_socket_error_code = ECONNREFUSED;
8641
8642 /* Wake up the select on both read and write FDsets. */
8643 nx_bsd_select_wakeup(bsd_socket_index, (FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION));
8644 }
8645 }
8646 else if(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
8647 {
8648
8649 /* Wake up the select on both read and write FDsets. */
8650 nx_bsd_select_wakeup(bsd_socket_index, (FDSET_READ | FDSET_WRITE | FDSET_EXCEPTION));
8651 }
8652 else
8653 {
8654
8655 /* In this case, connection reaches maximum retries or is refused by peer. */
8656 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ERROR;
8657 bsd_socket_ptr -> nx_bsd_socket_error_code = ENOTCONN;
8658 }
8659
8660 }
8661
8662
8663
8664 /**************************************************************************/
8665 /* */
8666 /* FUNCTION RELEASE */
8667 /* */
8668 /* nx_bsd_udp_receive_notify PORTABLE C */
8669 /* 6.1 */
8670 /* AUTHOR */
8671 /* */
8672 /* Yuxin Zhou, Microsoft Corporation */
8673 /* */
8674 /* DESCRIPTION */
8675 /* */
8676 /* This is the NetX callback function for UDP Socket receive */
8677 /* operation. */
8678 /* */
8679 /* INPUT */
8680 /* */
8681 /* *socket_ptr Pointer to the socket which */
8682 /* Received the data packet */
8683 /* */
8684 /* OUTPUT */
8685 /* */
8686 /* None */
8687 /* */
8688 /* CALLS */
8689 /* */
8690 /* FD_ZERO Clear a socket ready list */
8691 /* FD_ISSET Check a socket is ready */
8692 /* FD_SET Set a socket to check */
8693 /* tx_event_flags_get Get events */
8694 /* tx_mutex_get Get protection */
8695 /* tx_mutex_put Release protection */
8696 /* tx_thread_identify Get current thread pointer */
8697 /* nx_udp_socket_receive Receive UDP packet */
8698 /* */
8699 /* CALLED BY */
8700 /* */
8701 /* NetX */
8702 /* */
8703 /* RELEASE HISTORY */
8704 /* */
8705 /* DATE NAME DESCRIPTION */
8706 /* */
8707 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8708 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8709 /* resulting in version 6.1 */
8710 /* */
8711 /**************************************************************************/
nx_bsd_udp_receive_notify(NX_UDP_SOCKET * socket_ptr)8712 static VOID nx_bsd_udp_receive_notify(NX_UDP_SOCKET *socket_ptr)
8713 {
8714
8715 UINT bsd_socket_index;
8716 NX_PACKET *packet_ptr;
8717 NX_UDP_SOCKET *udp_socket_ptr;
8718
8719
8720 /* Figure out what BSD socket this is. */
8721 bsd_socket_index = ((UINT) socket_ptr -> nx_udp_socket_reserved_ptr) & 0x0000FFFF;
8722
8723 /* Determine if this is a good index into the BSD socket array. */
8724 if (bsd_socket_index >= NX_BSD_MAX_SOCKETS)
8725 {
8726 return;
8727 }
8728
8729 udp_socket_ptr = nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_udp_socket;
8730
8731 if (nx_udp_socket_receive(udp_socket_ptr, &packet_ptr, NX_NO_WAIT))
8732 {
8733 return;
8734 }
8735
8736 nx_bsd_udp_packet_received((INT)bsd_socket_index, packet_ptr);
8737
8738 }
8739
8740
8741 /**************************************************************************/
8742 /* */
8743 /* FUNCTION RELEASE */
8744 /* */
8745 /* FD_SET PORTABLE C */
8746 /* 6.3.0 */
8747 /* AUTHOR */
8748 /* */
8749 /* Yuxin Zhou, Microsoft Corporation */
8750 /* */
8751 /* DESCRIPTION */
8752 /* */
8753 /* This function adds a fd to the set. */
8754 /* */
8755 /* INPUT */
8756 /* */
8757 /* fd fd to add. */
8758 /* fd_set *fdset fd set. */
8759 /* */
8760 /* OUTPUT */
8761 /* */
8762 /* None */
8763 /* */
8764 /* CALLS */
8765 /* */
8766 /* None */
8767 /* */
8768 /* CALLED BY */
8769 /* */
8770 /* Application Code */
8771 /* */
8772 /* RELEASE HISTORY */
8773 /* */
8774 /* DATE NAME DESCRIPTION */
8775 /* */
8776 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8777 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8778 /* resulting in version 6.1 */
8779 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
8780 /* used new API/structs naming,*/
8781 /* resulting in version 6.3.0 */
8782 /* */
8783 /**************************************************************************/
NX_BSD_FD_SET(INT fd,nx_bsd_fd_set * fdset)8784 VOID NX_BSD_FD_SET(INT fd, nx_bsd_fd_set *fdset)
8785 {
8786
8787 UINT index;
8788
8789
8790 /* Check the FD size. */
8791 if (fd >= NX_BSD_SOCKFD_START)
8792 {
8793
8794 /* Normalize the fd. */
8795 fd = fd - NX_BSD_SOCKFD_START;
8796
8797 /* Now make sure it isn't too big. */
8798 if (fd < NX_BSD_MAX_SOCKETS)
8799 {
8800
8801 /* Calculate the index into the bit map. */
8802 index = (UINT)fd/32;
8803
8804 /* Now calculate the bit position. */
8805 fd = fd % 32;
8806
8807 /* Is the bit already set? */
8808 if ((fdset -> fd_array[index] & (((ULONG) 1) << fd)) == 0)
8809 {
8810
8811 /* No, set the bit. */
8812 fdset -> fd_array[index] = fdset -> fd_array[index] | (((ULONG) 1) << fd);
8813
8814 /* Increment the counter. */
8815 fdset -> fd_count++;
8816 }
8817 }
8818 }
8819 }
8820
8821 /**************************************************************************/
8822 /* */
8823 /* FUNCTION RELEASE */
8824 /* */
8825 /* FD_CLR PORTABLE C */
8826 /* 6.3.0 */
8827 /* AUTHOR */
8828 /* */
8829 /* Yuxin Zhou, Microsoft Corporation */
8830 /* */
8831 /* DESCRIPTION */
8832 /* */
8833 /* This function removes a fd from a fd set. */
8834 /* */
8835 /* INPUT */
8836 /* */
8837 /* fd fd to remove. */
8838 /* fd_set *fdset fd set. */
8839 /* */
8840 /* OUTPUT */
8841 /* */
8842 /* None */
8843 /* */
8844 /* CALLS */
8845 /* */
8846 /* None */
8847 /* */
8848 /* CALLED BY */
8849 /* */
8850 /* Application Code */
8851 /* */
8852 /* RELEASE HISTORY */
8853 /* */
8854 /* DATE NAME DESCRIPTION */
8855 /* */
8856 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8857 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8858 /* resulting in version 6.1 */
8859 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
8860 /* used new API/structs naming,*/
8861 /* resulting in version 6.3.0 */
8862 /* */
8863 /**************************************************************************/
NX_BSD_FD_CLR(INT fd,nx_bsd_fd_set * fdset)8864 VOID NX_BSD_FD_CLR(INT fd, nx_bsd_fd_set *fdset)
8865 {
8866
8867 UINT index;
8868
8869
8870 /* Check the FD size. */
8871 if (fd >= NX_BSD_SOCKFD_START)
8872 {
8873
8874 /* Normalize the fd. */
8875 fd = fd - NX_BSD_SOCKFD_START;
8876
8877 /* Now make sure it isn't too big. */
8878 if ((fd < NX_BSD_MAX_SOCKETS) && (fdset -> fd_count))
8879 {
8880
8881 /* Calculate the index into the bit map. */
8882 index = (UINT)fd/32;
8883
8884 /* Now calculate the bit position. */
8885 fd = fd % 32;
8886
8887 /* Determine if the bit is set. */
8888 if (fdset -> fd_array[index] & (((ULONG) 1) << fd))
8889 {
8890
8891 /* Yes, clear the bit. */
8892 fdset -> fd_array[index] = fdset -> fd_array[index] & ~(((ULONG) 1) << fd);
8893
8894 /* Decrement the counter. */
8895 fdset -> fd_count--;
8896 }
8897 }
8898 }
8899 }
8900
8901
8902 /**************************************************************************/
8903 /* */
8904 /* FUNCTION RELEASE */
8905 /* */
8906 /* FD_ISSET PORTABLE C */
8907 /* 6.1 */
8908 /* AUTHOR */
8909 /* */
8910 /* Yuxin Zhou, Microsoft Corporation */
8911 /* */
8912 /* DESCRIPTION */
8913 /* */
8914 /* This function tests to see if a fd is in the set. */
8915 /* */
8916 /* INPUT */
8917 /* */
8918 /* fd fd to add. */
8919 /* fd_set *fdset fd set. */
8920 /* */
8921 /* OUTPUT */
8922 /* */
8923 /* NX_TRUE If fd is found in the set. */
8924 /* NX_FALSE If fd is not there in the set.*/
8925 /* */
8926 /* CALLS */
8927 /* */
8928 /* None */
8929 /* */
8930 /* CALLED BY */
8931 /* */
8932 /* Application Code */
8933 /* */
8934 /* RELEASE HISTORY */
8935 /* */
8936 /* DATE NAME DESCRIPTION */
8937 /* */
8938 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
8939 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
8940 /* resulting in version 6.1 */
8941 /* */
8942 /**************************************************************************/
NX_BSD_FD_ISSET(INT fd,nx_bsd_fd_set * fdset)8943 INT NX_BSD_FD_ISSET(INT fd, nx_bsd_fd_set *fdset)
8944 {
8945
8946 UINT index;
8947
8948
8949 /* Check the FD size. */
8950 if (fd >= NX_BSD_SOCKFD_START)
8951 {
8952
8953 /* Normalize the fd. */
8954 fd = fd - NX_BSD_SOCKFD_START;
8955
8956 /* Now make sure it isn't too big. */
8957 if (fd < NX_BSD_MAX_SOCKETS)
8958 {
8959
8960 /* Calculate the index into the bit map. */
8961 index = (UINT)fd/32;
8962
8963 /* Now calculate the bit position. */
8964 fd = fd % 32;
8965
8966 /* Finally, see if the bit is set. */
8967 if (fdset -> fd_array[index] & (((ULONG) 1) << fd))
8968 {
8969
8970 /* Yes, return true! */
8971 return(NX_TRUE);
8972 }
8973 }
8974 }
8975
8976 /* Otherwise, return false. */
8977 return(NX_FALSE);
8978 }
8979
8980
8981 /**************************************************************************/
8982 /* */
8983 /* FUNCTION RELEASE */
8984 /* */
8985 /* FD_ZERO PORTABLE C */
8986 /* 6.3.0 */
8987 /* AUTHOR */
8988 /* */
8989 /* Yuxin Zhou, Microsoft Corporation */
8990 /* */
8991 /* DESCRIPTION */
8992 /* */
8993 /* This function clears a fd set. */
8994 /* */
8995 /* INPUT */
8996 /* */
8997 /* fd_set *fdset fd set to clear. */
8998 /* */
8999 /* OUTPUT */
9000 /* */
9001 /* None */
9002 /* */
9003 /* CALLS */
9004 /* */
9005 /* None */
9006 /* */
9007 /* CALLED BY */
9008 /* */
9009 /* Application Code */
9010 /* */
9011 /* RELEASE HISTORY */
9012 /* */
9013 /* DATE NAME DESCRIPTION */
9014 /* */
9015 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9016 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9017 /* resulting in version 6.1 */
9018 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
9019 /* used new API/structs naming,*/
9020 /* resulting in version 6.3.0 */
9021 /* */
9022 /**************************************************************************/
NX_BSD_FD_ZERO(nx_bsd_fd_set * fdset)9023 VOID NX_BSD_FD_ZERO(nx_bsd_fd_set *fdset)
9024 {
9025
9026 INT i;
9027
9028
9029 /* Clear the count. */
9030 fdset -> fd_count = 0;
9031
9032 /* Loop to clear the fd set. */
9033 for (i = 0; i < (NX_BSD_MAX_SOCKETS+31)/32; i++)
9034 {
9035 /* Clear an entry in the array. */
9036 fdset -> fd_array[i] = 0;
9037 }
9038 }
9039
9040
9041 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
9042 /**************************************************************************/
9043 /* */
9044 /* FUNCTION RELEASE */
9045 /* */
9046 /* nx_bsd_raw_packet_filter PORTABLE C */
9047 /* 6.1.9 */
9048 /* AUTHOR */
9049 /* */
9050 /* Yuxin Zhou, Microsoft Corporation */
9051 /* */
9052 /* DESCRIPTION */
9053 /* */
9054 /* This function receives raw packets from NetX Duo and determines if */
9055 /* BSD will consume the packet (store on the BSD socket raw receive */
9056 /* queue) or if the packet is available to NetX Duo (not consumed). */
9057 /* */
9058 /* INPUT */
9059 /* */
9060 /* ip_ptr NetX Duo IP instance */
9061 /* protocol Received packet protocol */
9062 /* packet_ptr Pointer to the received packet */
9063 /* */
9064 /* OUTPUT */
9065 /* */
9066 /* 0 Raw filter consumed the packet*/
9067 /* 1 Raw filter did not consume */
9068 /* packet. Allow the caller to*/
9069 /* process this packet */
9070 /* */
9071 /* CALLS */
9072 /* */
9073 /* nx_bsd_raw_receive_notify Notify threads waiting to */
9074 /* receive a raw packet */
9075 /* */
9076 /* CALLED BY */
9077 /* */
9078 /* NetX Duo */
9079 /* */
9080 /* RELEASE HISTORY */
9081 /* */
9082 /* DATE NAME DESCRIPTION */
9083 /* */
9084 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9085 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9086 /* resulting in version 6.1 */
9087 /* 10-15-2021 Yuxin Zhou Modified comment(s), */
9088 /* fixed NULL pointer access */
9089 /* for raw socket, */
9090 /* resulting in version 6.1.9 */
9091 /* */
9092 /**************************************************************************/
nx_bsd_raw_packet_filter(NX_IP * ip_ptr,ULONG protocol,NX_PACKET * packet_ptr)9093 static UINT nx_bsd_raw_packet_filter(NX_IP *ip_ptr, ULONG protocol, NX_PACKET *packet_ptr)
9094 {
9095
9096 UINT index;
9097 NX_BSD_SOCKET * bsd_socket_ptr;
9098
9099 /* Calculate the hash index in the raw socket protocol table. */
9100 index = (UINT) ((protocol + (protocol >> 8)) & NX_BSD_SOCKET_RAW_PROTOCOL_TABLE_MASK);
9101
9102 /* Search the bound sockets in this index for particular protocol. */
9103 bsd_socket_ptr = nx_bsd_socket_raw_protocol_table[index];
9104
9105 /* Was a BSD socket with this protocol found? */
9106 if (bsd_socket_ptr == NX_NULL)
9107 {
9108 /* No, let NetX Duo continue processing the packet. */
9109 return 1;
9110 }
9111
9112 do
9113 {
9114 /* Determine if the protocol is matched. */
9115 if ((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE) &&
9116 (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET ) &&
9117 (bsd_socket_ptr -> nx_bsd_socket_protocol == protocol))
9118 {
9119
9120 /* This packet protocol matches the BSD socket. */
9121 /* Make sure the queue_next is zero'ed out. */
9122 packet_ptr -> nx_packet_queue_next = NX_NULL;
9123
9124 /* Add the packet to the BSD socket raw packet receive queue.
9125 Are there any packets on this queue yet? */
9126 if (bsd_socket_ptr -> nx_bsd_socket_received_packet == NX_NULL)
9127 {
9128
9129 /* No, this will be the only one. */
9130 bsd_socket_ptr -> nx_bsd_socket_received_packet = packet_ptr;
9131 bsd_socket_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
9132
9133
9134 /* Set the packet count. */
9135 bsd_socket_ptr -> nx_bsd_socket_received_byte_count = packet_ptr -> nx_packet_length;
9136 bsd_socket_ptr -> nx_bsd_socket_received_packet_count = 1;
9137 }
9138 else
9139 {
9140 /* Yes; add this packet to the end of the queue. */
9141
9142 /* Check if the queue is currently full. */
9143 if (bsd_socket_ptr -> nx_bsd_socket_received_byte_count_max &&
9144 (bsd_socket_ptr -> nx_bsd_socket_received_byte_count >=
9145 bsd_socket_ptr -> nx_bsd_socket_received_byte_count_max))
9146 {
9147
9148 /* Release the packet here, and tell NetX Duo the packet is 'consumed'. */
9149 nx_packet_release(packet_ptr);
9150
9151 return 0;
9152 }
9153
9154 /* Drop the packet if the receive queue exceeds max depth.*/
9155 if(bsd_socket_ptr -> nx_bsd_socket_received_packet_count >=
9156 bsd_socket_ptr -> nx_bsd_socket_received_packet_count_max)
9157 {
9158 /* Release the packet here, and tell NetX Duo the packet is 'consumed'. */
9159 nx_packet_release(packet_ptr);
9160
9161 return 0;
9162 }
9163
9164 /* Add this packet to the end of the BSD raw receive queue. */
9165 (bsd_socket_ptr -> nx_bsd_socket_received_packet_tail) -> nx_packet_queue_next = packet_ptr;
9166 bsd_socket_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
9167
9168
9169 /* Update our packet count. */
9170 bsd_socket_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
9171 bsd_socket_ptr -> nx_bsd_socket_received_packet_count++;
9172 }
9173
9174 /* Notify any suspended threads waiting on this receive event. */
9175 nx_bsd_raw_receive_notify(ip_ptr, (UINT)(bsd_socket_ptr -> nx_bsd_socket_id));
9176
9177 return 0;
9178 }
9179
9180 }while(bsd_socket_ptr != nx_bsd_socket_raw_protocol_table[index]);
9181
9182 /* Was a BSD socket with this protocol found? */
9183 if (bsd_socket_ptr == nx_bsd_socket_raw_protocol_table[index])
9184 {
9185 /* No, let NetX Duo continue processing the packet. */
9186 return 1;
9187 }
9188
9189 return(NX_SUCCESS);
9190 }
9191
9192 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
9193
9194
9195 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
9196 /**************************************************************************/
9197 /* */
9198 /* FUNCTION RELEASE */
9199 /* */
9200 /* nx_bsd_raw_receive_notify PORTABLE C */
9201 /* 6.1 */
9202 /* AUTHOR */
9203 /* */
9204 /* Yuxin Zhou, Microsoft Corporation */
9205 /* */
9206 /* DESCRIPTION */
9207 /* */
9208 /* This is the NetX Duo callback function for raw socket receive */
9209 /* operation. */
9210 /* */
9211 /* INPUT */
9212 /* */
9213 /* ip_ptr NetX Duo IP instance */
9214 /* bsd_socket_index Index of the raw socket which */
9215 /* received the data packet */
9216 /* */
9217 /* OUTPUT */
9218 /* */
9219 /* None */
9220 /* */
9221 /* CALLS */
9222 /* */
9223 /* FD_ZERO Clear a socket ready list */
9224 /* FD_ISSET Check a socket is ready */
9225 /* FD_SET Set a socket to check */
9226 /* tx_event_flags_get Get events */
9227 /* tx_mutex_get Get protection */
9228 /* tx_mutex_put Release protection */
9229 /* tx_thread_identify Get current thread pointer */
9230 /* */
9231 /* CALLED BY */
9232 /* */
9233 /* NetX */
9234 /* */
9235 /* RELEASE HISTORY */
9236 /* */
9237 /* DATE NAME DESCRIPTION */
9238 /* */
9239 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9240 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9241 /* resulting in version 6.1 */
9242 /* */
9243 /**************************************************************************/
nx_bsd_raw_receive_notify(NX_IP * ip_ptr,UINT bsd_socket_index)9244 VOID nx_bsd_raw_receive_notify(NX_IP *ip_ptr, UINT bsd_socket_index)
9245 {
9246 NX_PARAMETER_NOT_USED(ip_ptr);
9247
9248 nx_bsd_select_wakeup(bsd_socket_index, FDSET_READ);
9249
9250 }
9251
9252 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
9253
9254 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
9255
9256 /**************************************************************************/
9257 /* */
9258 /* FUNCTION RELEASE */
9259 /* */
9260 /* nx_bsd_raw_packet_receive PORTABLE C */
9261 /* 6.3.0 */
9262 /* AUTHOR */
9263 /* */
9264 /* Yuxin Zhou, Microsoft Corporation */
9265 /* */
9266 /* DESCRIPTION */
9267 /* */
9268 /* This function retrieves a packet from the BSD raw socket receive */
9269 /* queue. */
9270 /* */
9271 /* INPUT */
9272 /* */
9273 /* bsd_socket_ptr BSD raw socket */
9274 /* packet_ptr Pointer to retrieved packet */
9275 /* */
9276 /* OUTPUT */
9277 /* */
9278 /* NX_SUCCESS Packet successfully retrieved */
9279 /* NX_NO_PACKET No packet on receive queue */
9280 /* NX_NOT_ENABLED Not enabled for raw packets */
9281 /* */
9282 /* CALLS */
9283 /* */
9284 /* None */
9285 /* */
9286 /* CALLED BY */
9287 /* */
9288 /* select Checks for receive packets */
9289 /* recv Checks the specified socket for */
9290 /* received packets */
9291 /* */
9292 /* RELEASE HISTORY */
9293 /* */
9294 /* DATE NAME DESCRIPTION */
9295 /* */
9296 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9297 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9298 /* resulting in version 6.1 */
9299 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
9300 /* used new API/structs naming,*/
9301 /* resulting in version 6.3.0 */
9302 /* */
9303 /**************************************************************************/
nx_bsd_raw_packet_receive(NX_BSD_SOCKET * bsd_socket_ptr,NX_PACKET ** packet_ptr)9304 UINT nx_bsd_raw_packet_receive(NX_BSD_SOCKET *bsd_socket_ptr, NX_PACKET **packet_ptr)
9305 {
9306
9307
9308 /* Sanity check. Check this is indeed a raw socket. */
9309 if (!(bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET))
9310 {
9311 /* Set the socket error. */
9312 nx_bsd_set_errno(EPROTOTYPE);
9313
9314 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
9315 return(NX_NOT_ENABLED);
9316 }
9317
9318 /* Verify this socket is enabled for raw packet processing. */
9319 if (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_RAW_SOCKET)
9320 {
9321
9322 /* Are there any packets on the socket raw receive queue? */
9323 if (bsd_socket_ptr -> nx_bsd_socket_received_packet != NX_NULL)
9324 {
9325
9326 /* Yes, return a pointer to the packet at the top of the queue. */
9327 *packet_ptr = bsd_socket_ptr -> nx_bsd_socket_received_packet;
9328
9329 /* Update the packet count. */
9330 bsd_socket_ptr -> nx_bsd_socket_received_byte_count -= (*packet_ptr) -> nx_packet_length;
9331 bsd_socket_ptr -> nx_bsd_socket_received_packet_count--;
9332
9333
9334 /* Remove this packet from the receive queue and update queue packet pointers. */
9335 bsd_socket_ptr -> nx_bsd_socket_received_packet = (*packet_ptr) -> nx_packet_queue_next;
9336
9337 /* If this was the last packet, set the tail pointer to NULL. */
9338 if (bsd_socket_ptr -> nx_bsd_socket_received_packet == NX_NULL)
9339 {
9340 bsd_socket_ptr -> nx_bsd_socket_received_packet_tail = NX_NULL;
9341 bsd_socket_ptr -> nx_bsd_socket_received_byte_count = 0;
9342 bsd_socket_ptr -> nx_bsd_socket_received_packet_count = 0;
9343 }
9344 }
9345 else
9346 {
9347
9348 /* No packets on the queue. Return the NetX Duo status. This is an internal call, so no BSD socket error to report. */
9349 return NX_NO_PACKET;
9350 }
9351 }
9352 else
9353 {
9354 return NX_NOT_ENABLED;
9355 }
9356
9357 return NX_SUCCESS;
9358 }
9359
9360 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
9361
9362 #ifdef NX_ENABLE_IP_RAW_PACKET_FILTER
9363 /**************************************************************************/
9364 /* */
9365 /* FUNCTION RELEASE */
9366 /* */
9367 /* nx_bsd_raw_packet_info_extract PORTABLE C */
9368 /* 6.1 */
9369 /* AUTHOR */
9370 /* */
9371 /* Yuxin Zhou, Microsoft Corporation */
9372 /* */
9373 /* DESCRIPTION */
9374 /* */
9375 /* This function extracts the source IP address and interface index */
9376 /* from the received packet. */
9377 /* */
9378 /* INPUT */
9379 /* */
9380 /* packet_ptr Pointer to received raw packet*/
9381 /* address Pointer to sender IP address */
9382 /* interface_index Pointer to network index */
9383 /* packet received on */
9384 /* */
9385 /* OUTPUT */
9386 /* */
9387 /* NX_SUCCESS Successful completion status */
9388 /* */
9389 /* CALLS */
9390 /* */
9391 /* COPY_IPV6_ADDRESS Copy IPv6 address */
9392 /* */
9393 /* CALLED BY */
9394 /* */
9395 /* Application Code */
9396 /* */
9397 /* RELEASE HISTORY */
9398 /* */
9399 /* DATE NAME DESCRIPTION */
9400 /* */
9401 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9402 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9403 /* resulting in version 6.1 */
9404 /* */
9405 /**************************************************************************/
nx_bsd_raw_packet_info_extract(NX_PACKET * packet_ptr,NXD_ADDRESS * address,UINT * interface_index)9406 UINT nx_bsd_raw_packet_info_extract(NX_PACKET *packet_ptr, NXD_ADDRESS *address, UINT *interface_index)
9407 {
9408
9409 NX_INTERFACE *if_ptr = NX_NULL;
9410
9411
9412 #ifndef NX_DISABLE_IPV4
9413 /* Determine what IP version the packet is. */
9414 if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
9415 {
9416
9417 NX_IPV4_HEADER *ip_header_ptr;
9418
9419 /* Set a pointer to the IPv4 header. */
9420 ip_header_ptr = (NX_IPV4_HEADER *)(packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_IPV4_HEADER));
9421
9422 /* Fill in the IP address information. */
9423 address -> nxd_ip_version = NX_IP_VERSION_V4;
9424 address -> nxd_ip_address.v4 = ip_header_ptr -> nx_ip_header_source_ip;
9425
9426 /* Pick up the packet interface. */
9427 if_ptr = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
9428 }
9429 #endif /* NX_DISABLE_IPV4 */
9430 #ifdef FEATURE_NX_IPV6
9431 if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
9432 {
9433
9434 NX_IPV6_HEADER *ipv6_header_ptr;
9435
9436 ipv6_header_ptr = (NX_IPV6_HEADER *)(packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_IPV6_HEADER));
9437
9438 /* Fill in the IPv6 address information. */
9439 address -> nxd_ip_version = NX_IP_VERSION_V6;
9440
9441 /* Copy the IPv6 address. */
9442 address -> nxd_ip_address.v6[0] = ipv6_header_ptr -> nx_ip_header_source_ip[0];
9443 address -> nxd_ip_address.v6[1] = ipv6_header_ptr -> nx_ip_header_source_ip[1];
9444 address -> nxd_ip_address.v6[2] = ipv6_header_ptr -> nx_ip_header_source_ip[2];
9445 address -> nxd_ip_address.v6[3] = ipv6_header_ptr -> nx_ip_header_source_ip[3];
9446
9447 /* Pick up the packet interface. */
9448 if_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
9449 }
9450 #endif
9451
9452 /* The last piece of information is the packet interface. If the return pointer is NULL we are done! */
9453 if(interface_index == NX_NULL)
9454 return(NX_SUCCESS);
9455
9456 /* Search for interface index number. Initialize interface value as
9457 invalid (0xFFFFFFFF). Once we find valid interface, we will update
9458 the returned value. */
9459 *interface_index = 0xFFFFFFFF;
9460
9461 if(if_ptr == NX_NULL)
9462 {
9463 /* No interface attached. Done here, and return success. */
9464 return(NX_SUCCESS);
9465 }
9466
9467 /* Compute the index by difference of the packet's interface from the primary interface, and dividing by the size. */
9468 *interface_index = if_ptr -> nx_interface_index;
9469
9470 return(NX_SUCCESS);
9471 }
9472
9473 #endif /* NX_ENABLE_IP_RAW_PACKET_FILTER */
9474
9475 /**************************************************************************/
9476 /* */
9477 /* FUNCTION RELEASE */
9478 /* */
9479 /* nx_bsd_set_socket_timed_wait_callback PORTABLE C */
9480 /* 6.1 */
9481 /* AUTHOR */
9482 /* */
9483 /* Yuxin Zhou, Microsoft Corporation */
9484 /* */
9485 /* DESCRIPTION */
9486 /* */
9487 /* This function is called when a BSD TCP socket has closed. If the */
9488 /* BSD socket associated with the TCP socket is not enabled for */
9489 /* REUSEADDR, this function will put the BSD socket in the TIMED WAIT */
9490 /* state. */
9491 /* */
9492 /* When this time out expires, the BSD socket is removed from the TIME */
9493 /* WAIT State and available to the host application. */
9494 /* */
9495 /* Note: only sockets not enabled with REUSEADDR are placed in the WAIT*/
9496 /* STATE. All other BSD sockets are immediately available upon closing.*/
9497 /* */
9498 /* INPUT */
9499 /* */
9500 /* tcp_socket_ptr TCP socket state being closed */
9501 /* */
9502 /* OUTPUT */
9503 /* */
9504 /* None */
9505 /* */
9506 /* CALLS */
9507 /* */
9508 /* tx_thread_identify Identify socket owning thread */
9509 /* tx_mutex_get Obtain BSD mutex protection */
9510 /* tx_mutex_put Release BSD mutex protection */
9511 /* */
9512 /* CALLED BY */
9513 /* */
9514 /* NetX */
9515 /* */
9516 /* RELEASE HISTORY */
9517 /* */
9518 /* DATE NAME DESCRIPTION */
9519 /* */
9520 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9521 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9522 /* resulting in version 6.1 */
9523 /* */
9524 /**************************************************************************/
nx_bsd_socket_timed_wait_callback(NX_TCP_SOCKET * tcp_socket_ptr)9525 VOID nx_bsd_socket_timed_wait_callback(NX_TCP_SOCKET *tcp_socket_ptr)
9526 {
9527 NX_PARAMETER_NOT_USED(tcp_socket_ptr);
9528
9529 /* Logic has been removed elsewhere but for compatibility with
9530 NetX we leave this function stub. */
9531
9532 return;
9533 }
9534
9535
9536
9537 /**************************************************************************/
9538 /* */
9539 /* FUNCTION RELEASE */
9540 /* */
9541 /* nx_packet_data_extract_offset PORTABLE C */
9542 /* 6.1 */
9543 /* AUTHOR */
9544 /* */
9545 /* Yuxin Zhou, Microsoft Corporation */
9546 /* */
9547 /* DESCRIPTION */
9548 /* */
9549 /* This function copies data from a NetX packet (or packet chain) into */
9550 /* the supplied user buffer. */
9551 /* */
9552 /* This basically defines the data extract service in the BSD source */
9553 /* code if it is not provided in the NetX or NetX Duo library already. */
9554 /* */
9555 /* INPUT */
9556 /* */
9557 /* packet_ptr Pointer to the source packet */
9558 /* buffer_start Pointer to destination data area */
9559 /* buffer_length Size in bytes */
9560 /* bytes_copied Number of bytes copied */
9561 /* */
9562 /* OUTPUT */
9563 /* */
9564 /* status Completion status */
9565 /* */
9566 /* CALLS */
9567 /* */
9568 /* None */
9569 /* */
9570 /* CALLED BY */
9571 /* */
9572 /* Application Code */
9573 /* */
9574 /* RELEASE HISTORY */
9575 /* */
9576 /* DATE NAME DESCRIPTION */
9577 /* */
9578 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9579 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
9580 /* verified memcpy use cases, */
9581 /* resulting in version 6.1 */
9582 /* */
9583 /**************************************************************************/
9584 #ifdef NX_BSD_INCLUDE_DATA_EXTRACT_OFFSET
nx_packet_data_extract_offset(NX_PACKET * packet_ptr,ULONG offset,VOID * buffer_start,ULONG buffer_length,ULONG * bytes_copied)9585 UINT nx_packet_data_extract_offset(NX_PACKET *packet_ptr, ULONG offset, VOID *buffer_start, ULONG buffer_length, ULONG *bytes_copied)
9586 {
9587
9588 ULONG remaining_bytes;
9589 UCHAR *source_ptr;
9590 UCHAR *destination_ptr;
9591 ULONG offset_bytes;
9592 #ifndef NX_DISABLE_PACKET_CHAIN
9593 ULONG packet_fragment_length;
9594 #endif
9595 ULONG bytes_to_copy;
9596 NX_PACKET *working_packet_ptr;
9597
9598 working_packet_ptr = packet_ptr;
9599
9600 /* Check for an invalid offset or packet length. */
9601 if(offset >= working_packet_ptr -> nx_packet_length)
9602 {
9603 /* Note: A zero offset with a packet of zero length is ok. */
9604 if ((offset == 0) && (working_packet_ptr -> nx_packet_length == 0))
9605 {
9606 *bytes_copied = 0;
9607 return(NX_SUCCESS);
9608 }
9609
9610 /* Otherwise, this is an invalid offset or packet length. */
9611 return(NX_PACKET_OFFSET_ERROR);
9612 }
9613
9614 /* Initialize the source pointer to NULL. */
9615 source_ptr = NX_NULL;
9616
9617 /* Traverse packet chain to offset. */
9618 offset_bytes = offset;
9619 #ifndef NX_DISABLE_PACKET_CHAIN
9620 while (working_packet_ptr)
9621 {
9622 packet_fragment_length = (working_packet_ptr -> nx_packet_append_ptr - working_packet_ptr -> nx_packet_prepend_ptr) ;
9623
9624 /* Determine if we are at the offset location fragment in the packet chain */
9625 if (packet_fragment_length > offset_bytes)
9626 {
9627 /* Setup loop to copy from this packet. */
9628 source_ptr = working_packet_ptr -> nx_packet_prepend_ptr + offset_bytes;
9629
9630 /* Yes, get out of this loop. */
9631 break;
9632 }
9633
9634 /* Decrement the remaining offset bytes*/
9635 offset_bytes = offset_bytes - packet_fragment_length ;
9636
9637 /* Move to next packet. */
9638 working_packet_ptr = working_packet_ptr -> nx_packet_next;
9639 }
9640 #else /* NX_DISABLE_PACKET_CHAIN */
9641
9642 /* Setup loop to copy from this packet. */
9643 source_ptr = working_packet_ptr -> nx_packet_prepend_ptr + offset_bytes;
9644
9645 #endif /* NX_DISABLE_PACKET_CHAIN */
9646
9647 /* Check for a valid source pointer. */
9648 if (source_ptr == NX_NULL)
9649 return(NX_PACKET_OFFSET_ERROR);
9650
9651 /* Setup the destination pointer. */
9652 destination_ptr = buffer_start;
9653 bytes_to_copy = (packet_ptr->nx_packet_length - offset);
9654
9655 /* Pickup the amount of bytes to copy. */
9656 if( bytes_to_copy < buffer_length)
9657 {
9658 *bytes_copied = bytes_to_copy; /* the amount of bytes returned to the caller */
9659 remaining_bytes = bytes_to_copy; /* for use in the copy loop */
9660 }
9661 else
9662 {
9663 *bytes_copied = buffer_length;
9664 remaining_bytes = buffer_length;
9665 }
9666
9667 #ifndef NX_DISABLE_PACKET_CHAIN
9668 /* Loop to copy bytes from packet(s). */
9669 while (working_packet_ptr && remaining_bytes)
9670 {
9671 #endif /* NX_DISABLE_PACKET_CHAIN */
9672
9673 /* Calculate bytes to copy. */
9674 bytes_to_copy = working_packet_ptr -> nx_packet_append_ptr - source_ptr;
9675 if(remaining_bytes < bytes_to_copy)
9676 bytes_to_copy = remaining_bytes;
9677
9678 /* Copy data from this packet. */
9679 memcpy(destination_ptr, source_ptr, bytes_to_copy); /* Use case of memcpy is verified. */
9680
9681 /* Update the pointers. */
9682 destination_ptr += bytes_to_copy;
9683 remaining_bytes -= bytes_to_copy;
9684
9685 #ifndef NX_DISABLE_PACKET_CHAIN
9686 /* Move to next packet. */
9687 working_packet_ptr = working_packet_ptr -> nx_packet_next;
9688
9689 /* Check for a next packet. */
9690 if (working_packet_ptr)
9691 {
9692
9693 /* Setup new source pointer. */
9694 source_ptr = working_packet_ptr -> nx_packet_prepend_ptr;
9695 }
9696 }
9697 #endif /* NX_DISABLE_PACKET_CHAIN */
9698
9699 /* Return successful completion. */
9700 return(NX_SUCCESS);
9701
9702 }
9703 #endif /* NX_BSD_INCLUDE_DATA_EXTRACT_OFFSET */
9704
9705 /**************************************************************************/
9706 /* */
9707 /* FUNCTION RELEASE */
9708 /* */
9709 /* nx_bsd_timer_entry PORTABLE C */
9710 /* 6.1 */
9711 /* AUTHOR */
9712 /* */
9713 /* Yuxin Zhou, Microsoft Corporation */
9714 /* */
9715 /* DESCRIPTION */
9716 /* */
9717 /* This function is called when the nx_bsd_socket_wait_timer expires. */
9718 /* It signals the BSD thread task to check and decrement the time */
9719 /* remaining on all sockets suspended in the wait state. */
9720 /* */
9721 /* INPUT */
9722 /* */
9723 /* info Timer thread data (not used) */
9724 /* */
9725 /* OUTPUT */
9726 /* */
9727 /* None */
9728 /* */
9729 /* CALLS */
9730 /* */
9731 /* tx_event_flags_set Sets the WAIT event in the BSD */
9732 /* event group */
9733 /* */
9734 /* CALLED BY */
9735 /* */
9736 /* ThreadX */
9737 /* */
9738 /* RELEASE HISTORY */
9739 /* */
9740 /* DATE NAME DESCRIPTION */
9741 /* */
9742 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9743 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9744 /* resulting in version 6.1 */
9745 /* */
9746 /**************************************************************************/
9747 #ifdef NX_BSD_TIMEOUT_PROCESS_IN_TIMER
nx_bsd_timer_entry(ULONG info)9748 VOID nx_bsd_timer_entry(ULONG info)
9749 {
9750 nx_bsd_timeout_process();
9751 }
9752 #endif
9753
9754
9755 /**************************************************************************/
9756 /* */
9757 /* FUNCTION RELEASE */
9758 /* */
9759 /* nx_bsd_socket_set_inherited_settings PORTABLE C */
9760 /* 6.1 */
9761 /* AUTHOR */
9762 /* */
9763 /* Yuxin Zhou, Microsoft Corporation */
9764 /* */
9765 /* DESCRIPTION */
9766 /* */
9767 /* This function applies the socket options of the specified parent */
9768 /* (master) socket to the specified child (secondary) socket, if BSD */
9769 /* extended socket options are enabled. If they are not, this function */
9770 /* has no effect. */
9771 /* */
9772 /* INPUT */
9773 /* */
9774 /* master_sock_id Source of socket options */
9775 /* secondary_sock_id Socket inheriting options */
9776 /* */
9777 /* OUTPUT */
9778 /* */
9779 /* NX_SUCCESS Successful completion */
9780 /* */
9781 /* CALLS */
9782 /* */
9783 /* None */
9784 /* */
9785 /* CALLED BY */
9786 /* */
9787 /* ThreadX */
9788 /* */
9789 /* RELEASE HISTORY */
9790 /* */
9791 /* DATE NAME DESCRIPTION */
9792 /* */
9793 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9794 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9795 /* resulting in version 6.1 */
9796 /* */
9797 /**************************************************************************/
nx_bsd_socket_set_inherited_settings(UINT master_sock_id,UINT secondary_sock_id)9798 UINT nx_bsd_socket_set_inherited_settings(UINT master_sock_id, UINT secondary_sock_id)
9799 {
9800
9801 /* Update the secondary socket options from the master socket. */
9802 if(nx_bsd_socket_array[master_sock_id].nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING)
9803 nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING;
9804 else
9805 nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING);
9806
9807 if(nx_bsd_socket_array[master_sock_id].nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR)
9808 nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_option_flags |= NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR;
9809 else
9810 nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_option_flags &= (ULONG)(~NX_BSD_SOCKET_ENABLE_OPTION_REUSEADDR);
9811
9812 #ifdef NX_ENABLE_TCP_WINDOW_SCALING
9813 nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_maximum =
9814 nx_bsd_socket_array[master_sock_id].nx_bsd_socket_tcp_socket -> nx_tcp_socket_rx_window_maximum;
9815 #endif
9816
9817
9818 /* Does this version of NetX Duo support TCP keep alive? */
9819 /* Is NetX Duo currently enabled for TCP keep alive? */
9820 #ifdef NX_ENABLE_TCP_KEEPALIVE
9821
9822 nx_bsd_socket_array[secondary_sock_id].nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled =
9823 nx_bsd_socket_array[master_sock_id].nx_bsd_socket_tcp_socket -> nx_tcp_socket_keepalive_enabled;
9824
9825 #endif /* NX_ENABLE_TCP_KEEPALIVE */
9826
9827
9828 return NX_SUCCESS;
9829 }
9830
9831
9832 /**************************************************************************/
9833 /* */
9834 /* FUNCTION RELEASE */
9835 /* */
9836 /* nx_bsd_isspace PORTABLE C */
9837 /* 6.1 */
9838 /* AUTHOR */
9839 /* */
9840 /* Yuxin Zhou, Microsoft Corporation */
9841 /* */
9842 /* DESCRIPTION */
9843 /* */
9844 /* This function determines if the input character is white space */
9845 /* (ascii characters 0x09 - 0x0D or space (0x20). */
9846 /* */
9847 /* INPUT */
9848 /* */
9849 /* c Input character to examine */
9850 /* */
9851 /* OUTPUT */
9852 /* */
9853 /* NX_TRUE Input character is white space */
9854 /* NX_FALSE Input character not white space*/
9855 /* */
9856 /* CALLS */
9857 /* */
9858 /* None */
9859 /* */
9860 /* CALLED BY */
9861 /* */
9862 /* ThreadX */
9863 /* */
9864 /* RELEASE HISTORY */
9865 /* */
9866 /* DATE NAME DESCRIPTION */
9867 /* */
9868 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9869 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9870 /* resulting in version 6.1 */
9871 /* */
9872 /**************************************************************************/
nx_bsd_isspace(UCHAR c)9873 static UINT nx_bsd_isspace(UCHAR c)
9874 {
9875
9876 /* Check for horizontal, vertical tabs, carriage return or formfeed characters. */
9877 if ((c >= 0x09) && (c <= 0x0D))
9878 {
9879 return NX_TRUE;
9880 }
9881 /* Check for a single space character*/
9882 else if (c == 20)
9883 {
9884 return NX_TRUE;
9885 }
9886 else
9887 /* Not a white space character. */
9888 return NX_FALSE;
9889 }
9890
9891
9892 /**************************************************************************/
9893 /* */
9894 /* FUNCTION RELEASE */
9895 /* */
9896 /* nx_bsd_islower PORTABLE C */
9897 /* 6.1 */
9898 /* AUTHOR */
9899 /* */
9900 /* Yuxin Zhou, Microsoft Corporation */
9901 /* */
9902 /* DESCRIPTION */
9903 /* */
9904 /* This function determines if the input character is lower case */
9905 /* alphabetic character. */
9906 /* */
9907 /* INPUT */
9908 /* */
9909 /* c Input character to examine */
9910 /* */
9911 /* OUTPUT */
9912 /* */
9913 /* NX_TRUE Input character is lower case */
9914 /* NX_FALSE Input character not lower case */
9915 /* */
9916 /* CALLS */
9917 /* */
9918 /* None */
9919 /* */
9920 /* CALLED BY */
9921 /* */
9922 /* ThreadX */
9923 /* */
9924 /* RELEASE HISTORY */
9925 /* */
9926 /* DATE NAME DESCRIPTION */
9927 /* */
9928 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9929 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9930 /* resulting in version 6.1 */
9931 /* */
9932 /**************************************************************************/
nx_bsd_islower(UCHAR c)9933 static UINT nx_bsd_islower(UCHAR c)
9934 {
9935
9936 /* Check if characters is any character 'a' through 'z'. */
9937 if ((c >= 0x61) && (c <= 0x7A))
9938 {
9939
9940 return NX_TRUE;
9941 }
9942 else
9943 return NX_FALSE;
9944
9945 }
9946
9947 /**************************************************************************/
9948 /* */
9949 /* FUNCTION RELEASE */
9950 /* */
9951 /* nx_bsd_isdigit PORTABLE C */
9952 /* 6.1 */
9953 /* AUTHOR */
9954 /* */
9955 /* Yuxin Zhou, Microsoft Corporation */
9956 /* */
9957 /* DESCRIPTION */
9958 /* */
9959 /* This function determines if the input character is a digit (0-9) */
9960 /* Does not include hex digits, (see nx_bsd_isxdigit). */
9961 /* */
9962 /* INPUT */
9963 /* */
9964 /* c Input character to examine */
9965 /* */
9966 /* OUTPUT */
9967 /* */
9968 /* NX_TRUE Input character is a digit */
9969 /* NX_FALSE Input character not a digit */
9970 /* */
9971 /* CALLS */
9972 /* */
9973 /* None */
9974 /* */
9975 /* CALLED BY */
9976 /* */
9977 /* ThreadX */
9978 /* */
9979 /* RELEASE HISTORY */
9980 /* */
9981 /* DATE NAME DESCRIPTION */
9982 /* */
9983 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
9984 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
9985 /* resulting in version 6.1 */
9986 /* */
9987 /**************************************************************************/
nx_bsd_isdigit(UCHAR c)9988 static UINT nx_bsd_isdigit(UCHAR c)
9989 {
9990
9991 /* Is the character any digit between 0 and 9? */
9992 if ((c >= 0x30) && (c <= 0x39))
9993 {
9994 return NX_TRUE;
9995 }
9996 else
9997 return NX_FALSE;
9998 }
9999
10000
10001 /**************************************************************************/
10002 /* */
10003 /* FUNCTION RELEASE */
10004 /* */
10005 /* nx_bsd_isxdigit PORTABLE C */
10006 /* 6.1 */
10007 /* AUTHOR */
10008 /* */
10009 /* Yuxin Zhou, Microsoft Corporation */
10010 /* */
10011 /* DESCRIPTION */
10012 /* */
10013 /* This function determines if the input character is a digit (0-9) */
10014 /* or hex digit (A - F, or a-f). For decimal digits, see */
10015 /* nx_bsd_isdigit. */
10016 /* */
10017 /* INPUT */
10018 /* */
10019 /* c Input character to examine */
10020 /* */
10021 /* OUTPUT */
10022 /* */
10023 /* NX_TRUE Input character is hex digit */
10024 /* NX_FALSE Input character not hex digit */
10025 /* */
10026 /* CALLS */
10027 /* */
10028 /* None */
10029 /* */
10030 /* CALLED BY */
10031 /* */
10032 /* ThreadX */
10033 /* */
10034 /* RELEASE HISTORY */
10035 /* */
10036 /* DATE NAME DESCRIPTION */
10037 /* */
10038 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10039 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10040 /* resulting in version 6.1 */
10041 /* */
10042 /**************************************************************************/
nx_bsd_isxdigit(UCHAR c)10043 static UINT nx_bsd_isxdigit(UCHAR c)
10044 {
10045
10046 /* Is the character any digit between 0 - 9? */
10047 if ((c >= 0x30) && (c <= 0x39))
10048 {
10049 return NX_TRUE;
10050 }
10051
10052 /* Or is the character any base 16 digit A-F? */
10053 if ((c >= 0x41) && (c <= 0x46))
10054 {
10055 return NX_TRUE;
10056 }
10057
10058 /* Lastly, check if character is any base 16 digit a-f? */
10059 if ((c >= 0x61) && (c <= 0x66))
10060 {
10061 return NX_TRUE;
10062 }
10063 else
10064 return NX_FALSE;
10065 }
10066
10067 /**************************************************************************/
10068 /* */
10069 /* FUNCTION RELEASE */
10070 /* */
10071 /* set_errno PORTABLE C */
10072 /* 6.3.0 */
10073 /* AUTHOR */
10074 /* */
10075 /* Yuxin Zhou, Microsoft Corporation */
10076 /* */
10077 /* DESCRIPTION */
10078 /* */
10079 /* This function sets the error on the current socket (thread) for */
10080 /* sockets enabled with BSD extended socket options. For sockets not */
10081 /* enabled with extended features, this function has no effect. */
10082 /* */
10083 /* INPUT */
10084 /* */
10085 /* tx_errno Socket error status code */
10086 /* */
10087 /* OUTPUT */
10088 /* */
10089 /* None */
10090 /* */
10091 /* CALLS */
10092 /* */
10093 /* None */
10094 /* */
10095 /* CALLED BY */
10096 /* */
10097 /* ThreadX */
10098 /* */
10099 /* RELEASE HISTORY */
10100 /* */
10101 /* DATE NAME DESCRIPTION */
10102 /* */
10103 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10104 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10105 /* resulting in version 6.1 */
10106 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
10107 /* used new API/structs naming,*/
10108 /* resulting in version 6.3.0 */
10109 /* */
10110 /**************************************************************************/
nx_bsd_set_errno(INT tx_errno)10111 VOID nx_bsd_set_errno(INT tx_errno)
10112 {
10113
10114 TX_INTERRUPT_SAVE_AREA
10115 TX_THREAD *current_thread_ptr;
10116
10117
10118 TX_DISABLE
10119
10120 current_thread_ptr = tx_thread_identify();
10121 current_thread_ptr -> bsd_errno = tx_errno;
10122
10123 TX_RESTORE
10124
10125 return;
10126 }
10127
10128 /**************************************************************************/
10129 /* */
10130 /* FUNCTION RELEASE */
10131 /* */
10132 /* get_errno PORTABLE C */
10133 /* 6.1 */
10134 /* AUTHOR */
10135 /* */
10136 /* Yuxin Zhou, Microsoft Corporation */
10137 /* */
10138 /* DESCRIPTION */
10139 /* */
10140 /* This function retrieves the error on the current socket (thread) for*/
10141 /* sockets enabled with BSD extended socket options. For sockets not */
10142 /* enabled with extended features, this function has no effect. */
10143 /* */
10144 /* INPUT */
10145 /* */
10146 /* None */
10147 /* */
10148 /* OUTPUT */
10149 /* */
10150 /* Socket error status code */
10151 /* */
10152 /* CALLS */
10153 /* */
10154 /* None */
10155 /* */
10156 /* CALLED BY */
10157 /* */
10158 /* ThreadX */
10159 /* */
10160 /* RELEASE HISTORY */
10161 /* */
10162 /* DATE NAME DESCRIPTION */
10163 /* */
10164 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10165 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10166 /* resulting in version 6.1 */
10167 /* */
10168 /**************************************************************************/
_nxd_get_errno()10169 INT _nxd_get_errno()
10170 {
10171
10172 TX_INTERRUPT_SAVE_AREA
10173 INT val;
10174 TX_THREAD *current_thread_ptr;
10175
10176
10177 TX_DISABLE
10178
10179 current_thread_ptr = tx_thread_identify();
10180 val = current_thread_ptr -> bsd_errno;
10181
10182 TX_RESTORE
10183
10184 return (val);
10185 }
10186
10187
10188 /**************************************************************************/
10189 /* */
10190 /* FUNCTION RELEASE */
10191 /* */
10192 /* nx_bsd_select_wakeup PORTABLE C */
10193 /* 6.3.0 */
10194 /* AUTHOR */
10195 /* */
10196 /* Yuxin Zhou, Microsoft Corporation */
10197 /* */
10198 /* DESCRIPTION */
10199 /* */
10200 /* This function checks the suspend list for a given socket being */
10201 /* readable or writeable. */
10202 /* */
10203 /* INPUT */
10204 /* */
10205 /* sock_id BSD socket ID */
10206 /* fd_sets The FD set to check */
10207 /* */
10208 /* OUTPUT */
10209 /* */
10210 /* None */
10211 /* */
10212 /* CALLS */
10213 /* */
10214 /* FD_ZERO Zeros out an FD Set */
10215 /* FD_SET Set a socket in the FDSET */
10216 /* TX_DISABLE Disable Interrupt */
10217 /* TX_RESTORE Enable Interrupt */
10218 /* tx_event_flags_set Set an event flag */
10219 /* */
10220 /* CALLED BY */
10221 /* */
10222 /* nx_bsd_timeout_process */
10223 /* nx_bsd_tcp_receive_notify */
10224 /* nx_bsd_tcp_establish_notify */
10225 /* nx_bsd_tcp_socket_disconnect_notify */
10226 /* nx_bsd_raw_receive_notify */
10227 /* nx_bsd_udp_packet_received */
10228 /* */
10229 /* RELEASE HISTORY */
10230 /* */
10231 /* DATE NAME DESCRIPTION */
10232 /* */
10233 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10234 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10235 /* resulting in version 6.1 */
10236 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
10237 /* used new API/structs naming,*/
10238 /* resulting in version 6.3.0 */
10239 /* */
10240 /**************************************************************************/
nx_bsd_select_wakeup(UINT sock_id,UINT fd_sets)10241 static VOID nx_bsd_select_wakeup(UINT sock_id, UINT fd_sets)
10242 {
10243 TX_INTERRUPT_SAVE_AREA
10244 nx_bsd_fd_set local_fd;
10245 TX_THREAD *suspended_thread;
10246 ULONG suspended_count;
10247 ULONG original_suspended_count;
10248 NX_BSD_SOCKET_SUSPEND *suspend_info;
10249
10250
10251 /* At this point the thread should NOT own the IP mutex, and it must own the
10252 BSD mutex. */
10253
10254
10255 NX_BSD_FD_ZERO(&local_fd);
10256 NX_BSD_FD_SET((INT)sock_id + NX_BSD_SOCKFD_START, &local_fd);
10257
10258 /* Disable interrupts temporarily. */
10259 TX_DISABLE
10260
10261 /* Setup the head pointer and the count. */
10262 suspended_thread = nx_bsd_events.tx_event_flags_group_suspension_list;
10263 suspended_count = nx_bsd_events.tx_event_flags_group_suspended_count;
10264
10265 /* Save the original suspended count. */
10266 original_suspended_count = suspended_count;
10267
10268 /* Loop to examine all threads suspended on select via the BSD event flag group. */
10269 while (suspended_count--)
10270 {
10271
10272 /* Determine if this thread is suspended on select. */
10273 if (suspended_thread -> tx_thread_suspend_info == NX_BSD_SELECT_EVENT)
10274 {
10275
10276 /* Yes, this thread is suspended on select. */
10277
10278 /* Pickup a pointer to its select suspend structure. */
10279 suspend_info = (NX_BSD_SOCKET_SUSPEND *) suspended_thread -> tx_thread_additional_suspend_info;
10280
10281 /* Now determine if this thread was waiting for this socket. */
10282 if ((fd_sets & FDSET_READ) && (NX_BSD_FD_ISSET((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_read_fd_set)))
10283 {
10284
10285 /* Copy the local fd over so that the return shows the receive socket. */
10286 suspend_info -> nx_bsd_socket_suspend_read_fd_set = local_fd;
10287
10288 /* Adjust the suspension type so that the event flag set below will wakeup the thread
10289 selecting. */
10290 suspended_thread -> tx_thread_suspend_info = NX_BSD_RECEIVE_EVENT;
10291 }
10292
10293 /* Now determine if this thread was waiting for this socket. */
10294 if ((fd_sets & FDSET_WRITE) && (NX_BSD_FD_ISSET((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_write_fd_set)))
10295 {
10296
10297 /* Copy the local fd over so that the return shows the receive socket. */
10298 suspend_info -> nx_bsd_socket_suspend_write_fd_set = local_fd;
10299
10300 /* Adjust the suspension type so that the event flag set below will wakeup the thread
10301 selecting. */
10302 suspended_thread -> tx_thread_suspend_info = NX_BSD_RECEIVE_EVENT;
10303 }
10304
10305 /* Now determine if this thread was waiting for this socket. */
10306 if ((fd_sets & FDSET_EXCEPTION) && (NX_BSD_FD_ISSET((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_exception_fd_set)))
10307 {
10308
10309 /* Copy the local fd over so that the return shows the receive socket. */
10310 suspend_info -> nx_bsd_socket_suspend_exception_fd_set = local_fd;
10311
10312 /* Adjust the suspension type so that the event flag set below will wakeup the thread
10313 selecting. */
10314 suspended_thread -> tx_thread_suspend_info = NX_BSD_RECEIVE_EVENT;
10315 }
10316
10317 /* Clear FD that is not set. */
10318 if (suspended_thread -> tx_thread_suspend_info == NX_BSD_RECEIVE_EVENT)
10319 {
10320 if (!(fd_sets & FDSET_READ) && (NX_BSD_FD_ISSET((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_read_fd_set)))
10321 {
10322
10323 /* Clear read FD. */
10324 NX_BSD_FD_CLR((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_read_fd_set);
10325 }
10326
10327 if (!(fd_sets & FDSET_WRITE) && (NX_BSD_FD_ISSET((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_write_fd_set)))
10328 {
10329
10330 /* Clear write FD. */
10331 NX_BSD_FD_CLR((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_write_fd_set);
10332 }
10333
10334 if (!(fd_sets & FDSET_EXCEPTION) && (NX_BSD_FD_ISSET((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_exception_fd_set)))
10335 {
10336
10337 /* Clear exception FD. */
10338 NX_BSD_FD_CLR((INT)sock_id + NX_BSD_SOCKFD_START, &suspend_info -> nx_bsd_socket_suspend_exception_fd_set);
10339 }
10340 }
10341 }
10342
10343 /* Now move to the next event. */
10344 suspended_thread = suspended_thread -> tx_thread_suspended_next;
10345
10346 /* Restore interrupts. */
10347 TX_RESTORE
10348
10349 /* Disable interrupts again. */
10350 TX_DISABLE
10351
10352 /* Determine if something changes on the suspension list... this could have happened if there
10353 was a timeout or a wait abort on the thread. */
10354 if (original_suspended_count != nx_bsd_events.tx_event_flags_group_suspended_count)
10355 {
10356
10357 /* Something changed, so simply restart the search. */
10358
10359 /* Setup the head pointer and the count. */
10360 suspended_thread = nx_bsd_events.tx_event_flags_group_suspension_list;
10361 suspended_count = nx_bsd_events.tx_event_flags_group_suspended_count;
10362
10363 /* Save the original suspended count. */
10364 original_suspended_count = suspended_count;
10365 }
10366 }
10367
10368 /* Restore interrupts. */
10369 TX_RESTORE
10370
10371 /* Wakeup all threads that are attempting to perform a receive or that had their select satisfied. */
10372 tx_event_flags_set(&nx_bsd_events, NX_BSD_RECEIVE_EVENT, TX_OR);
10373
10374 return;
10375
10376 }
10377
10378 /**************************************************************************/
10379 /* */
10380 /* FUNCTION RELEASE */
10381 /* */
10382 /* nx_bsd_set_error_code PORTABLE C */
10383 /* 6.3.0 */
10384 /* AUTHOR */
10385 /* */
10386 /* Yuxin Zhou, Microsoft Corporation */
10387 /* */
10388 /* DESCRIPTION */
10389 /* */
10390 /* This is sets the BSD error code based on NetX Duo API return code */
10391 /* */
10392 /* INPUT */
10393 /* */
10394 /* bsd_socket_ptr Pointer to the BSD socket */
10395 /* status_code NetX Duo API return code */
10396 /* */
10397 /* OUTPUT */
10398 /* */
10399 /* None */
10400 /* */
10401 /* CALLS */
10402 /* */
10403 /* set_errno Sets the BSD errno */
10404 /* */
10405 /* CALLED BY */
10406 /* */
10407 /* connect */
10408 /* bind */
10409 /* */
10410 /* RELEASE HISTORY */
10411 /* */
10412 /* DATE NAME DESCRIPTION */
10413 /* */
10414 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10415 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10416 /* resulting in version 6.1 */
10417 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
10418 /* used new API/structs naming,*/
10419 /* resulting in version 6.3.0 */
10420 /* */
10421 /**************************************************************************/
nx_bsd_set_error_code(NX_BSD_SOCKET * bsd_socket_ptr,UINT status_code)10422 static VOID nx_bsd_set_error_code(NX_BSD_SOCKET *bsd_socket_ptr, UINT status_code)
10423 {
10424 switch(status_code)
10425 {
10426 case NX_NOT_CLOSED:
10427 /* TCP connection is not closed state. */
10428 nx_bsd_set_errno(EISCONN);
10429 break;
10430
10431 case NX_PTR_ERROR:
10432 case NX_INVALID_PORT:
10433 /* Invalid arguement. */
10434 nx_bsd_set_errno(EINVAL);
10435 break;
10436
10437 case NX_MAX_LISTEN:
10438 nx_bsd_set_errno(ENOBUFS);
10439 break;
10440
10441 case NX_PORT_UNAVAILABLE:
10442 case NX_NO_FREE_PORTS:
10443 nx_bsd_set_errno(EADDRNOTAVAIL);
10444 break;
10445
10446 case NX_ALREADY_BOUND:
10447 nx_bsd_set_errno(EINVAL);
10448 break;
10449
10450 case NX_WAIT_ABORTED:
10451 nx_bsd_set_errno(ETIMEDOUT);
10452 break;
10453
10454 case NX_NOT_CONNECTED:
10455 /* NX TCP connect service may return NX_NOT_CONNECTED if the timeout is WAIT_FOREVER. */
10456 nx_bsd_set_errno(ECONNREFUSED);
10457 break;
10458
10459 case NX_IN_PROGRESS:
10460 /* The NetX "in progress" status is the equivalent of the non blocking BSD socket waiting
10461 to connect. This can only happen if timeout is NX_NO_WAIT.*/
10462 if (bsd_socket_ptr -> nx_bsd_socket_option_flags & NX_BSD_SOCKET_ENABLE_OPTION_NON_BLOCKING)
10463 {
10464 bsd_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
10465 nx_bsd_set_errno(EINPROGRESS);
10466 }
10467 else
10468 nx_bsd_set_errno(EINTR);
10469 break;
10470
10471 case NX_INVALID_INTERFACE:
10472 case NX_IP_ADDRESS_ERROR:
10473 nx_bsd_set_errno(ENETUNREACH);
10474 break;
10475
10476 case NX_NOT_ENABLED:
10477 nx_bsd_set_errno(EPROTONOSUPPORT);
10478 break;
10479
10480 case NX_NOT_BOUND:
10481 case NX_DUPLICATE_LISTEN:
10482 default:
10483 nx_bsd_set_errno(EINVAL);
10484 break;
10485 }
10486
10487 return;
10488 }
10489
10490 /**************************************************************************/
10491 /* */
10492 /* FUNCTION RELEASE */
10493 /* */
10494 /* nx_bsd_udp_packet_received PORTABLE C */
10495 /* 6.1 */
10496 /* AUTHOR */
10497 /* */
10498 /* Yuxin Zhou, Microsoft Corporation */
10499 /* */
10500 /* DESCRIPTION */
10501 /* */
10502 /* This is executed as part of the UDP packet receive callback */
10503 /* function. */
10504 /* */
10505 /* This routine puts an incoming UDP packet into the appropriate */
10506 /* UDP BSD socket, taking into consideration that multiple BSD sockets */
10507 /* may be mapped to the same NetX Duo UDP socket. */
10508 /* */
10509 /* INPUT */
10510 /* */
10511 /* sockID The BSD socket descriptor */
10512 /* packet_ptr The incoming UDP packet */
10513 /* */
10514 /* OUTPUT */
10515 /* */
10516 /* None */
10517 /* */
10518 /* CALLS */
10519 /* */
10520 /* nx_packet_release Release a packet that is not */
10521 /* received by any sockets. */
10522 /* nx_bsd_select_wakeup Wake up any asychronous */
10523 /* receive call */
10524 /* */
10525 /* CALLED BY */
10526 /* */
10527 /* nx_bsd_udp_receive_notify */
10528 /* */
10529 /* RELEASE HISTORY */
10530 /* */
10531 /* DATE NAME DESCRIPTION */
10532 /* */
10533 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10534 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10535 /* resulting in version 6.1 */
10536 /* */
10537 /**************************************************************************/
nx_bsd_udp_packet_received(INT sockID,NX_PACKET * packet_ptr)10538 static VOID nx_bsd_udp_packet_received(INT sockID, NX_PACKET *packet_ptr)
10539 {
10540
10541 NX_BSD_SOCKET *bsd_ptr;
10542 ULONG addr_family;
10543 NX_BSD_SOCKET *exact_match = NX_NULL;
10544 NX_BSD_SOCKET *receiver_match = NX_NULL;
10545 NX_BSD_SOCKET *wildcard_match = NX_NULL;
10546 NX_INTERFACE *interface_ptr;
10547
10548
10549 bsd_ptr = &nx_bsd_socket_array[sockID];
10550
10551 #ifndef NX_DISABLE_IPV4
10552 if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
10553 {
10554 addr_family = AF_INET;
10555 interface_ptr = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
10556 }
10557 else
10558 #endif /* NX_DISABLE_IPV4 */
10559 #ifdef FEATURE_NX_IPV6
10560 if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
10561 {
10562 addr_family = AF_INET6;
10563 interface_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
10564 }
10565 else
10566 #endif /* FEATURE_NX_IPV6 */
10567 {
10568
10569 /* Invalid version. Release the packet and return. */
10570 nx_packet_release(packet_ptr);
10571
10572 return;
10573 }
10574
10575 /* Start the search for the BSD socket we received this packet on from current input socket ID. */
10576 bsd_ptr = &nx_bsd_socket_array[sockID];
10577
10578 do
10579 {
10580 /* Skip the sockets with different address family. */
10581 if(bsd_ptr -> nx_bsd_socket_family == addr_family)
10582 {
10583 /* bsd_ptr points to a related UDP socket. */
10584 if(bsd_ptr -> nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
10585 {
10586 wildcard_match = bsd_ptr;
10587 }
10588 else if(((ULONG)(interface_ptr) == bsd_ptr -> nx_bsd_socket_local_bind_interface) ||
10589 ((ULONG)(packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr) == bsd_ptr -> nx_bsd_socket_local_bind_interface))
10590 {
10591
10592 receiver_match = bsd_ptr;
10593 }
10594 else
10595 {
10596
10597 /* Does not match the local interface. Move to the next entry. */
10598 bsd_ptr = bsd_ptr -> nx_bsd_socket_next;
10599 continue;
10600 }
10601
10602 /* At this point this socket is either a wildcard match or a receiver match. */
10603
10604 /* If the socket is connected, we check for sender's address match. */
10605 if(bsd_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED)
10606 {
10607
10608 nxd_udp_source_extract(packet_ptr,
10609 &bsd_ptr -> nx_bsd_socket_source_ip_address,
10610 (UINT *)&bsd_ptr -> nx_bsd_socket_source_port);
10611
10612 #ifndef NX_DISABLE_IPV4
10613 if(bsd_ptr -> nx_bsd_socket_family == AF_INET)
10614 {
10615
10616 /* Now we can check for an exact match based on sender IP address and port. */
10617 if((bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v4 ==
10618 bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v4) &&
10619 (bsd_ptr -> nx_bsd_socket_source_port ==
10620 bsd_ptr -> nx_bsd_socket_peer_port))
10621 {
10622 exact_match = bsd_ptr;
10623 }
10624 }
10625 #endif /* NX_DISABLE_IPV4 */
10626 #ifdef FEATURE_NX_IPV6
10627 if(bsd_ptr -> nx_bsd_socket_family == AF_INET6)
10628 {
10629
10630 /* Now we can check for an exact match based on sender IP address and port. */
10631 if((bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[0] ==
10632 bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[0]) &&
10633 (bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[1] ==
10634 bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[1]) &&
10635 (bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[2] ==
10636 bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[2]) &&
10637 (bsd_ptr -> nx_bsd_socket_source_ip_address.nxd_ip_address.v6[3] ==
10638 bsd_ptr -> nx_bsd_socket_peer_ip.nxd_ip_address.v6[3]) &&
10639 (bsd_ptr -> nx_bsd_socket_source_port ==
10640 bsd_ptr -> nx_bsd_socket_peer_port))
10641 {
10642
10643 exact_match = bsd_ptr;
10644 }
10645 }
10646 #endif
10647
10648 if(exact_match != NX_NULL)
10649 break;
10650
10651 if(receiver_match != NX_NULL)
10652 receiver_match = NX_NULL;
10653
10654 if(wildcard_match != NX_NULL)
10655 wildcard_match = NX_NULL;
10656 }
10657 }
10658
10659 /* Move to the next entry. */
10660 bsd_ptr = bsd_ptr -> nx_bsd_socket_next;
10661
10662 }while(bsd_ptr != &nx_bsd_socket_array[sockID]);
10663
10664 /* Let bsd_ptr point to the matched socket. */
10665 if(exact_match != NX_NULL)
10666 bsd_ptr = exact_match;
10667 else if(receiver_match != NX_NULL)
10668 bsd_ptr = receiver_match;
10669 else if(wildcard_match != NX_NULL)
10670 bsd_ptr = wildcard_match;
10671 else
10672 {
10673 /* This packet is not for any of the BSD sockets. Release the packet and we are done. */
10674 nx_packet_release(packet_ptr);
10675
10676 return;
10677 }
10678
10679 /* Move the packet to the socket internal receive queue. */
10680
10681 if(bsd_ptr -> nx_bsd_socket_received_byte_count_max &&
10682 (bsd_ptr -> nx_bsd_socket_received_byte_count >= bsd_ptr -> nx_bsd_socket_received_byte_count_max))
10683 {
10684
10685 /* Receive buffer is full. Release the packet and return. */
10686 nx_packet_release(packet_ptr);
10687
10688 return;
10689 }
10690
10691 /* Drop the packet if the receive queue exceeds max depth.*/
10692 if(bsd_ptr -> nx_bsd_socket_received_packet_count >=
10693 bsd_ptr -> nx_bsd_socket_received_packet_count_max)
10694 {
10695
10696 /* Receive buffer is full. Release the packet and return. */
10697 nx_packet_release(packet_ptr);
10698
10699 return;
10700 }
10701 if(bsd_ptr -> nx_bsd_socket_received_packet)
10702 {
10703 bsd_ptr -> nx_bsd_socket_received_packet_tail -> nx_packet_queue_next = packet_ptr;
10704 }
10705 else
10706 {
10707
10708 bsd_ptr -> nx_bsd_socket_received_packet = packet_ptr;
10709 bsd_ptr -> nx_bsd_socket_received_packet_offset = 0;
10710 }
10711
10712 bsd_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
10713 bsd_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
10714 bsd_ptr -> nx_bsd_socket_received_packet_count++;
10715
10716 nx_bsd_select_wakeup((UINT)(bsd_ptr -> nx_bsd_socket_id), FDSET_READ);
10717
10718 return;
10719 }
10720
10721 /**************************************************************************/
10722 /* */
10723 /* FUNCTION RELEASE */
10724 /* */
10725 /* nx_bsd_tcp_syn_received_notify PORTABLE C */
10726 /* 6.1 */
10727 /* AUTHOR */
10728 /* */
10729 /* Yuxin Zhou, Microsoft Corporation */
10730 /* */
10731 /* DESCRIPTION */
10732 /* */
10733 /* This function checks if the socket has a connection request. */
10734 /* */
10735 /* INPUT */
10736 /* */
10737 /* socket_ptr Socket receiving the packet */
10738 /* packet_ptr Pointer to the received packet */
10739 /* */
10740 /* OUTPUT */
10741 /* */
10742 /* 0 Not a valid match */
10743 /* 1 Valid match found */
10744 /* */
10745 /* CALLS */
10746 /* */
10747 /* None */
10748 /* */
10749 /* CALLED BY */
10750 /* */
10751 /* NetX Duo */
10752 /* */
10753 /* RELEASE HISTORY */
10754 /* */
10755 /* DATE NAME DESCRIPTION */
10756 /* */
10757 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10758 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10759 /* resulting in version 6.1 */
10760 /* */
10761 /**************************************************************************/
nx_bsd_tcp_syn_received_notify(NX_TCP_SOCKET * socket_ptr,NX_PACKET * packet_ptr)10762 static UINT nx_bsd_tcp_syn_received_notify(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr)
10763 {
10764
10765 UINT bsd_socket_index;
10766 INT i;
10767 INT sockID_find;
10768 ULONG addr_family;
10769 INT search_index;
10770 INT receiver_match = NX_BSD_MAX_SOCKETS;
10771 INT wildcard_match = NX_BSD_MAX_SOCKETS;
10772 NX_BSD_SOCKET *bsd_socket_ptr;
10773 NX_INTERFACE *interface_ptr;
10774
10775
10776 bsd_socket_index = (UINT)socket_ptr -> nx_tcp_socket_reserved_ptr;
10777
10778 if(bsd_socket_index >= NX_BSD_MAX_SOCKETS)
10779 {
10780
10781 /* Bad socket index... simply return! */
10782 return(NX_FALSE);
10783 }
10784
10785 nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
10786
10787 #ifndef NX_DISABLE_IPV4
10788 if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
10789 {
10790 addr_family = AF_INET;
10791 }
10792 else
10793 #endif /* NX_DISABLE_IPV4 */
10794 {
10795 addr_family = AF_INET6;
10796 }
10797
10798 /* Start the search at the position of the input socket. */
10799 search_index = (INT)bsd_socket_index;
10800
10801 /* Get the packet interface. */
10802 #ifdef FEATURE_NX_IPV6
10803 if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4)
10804 #endif /* FEATURE_NX_IPV6 */
10805 interface_ptr = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
10806 #ifdef FEATURE_NX_IPV6
10807 else if(packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6)
10808 interface_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
10809 else
10810 return (NX_FALSE);
10811 #endif /* FEATURE_NX_IPV6 */
10812
10813 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
10814 {
10815
10816 bsd_socket_ptr = &nx_bsd_socket_array[search_index];
10817
10818 /* Skip the unrelated sockets. */
10819 if((bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP) &&
10820 (bsd_socket_ptr -> nx_bsd_socket_family == addr_family) &&
10821 ((bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CONNECTED) == 0) &&
10822 (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) &&
10823 (bsd_socket_ptr -> nx_bsd_socket_local_port == socket_ptr -> nx_tcp_socket_port) &&
10824 (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE))
10825 {
10826
10827 if(bsd_socket_ptr -> nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY)
10828 {
10829
10830 wildcard_match = search_index;
10831 }
10832 else if(((ULONG)(interface_ptr) == bsd_socket_ptr -> nx_bsd_socket_local_bind_interface) ||
10833 ((ULONG)(packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr) == bsd_socket_ptr -> nx_bsd_socket_local_bind_interface))
10834 {
10835
10836 receiver_match = search_index;
10837
10838 /* Found a receiver match, which is a tighter match than the wildcard match.
10839 So we can get out of the loop. */
10840 break;
10841 }
10842 }
10843
10844 /* Move to the next entry. */
10845 search_index++;
10846
10847 if(search_index >= NX_BSD_MAX_SOCKETS)
10848 search_index = 0;
10849 }
10850
10851 if(receiver_match != NX_BSD_MAX_SOCKETS)
10852 sockID_find = receiver_match;
10853 else if(wildcard_match != NX_BSD_MAX_SOCKETS)
10854 sockID_find = wildcard_match;
10855 else
10856 {
10857
10858 /* No match found. Simply return .*/
10859 return(NX_FALSE);
10860 }
10861
10862 /* Found the listening master socket. Update the master socket ID of the input socket. */
10863 nx_bsd_socket_array[bsd_socket_index].nx_bsd_socket_union_id.nx_bsd_socket_master_socket_id = sockID_find;
10864
10865 return(NX_TRUE);
10866 }
10867
10868 /**************************************************************************/
10869 /* */
10870 /* FUNCTION RELEASE */
10871 /* */
10872 /* nx_bsd_tcp_create_listen_socket PORTABLE C */
10873 /* 6.3.0 */
10874 /* AUTHOR */
10875 /* */
10876 /* Yuxin Zhou, Microsoft Corporation */
10877 /* */
10878 /* DESCRIPTION */
10879 /* */
10880 /* This routine sets up the input socket as a listen socket. */
10881 /* */
10882 /* INPUT */
10883 /* */
10884 /* master_sockid Index to the master socket */
10885 /* backlog Size of the socket listen queue*/
10886 /* */
10887 /* OUTPUT */
10888 /* */
10889 /* NX_SOC_OK Successfully set up socket */
10890 /* NX_SOC_ERROR Error setting up the socket */
10891 /* */
10892 /* CALLS */
10893 /* */
10894 /* socket Allocate a BSD socket */
10895 /* nx_bsd_socket_set_inherited_settings Apply master socket options */
10896 /* nx_tcp_server_socket_listen Enable the socket to listen **/
10897 /* nx_tcp_server_socket_accept Wait for connection request */
10898 /* nx_tcp_server_socket_relisten Reset the socket to listen */
10899 /* */
10900 /* CALLED BY */
10901 /* */
10902 /* NetX Duo */
10903 /* */
10904 /* RELEASE HISTORY */
10905 /* */
10906 /* DATE NAME DESCRIPTION */
10907 /* */
10908 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
10909 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
10910 /* resulting in version 6.1 */
10911 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
10912 /* used new API/structs naming,*/
10913 /* resulting in version 6.3.0 */
10914 /* */
10915 /**************************************************************************/
nx_bsd_tcp_create_listen_socket(INT master_sockid,INT backlog)10916 static INT nx_bsd_tcp_create_listen_socket(INT master_sockid, INT backlog)
10917 {
10918
10919 INT i;
10920 UINT status;
10921 UINT local_port;
10922 NX_BSD_SOCKET *master_socket_ptr = &nx_bsd_socket_array[master_sockid];
10923 NX_BSD_SOCKET *bsd_secondary_socket;
10924 NX_BSD_SOCKET *bsd_socket_ptr;
10925 NX_TCP_SOCKET *sec_socket_ptr;
10926 INT secondary_sockID = NX_BSD_MAX_SOCKETS;
10927
10928
10929 /* This is called from BSD internal code so the BSD mutex is obtained. */
10930
10931 /* Search through the sockets to find a master socket that is listening on the same port. */
10932 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
10933 {
10934
10935 /* Skip the entry if it is not master socket */
10936 if((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) == 0)
10937 continue;
10938
10939 /* Skip the current master socket. */
10940 if(i == master_sockid)
10941 continue;
10942
10943 /* Skip the entry if it is not TCP */
10944 if(nx_bsd_socket_array[i].nx_bsd_socket_protocol != NX_PROTOCOL_TCP)
10945 continue;
10946
10947 /* Skip the entry if the the secondary socket id field is not valid. */
10948 if(nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id == NX_BSD_MAX_SOCKETS)
10949 continue;
10950
10951 /* Check if another master socket is listening on the same port. */
10952 if((nx_bsd_socket_array[i].nx_bsd_socket_local_port == master_socket_ptr -> nx_bsd_socket_local_port) &&
10953 (nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id
10954 != (master_socket_ptr -> nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id)) &&
10955 (nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN))
10956 {
10957
10958 /* This one is. Point to the same secondary socket. */
10959 (master_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id =
10960 nx_bsd_socket_array[i].nx_bsd_socket_union_id.nx_bsd_socket_secondary_socket_id;
10961 master_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ENABLE_LISTEN;
10962 master_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET);
10963 master_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_client_type = NX_FALSE;
10964 master_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_SERVER_MASTER_SOCKET;
10965
10966 return(NX_SOC_OK);
10967 }
10968 }
10969
10970 /* Did not find an existing master socket for listening. */
10971
10972 /* Check for a valid backlog. */
10973 if(backlog)
10974 {
10975
10976 /* Check backlog argument is within limits. */
10977 if (backlog > NX_BSD_MAX_LISTEN_BACKLOG)
10978 {
10979
10980 /* Error, invalid backlog. */
10981 /* Set the socket error if extended socket options enabled. */
10982 nx_bsd_set_errno(ENOBUFS);
10983
10984 /* Return error code. */
10985 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
10986 return(NX_SOC_ERROR);
10987 }
10988 }
10989
10990 /* Now create a dedicated secondary socket to listen for next client connection. */
10991 secondary_sockID = nx_bsd_socket((INT)(master_socket_ptr -> nx_bsd_socket_family), SOCK_STREAM, IPPROTO_TCP);
10992
10993 /* Determine if there was an error. */
10994 if (secondary_sockID == NX_SOC_ERROR)
10995 {
10996
10997 /* Secondary socket create failed. Note: The socket thread error is set in socket(). */
10998 nx_bsd_set_errno(ENOMEM);
10999
11000 /* Return error code. */
11001 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
11002 return(NX_SOC_ERROR);
11003 }
11004
11005 /* Adjust the secondary socket ID. */
11006 secondary_sockID = secondary_sockID - NX_BSD_SOCKFD_START;
11007
11008 /* The master server socket will never connect to a client! For each successful
11009 client connection there will be a new secondary server socket and
11010 each such socket is associated with this master server socket. This is
11011 the difference between NetX and BSD sockets. The NetX listen() service is used
11012 with this secondary server socket. */
11013
11014 /* Set a pointer to the secondary socket. */
11015 bsd_secondary_socket = &nx_bsd_socket_array[secondary_sockID];
11016
11017 /* Apply the master socket options to the secondary socket. */
11018 nx_bsd_socket_set_inherited_settings((UINT)master_sockid, (UINT)secondary_sockID);
11019
11020 local_port = master_socket_ptr -> nx_bsd_socket_local_port;
11021
11022 /* Invalidate the secondary master socket ID. */
11023 (bsd_secondary_socket -> nx_bsd_socket_union_id).nx_bsd_socket_master_socket_id = NX_BSD_MAX_SOCKETS;
11024
11025 /* Now call listen for the secondary server socket. */
11026 if(backlog)
11027 status = nx_tcp_server_socket_listen(nx_bsd_default_ip, local_port, bsd_secondary_socket -> nx_bsd_socket_tcp_socket, (UINT)backlog, NX_NULL);
11028 else
11029 {
11030
11031 /* Since a zero backlog is specified, this secondary socket needs to share with another master socket. */
11032 bsd_secondary_socket -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_port = local_port;
11033
11034 /* Check if a listen request is queued up for this socket. */
11035 nx_bsd_tcp_pending_connection(local_port, bsd_secondary_socket -> nx_bsd_socket_tcp_socket);
11036
11037 status = nx_tcp_server_socket_relisten(nx_bsd_default_ip, local_port, bsd_secondary_socket -> nx_bsd_socket_tcp_socket);
11038 }
11039
11040 /* Check for an error. */
11041 if ((status != NX_SUCCESS) && (status != NX_CONNECTION_PENDING))
11042 {
11043
11044 /* Error, listen or relisten failed. */
11045
11046 /* Set the socket error depending on the NetX error status returned. */
11047 nx_bsd_set_error_code(master_socket_ptr, status);
11048
11049 /* Return error code. */
11050 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
11051 return(NX_SOC_ERROR);
11052 }
11053
11054 /* Now mark this as a master server socket listening to client connections. */
11055 master_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ENABLE_LISTEN;
11056 master_socket_ptr -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET);
11057 master_socket_ptr -> nx_bsd_socket_tcp_socket -> nx_tcp_socket_client_type = NX_FALSE;
11058 master_socket_ptr -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_SERVER_MASTER_SOCKET;
11059
11060 /* This is a master socket. So we use the nx_bsd_socket_master_socket_id field to
11061 record the secondary socket that is doing the real listen/accept work. */
11062 (master_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = secondary_sockID;
11063
11064 /* Mark the secondary server socket as assigned to this master server socket. */
11065 bsd_secondary_socket -> nx_bsd_socket_status_flags &= (ULONG)(~NX_BSD_SOCKET_ACCEPTING);
11066 bsd_secondary_socket -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_SERVER_SECONDARY_SOCKET;
11067 bsd_secondary_socket -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_ENABLE_LISTEN;
11068 bsd_secondary_socket -> nx_bsd_socket_local_port = (USHORT)local_port;
11069
11070 /* If the master server socket is marked as non-blocking, we need to
11071 start the NetX accept process here. */
11072
11073 sec_socket_ptr = bsd_secondary_socket -> nx_bsd_socket_tcp_socket;
11074
11075 /* Allow accept from remote. */
11076 nx_tcp_server_socket_accept(sec_socket_ptr, 0);
11077
11078 /* Set the master socket of other BSD TCP sockets that bind to the same port to the same secondary socket. */
11079 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
11080 {
11081
11082 bsd_socket_ptr = &nx_bsd_socket_array[i];
11083
11084 if((bsd_socket_ptr -> nx_bsd_socket_protocol == NX_PROTOCOL_TCP) &&
11085 (!(bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_CLIENT)) &&
11086 (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_SERVER_MASTER_SOCKET) &&
11087 (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_ENABLE_LISTEN) &&
11088 (bsd_socket_ptr -> nx_bsd_socket_status_flags & NX_BSD_SOCKET_BOUND) &&
11089 (bsd_socket_ptr -> nx_bsd_socket_local_port == local_port))
11090 {
11091
11092 (bsd_socket_ptr -> nx_bsd_socket_union_id).nx_bsd_socket_secondary_socket_id = secondary_sockID;
11093 }
11094 }
11095
11096 /* Check the relisten/listen status. */
11097 if(status == NX_CONNECTION_PENDING)
11098 {
11099
11100 /* Set the connection pending flag. */
11101 bsd_secondary_socket -> nx_bsd_socket_status_flags |= NX_BSD_SOCKET_CONNECTION_INPROGRESS;
11102
11103 }
11104
11105 return(NX_SOC_OK);
11106 }
11107
11108 /**************************************************************************/
11109 /* */
11110 /* FUNCTION RELEASE */
11111 /* */
11112 /* nx_bsd_tcp_pending_connection PORTABLE C */
11113 /* 6.1 */
11114 /* AUTHOR */
11115 /* */
11116 /* Yuxin Zhou, Microsoft Corporation */
11117 /* */
11118 /* DESCRIPTION */
11119 /* */
11120 /* This routine checks if the BSD TCP socket has a listen request */
11121 /* queued up on in the specified port. */
11122 /* */
11123 /* INPUT */
11124 /* */
11125 /* local_port Listening port */
11126 /* socket_ptr Socket to check */
11127 /* */
11128 /* OUTPUT */
11129 /* */
11130 /* None */
11131 /* */
11132 /* CALLS */
11133 /* */
11134 /* nx_bsd_tcp_syn_received_notify Match connection request */
11135 /* (packet) to input socket */
11136 /* nx_packet_receive Release packet to packet pool */
11137 /* */
11138 /* CALLED BY */
11139 /* */
11140 /* NetX Duo */
11141 /* */
11142 /* RELEASE HISTORY */
11143 /* */
11144 /* DATE NAME DESCRIPTION */
11145 /* */
11146 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11147 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
11148 /* resulting in version 6.1 */
11149 /* */
11150 /**************************************************************************/
nx_bsd_tcp_pending_connection(UINT local_port,NX_TCP_SOCKET * socket_ptr)11151 static VOID nx_bsd_tcp_pending_connection(UINT local_port, NX_TCP_SOCKET *socket_ptr)
11152 {
11153
11154 struct NX_TCP_LISTEN_STRUCT *listen_ptr;
11155 NX_PACKET *packet_ptr;
11156 NX_TCP_HEADER *tcp_header_ptr;
11157 UINT ret;
11158
11159
11160 listen_ptr = nx_bsd_default_ip -> nx_ip_tcp_active_listen_requests;
11161
11162 if(listen_ptr)
11163 {
11164
11165 do
11166 {
11167
11168 if((listen_ptr -> nx_tcp_listen_port == local_port) &&
11169 (listen_ptr -> nx_tcp_listen_queue_current))
11170 {
11171
11172 do
11173 {
11174
11175 packet_ptr = listen_ptr -> nx_tcp_listen_queue_head;
11176
11177 tcp_header_ptr = (NX_TCP_HEADER*)packet_ptr -> nx_packet_prepend_ptr;
11178
11179 if(tcp_header_ptr -> nx_tcp_header_word_3 & NX_TCP_SYN_BIT)
11180 {
11181
11182 ret = nx_bsd_tcp_syn_received_notify(socket_ptr, packet_ptr);
11183
11184 /* Yes. We are done. */
11185 if(ret == NX_TRUE)
11186 {
11187
11188 return;
11189 }
11190
11191 listen_ptr -> nx_tcp_listen_queue_head = packet_ptr -> nx_packet_queue_next;
11192
11193 if(packet_ptr == listen_ptr -> nx_tcp_listen_queue_tail)
11194 {
11195 listen_ptr -> nx_tcp_listen_queue_tail = NX_NULL;
11196 }
11197
11198 listen_ptr -> nx_tcp_listen_queue_current--;
11199
11200 nx_packet_release(packet_ptr);
11201
11202 }
11203 } while(listen_ptr -> nx_tcp_listen_queue_head);
11204 }
11205
11206 listen_ptr = listen_ptr -> nx_tcp_listen_next;
11207
11208 }while(listen_ptr != nx_bsd_default_ip -> nx_ip_tcp_active_listen_requests);
11209 }
11210 }
11211
11212 /**************************************************************************/
11213 /* */
11214 /* FUNCTION RELEASE */
11215 /* */
11216 /* nx_bsd_find_interface_by_source_addr PORTABLE C */
11217 /* 6.1 */
11218 /* AUTHOR */
11219 /* */
11220 /* Yuxin Zhou, Microsoft Corporation */
11221 /* */
11222 /* DESCRIPTION */
11223 /* */
11224 /* This function finds the interface index value of a given IPv4 or */
11225 /* IPv6 source address. */
11226 /* */
11227 /* INPUT */
11228 /* */
11229 /* addr_family Address Family */
11230 /* ip_addr Pointer to an array of IPv4 */
11231 /* or IPv6 address */
11232 /* */
11233 /* OUTPUT */
11234 /* */
11235 /* Index value */
11236 /* */
11237 /* CALLS */
11238 /* */
11239 /* None */
11240 /* */
11241 /* CALLED BY */
11242 /* */
11243 /* nx_bsd_send_internal */
11244 /* */
11245 /* RELEASE HISTORY */
11246 /* */
11247 /* DATE NAME DESCRIPTION */
11248 /* */
11249 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11250 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
11251 /* resulting in version 6.1 */
11252 /* */
11253 /**************************************************************************/
nx_bsd_find_interface_by_source_addr(UINT addr_family,ULONG * ip_addr)11254 static INT nx_bsd_find_interface_by_source_addr(UINT addr_family, ULONG* ip_addr)
11255 {
11256 INT i;
11257 #ifndef NX_DISABLE_IPV4
11258 ULONG ipv4_addr;
11259 #endif /* NX_DISABLE_IPV4 */
11260 #ifdef FEATURE_NX_IPV6
11261 ULONG ipv6_addr[4];
11262 #endif
11263
11264 #ifndef NX_DISABLE_IPV4
11265 if(addr_family == AF_INET)
11266 {
11267 ipv4_addr = *ip_addr;
11268 NX_CHANGE_ULONG_ENDIAN(ipv4_addr);
11269
11270 for(i = 0; i < NX_MAX_IP_INTERFACES; i++)
11271 {
11272 if((nx_bsd_default_ip -> nx_ip_interface[i].nx_interface_valid) &&
11273 (nx_bsd_default_ip -> nx_ip_interface[i].nx_interface_ip_address == ipv4_addr))
11274 return i;
11275 }
11276 }
11277 #endif /* NX_DISABLE_IPV4 */
11278 #ifdef FEATURE_NX_IPV6
11279 if(addr_family == AF_INET6)
11280 {
11281 ipv6_addr[0] = *(ip_addr);
11282 ipv6_addr[1] = *(ip_addr + 1);
11283 ipv6_addr[2] = *(ip_addr + 2);
11284 ipv6_addr[3] = *(ip_addr + 3);
11285 NX_IPV6_ADDRESS_CHANGE_ENDIAN(ipv6_addr);
11286
11287 for(i = 0; i < NX_MAX_IPV6_ADDRESSES; i++)
11288 {
11289
11290 if((nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address_valid) &&
11291 (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address_attached -> nx_interface_valid) &&
11292 (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address[0] == ipv6_addr[0]) &&
11293 (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address[1] == ipv6_addr[1]) &&
11294 (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address[2] == ipv6_addr[2]) &&
11295 (nx_bsd_default_ip -> nx_ipv6_address[i].nxd_ipv6_address[3] == ipv6_addr[3]))
11296 return i;
11297 }
11298 }
11299 #endif
11300
11301 return((INT)(NX_BSD_LOCAL_IF_INADDR_ANY));
11302
11303 }
11304
11305
11306 #ifndef NX_DISABLE_IPV4
11307 /**************************************************************************/
11308 /* */
11309 /* FUNCTION RELEASE */
11310 /* */
11311 /* _nxd_bsd_ipv4_packet_send PORTABLE C */
11312 /* 6.1 */
11313 /* AUTHOR */
11314 /* */
11315 /* Yuxin Zhou, Microsoft Corporation */
11316 /* */
11317 /* DESCRIPTION */
11318 /* */
11319 /* This function computes the IP header checksum and updates that into */
11320 /* the ip header ,which is assumed to be already prepended in the */
11321 /* input packet buffer, and forwards it to the driver directly. */
11322 /* */
11323 /* INPUT */
11324 /* */
11325 /* packet_ptr Pointer to packet to send */
11326 /* */
11327 /* OUTPUT */
11328 /* */
11329 /* None */
11330 /* */
11331 /* CALLS */
11332 /* */
11333 /* _nx_ip_checksum_compute Compute IP checksum */
11334 /* (_nx_arp_entry_allocate) ARP entry allocate service */
11335 /* (_nx_arp_packet_send) Send an ARP packet */
11336 /* _nx_ip_packet_deferred_receive Receive loopback packet */
11337 /* _nx_packet_copy Copy packet to input packet */
11338 /* _nx_packet_transmit_release Release transmit packet */
11339 /* (nx_ip_fragment_processing) Fragment processing */
11340 /* (ip_link_driver) User supplied link driver */
11341 /* */
11342 /* CALLED BY */
11343 /* */
11344 /* nx_bsd_send_internal */
11345 /* */
11346 /* RELEASE HISTORY */
11347 /* */
11348 /* DATE NAME DESCRIPTION */
11349 /* */
11350 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
11351 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
11352 /* resulting in version 6.1 */
11353 /* */
11354 /**************************************************************************/
_nxd_bsd_ipv4_packet_send(NX_PACKET * packet_ptr)11355 static VOID _nxd_bsd_ipv4_packet_send(NX_PACKET *packet_ptr)
11356 {
11357
11358 TX_INTERRUPT_SAVE_AREA
11359 NX_IP_DRIVER driver_request;
11360 NX_IPV4_HEADER *ip_header_ptr;
11361 #ifndef NX_DISABLE_IP_TX_CHECKSUM
11362 ULONG checksum;
11363 ULONG val;
11364 #endif
11365 UINT index;
11366 NX_ARP *arp_ptr;
11367 NX_PACKET *last_packet;
11368 NX_PACKET *remove_packet;
11369 UINT queued_count;
11370 NX_PACKET *packet_copy;
11371 ULONG network_mask;
11372 ULONG network;
11373 NX_IP * ip_ptr;
11374 ULONG destination_ip;
11375
11376 ip_ptr = nx_bsd_default_ip;
11377 #ifndef NX_DISABLE_IP_INFO
11378
11379 /* Increment the total send requests counter. */
11380 ip_ptr -> nx_ip_total_packet_send_requests++;
11381 #endif
11382
11383
11384 /* Setup the IP header pointer. */
11385 ip_header_ptr = (NX_IPV4_HEADER *) packet_ptr -> nx_packet_prepend_ptr;
11386
11387 destination_ip = ip_header_ptr -> nx_ip_header_destination_ip;
11388
11389 /* Swap the destination address to host byte order.*/
11390 NX_CHANGE_ULONG_ENDIAN(destination_ip);
11391
11392 #ifndef NX_DISABLE_IP_TX_CHECKSUM
11393 checksum = _nx_ip_checksum_compute(packet_ptr, NX_IP_VERSION_V4,
11394 /* Length is the size of IP header, including options */
11395 (UINT)((*(UCHAR*)ip_header_ptr & 0xf) << 2),
11396 /* IPv4 header checksum does not use src/dest addresses */
11397 NULL, NULL);
11398
11399 val = (ULONG)(~checksum);
11400 val = val & NX_LOWER_16_MASK;
11401
11402 /* Convert to network byte order. */
11403 NX_CHANGE_ULONG_ENDIAN(val);
11404
11405 /* Now store the checksum in the IP header. */
11406 ip_header_ptr -> nx_ip_header_word_2 = ip_header_ptr -> nx_ip_header_word_2 | val;
11407
11408 #endif
11409
11410 /* Determine if physical mapping is needed by the link driver. */
11411 if (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_address_mapping_needed )
11412 {
11413
11414
11415 network_mask = packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_network_mask;
11416 network = packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_network;
11417
11418 /* Determine whether or not the destination address is out of this local network. */
11419 if (((destination_ip & network_mask) != network) ||
11420 ((destination_ip & ~network_mask) == ~network_mask) ||
11421 (destination_ip == packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_address))
11422 {
11423
11424 /* We have an out-of-network destination IP address, check for a variety
11425 of out-of-network destinations. */
11426
11427 /* Determine if an IP limited or directed broadcast is requested. */
11428 if ((destination_ip == NX_IP_LIMITED_BROADCAST) ||
11429 (((destination_ip & network_mask) == network) &&
11430 ((destination_ip & ~network_mask) == ~network_mask)))
11431 {
11432
11433 /* Build the driver request. */
11434 driver_request.nx_ip_driver_ptr = ip_ptr;
11435 driver_request.nx_ip_driver_command = NX_LINK_PACKET_BROADCAST;
11436 driver_request.nx_ip_driver_packet = packet_ptr;
11437 driver_request.nx_ip_driver_physical_address_msw = 0xFFFFUL;
11438 driver_request.nx_ip_driver_physical_address_lsw = 0xFFFFFFFFUL;
11439 driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11440
11441 #ifndef NX_DISABLE_FRAGMENTATION
11442 /* Determine if fragmentation is needed. */
11443 if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
11444 {
11445
11446 /* Fragmentation is needed, call the fragment routine if available. */
11447 if (ip_ptr -> nx_ip_fragment_processing)
11448 {
11449
11450 /* Call the IP fragment processing routine. */
11451 (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
11452 }
11453 else
11454 {
11455
11456 #ifndef NX_DISABLE_IP_INFO
11457
11458 /* Increment the IP send packets dropped count. */
11459 ip_ptr -> nx_ip_send_packets_dropped++;
11460 #endif
11461 /* Just release the packet. */
11462 _nx_packet_transmit_release(packet_ptr);
11463 }
11464
11465 /* In either case, this packet send is complete, just return. */
11466 return;
11467 }
11468 #endif
11469
11470 #ifndef NX_DISABLE_IP_INFO
11471
11472 /* Increment the IP packet sent count. */
11473 ip_ptr -> nx_ip_total_packets_sent++;
11474
11475 /* Increment the IP bytes sent count. */
11476 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11477 #endif
11478
11479 /* Broadcast packet. */
11480 (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
11481
11482 return;
11483 }
11484
11485 /* Determine if we have a loopback address. */
11486 else if ((((destination_ip >= NX_IP_LOOPBACK_FIRST) &&
11487 (destination_ip <= NX_IP_LOOPBACK_LAST))) ||
11488 (destination_ip == ip_ptr -> nx_ip_interface[0].nx_interface_ip_address))
11489 {
11490
11491 /* Yes, we have an internal loopback address. */
11492
11493 /* Copy the packet so it can be enqueued properly by the receive
11494 processing. */
11495 if (_nx_packet_copy(packet_ptr, &packet_copy, ip_ptr -> nx_ip_default_packet_pool, NX_NO_WAIT) == NX_SUCCESS)
11496 {
11497
11498 #ifndef NX_DISABLE_IP_INFO
11499
11500 /* Increment the IP packet sent count. */
11501 ip_ptr -> nx_ip_total_packets_sent++;
11502
11503 /* Increment the IP bytes sent count. */
11504 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11505 #endif
11506
11507 /* Send the packet to this IP's receive processing like it came in from the
11508 driver. */
11509 _nx_ip_packet_deferred_receive(ip_ptr, packet_copy);
11510 }
11511 #ifndef NX_DISABLE_IP_INFO
11512 else
11513 {
11514
11515 /* Increment the IP send packets dropped count. */
11516 ip_ptr -> nx_ip_send_packets_dropped++;
11517
11518 /* Increment the IP transmit resource error count. */
11519 ip_ptr -> nx_ip_transmit_resource_errors++;
11520 }
11521 #endif
11522
11523 /* Release the transmit packet. */
11524 _nx_packet_transmit_release(packet_ptr);
11525 return;
11526 }
11527
11528 /* Determine if we have a class D multicast address. */
11529 else if ((destination_ip & NX_IP_CLASS_D_MASK) == NX_IP_CLASS_D_TYPE)
11530 {
11531
11532 /* Yes, we have a class D multicast address. Derive the physical mapping from
11533 the class D address. */
11534 driver_request.nx_ip_driver_physical_address_msw = NX_IP_MULTICAST_UPPER;
11535 driver_request.nx_ip_driver_physical_address_lsw = NX_IP_MULTICAST_LOWER | (destination_ip & NX_IP_MULTICAST_MASK);
11536 driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11537
11538 /* Determine if the group address has been joined in this IP instance. */
11539 index = 0;
11540 while (index < NX_MAX_MULTICAST_GROUPS)
11541 {
11542
11543 /* Determine if the destination address matches the requested address. */
11544 if (ip_ptr -> nx_ipv4_multicast_entry[index].nx_ipv4_multicast_join_list == destination_ip)
11545 {
11546
11547 /* Yes, break the loop! */
11548 break;
11549 }
11550
11551 /* Increment the join list index. */
11552 index++;
11553 }
11554
11555 /* Determine if the group was joined by this IP instance. */
11556 if (index < NX_MAX_MULTICAST_GROUPS)
11557 {
11558
11559 /* Determine if the group has loopback enabled. */
11560 if (ip_ptr -> nx_ipv4_multicast_entry[index].nx_ipv4_multicast_loopback_enable)
11561 {
11562
11563 /* Yes, loopback is enabled! */
11564
11565 /* Copy the packet so we can send it via loopback. */
11566 if (_nx_packet_copy(packet_ptr, &packet_copy, ip_ptr -> nx_ip_default_packet_pool, NX_NO_WAIT) == NX_SUCCESS)
11567 {
11568
11569 #ifndef NX_DISABLE_IP_INFO
11570
11571 /* Increment the IP packet sent count. */
11572 ip_ptr -> nx_ip_total_packets_sent++;
11573
11574 /* Increment the IP bytes sent count. */
11575 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11576 #endif
11577
11578 /* Packet copy was successful. Send the packet to this IP's receive processing like it came in from the
11579 driver. */
11580 _nx_ip_packet_deferred_receive(ip_ptr, packet_copy);
11581 }
11582 #ifndef NX_DISABLE_IP_INFO
11583 else
11584 {
11585
11586 /* Increment the IP send packets dropped count. */
11587 ip_ptr -> nx_ip_send_packets_dropped++;
11588
11589 /* Increment the IP transmit resource error count. */
11590 ip_ptr -> nx_ip_transmit_resource_errors++;
11591 }
11592 #endif
11593 }
11594 }
11595
11596 /* Build the driver request. */
11597 driver_request.nx_ip_driver_ptr = ip_ptr;
11598 driver_request.nx_ip_driver_command = NX_LINK_PACKET_SEND;
11599 driver_request.nx_ip_driver_packet = packet_ptr;
11600 driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11601
11602 #ifndef NX_DISABLE_FRAGMENTATION
11603 /* Determine if fragmentation is needed. */
11604 if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
11605 {
11606
11607 /* Fragmentation is needed, call the fragment routine if available. */
11608 if (ip_ptr -> nx_ip_fragment_processing)
11609 {
11610
11611 /* Call the IP fragment processing routine. */
11612 (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
11613 }
11614 else
11615 {
11616
11617 #ifndef NX_DISABLE_IP_INFO
11618
11619 /* Increment the IP send packets dropped count. */
11620 ip_ptr -> nx_ip_send_packets_dropped++;
11621 #endif
11622 /* Just release the packet. */
11623 _nx_packet_transmit_release(packet_ptr);
11624 }
11625
11626 /* In either case, this packet send is complete, just return. */
11627 return;
11628 }
11629 #endif
11630
11631 #ifndef NX_DISABLE_IP_INFO
11632
11633 /* Increment the IP packet sent count. */
11634 ip_ptr -> nx_ip_total_packets_sent++;
11635
11636 /* Increment the IP bytes sent count. */
11637 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11638 #endif
11639
11640 /* Send the IP packet out on the network via the attached driver. */
11641 (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
11642
11643 /* Return to caller. */
11644 return;
11645 }
11646
11647 /* Use default gateway. */
11648 else
11649 {
11650
11651 /* We have an out-of-network destination IP address, check to see if a
11652 Gateway IP address has been specified. */
11653 if (ip_ptr -> nx_ip_gateway_address)
11654 {
11655
11656 /* Remap the destination IP address to the Gateway IP address. The ARP
11657 processing below will handle getting the physical address for the
11658 Gateway. */
11659 destination_ip = ip_ptr -> nx_ip_gateway_address;
11660 }
11661 else
11662 {
11663
11664 #ifndef NX_DISABLE_IP_INFO
11665
11666 /* Increment the number of no route errors. */
11667 ip_ptr -> nx_ip_transmit_no_route_errors++;
11668
11669 /* Increment the IP send packets dropped count. */
11670 ip_ptr -> nx_ip_send_packets_dropped++;
11671 #endif
11672 /* Just release the packet. */
11673 _nx_packet_transmit_release(packet_ptr);
11674
11675 /* In either case, this packet send is complete, just return. */
11676 return;
11677 }
11678 }
11679 }
11680
11681 /* Yes, look into the ARP Routing Table to derive the physical address. */
11682
11683 /* Calculate the hash index for the destination IP address. */
11684 index = (UINT) ((destination_ip + (destination_ip >> 8)) & NX_ARP_TABLE_MASK);
11685
11686 /* Disable interrupts temporarily. */
11687 TX_DISABLE
11688
11689 /* Determine if there is an entry for this IP address. */
11690 arp_ptr = ip_ptr -> nx_ip_arp_table[index];
11691
11692 /* Determine if this arp entry matches the destination IP address. */
11693 if ((arp_ptr) && (arp_ptr -> nx_arp_ip_address == destination_ip))
11694 {
11695
11696 /* Yes, we have an existing ARP mapping entry. */
11697
11698 /* Determine if there is a physical address. */
11699 if (arp_ptr -> nx_arp_physical_address_msw | arp_ptr -> nx_arp_physical_address_lsw)
11700 {
11701
11702 /* Yes, we have a physical mapping. Copy the physical address into the driver
11703 request structure. */
11704 driver_request.nx_ip_driver_physical_address_msw = arp_ptr -> nx_arp_physical_address_msw;
11705 driver_request.nx_ip_driver_physical_address_lsw = arp_ptr -> nx_arp_physical_address_lsw;
11706
11707 /* Restore interrupts. */
11708 TX_RESTORE
11709
11710 /* Build the driver request. */
11711 driver_request.nx_ip_driver_ptr = ip_ptr;
11712 driver_request.nx_ip_driver_command = NX_LINK_PACKET_SEND;
11713 driver_request.nx_ip_driver_packet = packet_ptr;
11714 driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11715
11716 #ifndef NX_DISABLE_FRAGMENTATION
11717 /* Determine if fragmentation is needed. */
11718 if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
11719 {
11720
11721 /* Fragmentation is needed, call the fragment routine if available. */
11722 if (ip_ptr -> nx_ip_fragment_processing)
11723 {
11724
11725 /* Call the IP fragment processing routine. */
11726 (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
11727 }
11728 else
11729 {
11730
11731 #ifndef NX_DISABLE_IP_INFO
11732
11733 /* Increment the IP send packets dropped count. */
11734 ip_ptr -> nx_ip_send_packets_dropped++;
11735 #endif
11736
11737 /* Just release the packet. */
11738 _nx_packet_transmit_release(packet_ptr);
11739 }
11740
11741 /* In either case, this packet send is complete, just return. */
11742 return;
11743 }
11744 #endif
11745
11746 #ifndef NX_DISABLE_IP_INFO
11747
11748 /* Increment the IP packet sent count. */
11749 ip_ptr -> nx_ip_total_packets_sent++;
11750
11751 /* Increment the IP bytes sent count. */
11752 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11753 #endif
11754
11755 /* Send the IP packet out on the network via the attached driver. */
11756 (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
11757
11758 /* Return to caller. */
11759 return;
11760 }
11761 else
11762 {
11763
11764 /* Ensure the current packet's queue next pointer to NULL. */
11765 packet_ptr -> nx_packet_queue_next = NX_NULL;
11766
11767 /* Determine if the queue is empty. */
11768 if (arp_ptr -> nx_arp_packets_waiting == NX_NULL)
11769 {
11770
11771 /* Yes, we have an empty ARP packet queue. Simply place the
11772 packet at the head of the list. */
11773 arp_ptr -> nx_arp_packets_waiting = packet_ptr;
11774
11775 /* Restore interrupts. */
11776 TX_RESTORE
11777 }
11778 else
11779 {
11780
11781 /* Determine how many packets are on the ARP entry's packet
11782 queue and remember the last packet in the queue. We know
11783 there is at least one on the queue and another that is
11784 going to be queued. */
11785 last_packet = arp_ptr -> nx_arp_packets_waiting;
11786 queued_count = 0;
11787 while (last_packet -> nx_packet_queue_next)
11788 {
11789
11790 /* Increment the queued count. */
11791 queued_count++;
11792
11793 /* Move to the next packet in the queue. */
11794 last_packet = last_packet -> nx_packet_queue_next;
11795 }
11796
11797 /* Place the packet at the end of the list. */
11798 last_packet -> nx_packet_queue_next = packet_ptr;
11799
11800 /* Default the remove packet pointer to NULL. */
11801 remove_packet = NX_NULL;
11802
11803 /* Determine if the packets queued has exceeded the queue
11804 depth. */
11805 if (queued_count >= NX_ARP_MAX_QUEUE_DEPTH)
11806 {
11807
11808 /* Save the packet pointer at the head of the list. */
11809 remove_packet = arp_ptr -> nx_arp_packets_waiting;
11810
11811 /* Remove the packet from the ARP queue. */
11812 arp_ptr -> nx_arp_packets_waiting = remove_packet -> nx_packet_queue_next;
11813
11814 /* Clear the remove packet queue next pointer. */
11815 remove_packet -> nx_packet_queue_next = NX_NULL;
11816
11817 #ifndef NX_DISABLE_IP_INFO
11818
11819 /* Increment the IP transmit resource error count. */
11820 ip_ptr -> nx_ip_transmit_resource_errors++;
11821
11822 /* Increment the IP send packets dropped count. */
11823 ip_ptr -> nx_ip_send_packets_dropped++;
11824 #endif
11825 }
11826
11827 /* Restore interrupts. */
11828 TX_RESTORE
11829
11830 /* Determine if there is a packet to remove. */
11831 if (remove_packet)
11832 {
11833
11834 /* Yes, the packet queue depth for this ARP entry was exceeded
11835 so release the packet that was removed from the queue. */
11836 _nx_packet_transmit_release(remove_packet);
11837 }
11838 }
11839
11840 /* Return to caller. */
11841 return;
11842 }
11843 }
11844 else
11845 {
11846
11847 /* At this point, we need to search the ARP list for a match for the
11848 destination IP. */
11849
11850 /* First, restore interrupts. */
11851 TX_RESTORE
11852
11853 /* Pickup the first ARP entry. */
11854 arp_ptr = ip_ptr -> nx_ip_arp_table[index];
11855
11856 /* Loop to look for an ARP match. */
11857 while (arp_ptr)
11858 {
11859
11860 /* Check for an IP match. */
11861 if (arp_ptr -> nx_arp_ip_address == destination_ip)
11862 {
11863
11864 /* Yes, we found a match. Get out of the loop! */
11865 break;
11866 }
11867
11868 /* Move to the next active ARP entry. */
11869 arp_ptr = arp_ptr -> nx_arp_active_next;
11870
11871 /* Determine if we are at the end of the ARP list. */
11872 if (arp_ptr == ip_ptr -> nx_ip_arp_table[index])
11873 {
11874 /* Clear the ARP pointer. */
11875 arp_ptr = NX_NULL;
11876 break;
11877 }
11878 }
11879
11880 /* Determine if we actually found a matching ARP entry. */
11881 if (arp_ptr)
11882 {
11883
11884 /* Yes, we found an ARP entry. Now check and see if
11885 it has an actual physical address. */
11886 if (arp_ptr -> nx_arp_physical_address_msw | arp_ptr -> nx_arp_physical_address_lsw)
11887 {
11888
11889 /* Yes, we have a physical mapping. Copy the physical address into the driver
11890 request structure. */
11891 driver_request.nx_ip_driver_physical_address_msw = arp_ptr -> nx_arp_physical_address_msw;
11892 driver_request.nx_ip_driver_physical_address_lsw = arp_ptr -> nx_arp_physical_address_lsw;
11893
11894 /* Disable interrupts. */
11895 TX_DISABLE
11896
11897 /* Move this ARP entry to the head of the list. */
11898 ip_ptr -> nx_ip_arp_table[index] = arp_ptr;
11899
11900 /* Restore interrupts. */
11901 TX_RESTORE
11902
11903 /* Build the driver request message. */
11904 driver_request.nx_ip_driver_ptr = ip_ptr;
11905 driver_request.nx_ip_driver_command = NX_LINK_PACKET_SEND;
11906 driver_request.nx_ip_driver_packet = packet_ptr;
11907 driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
11908
11909 #ifndef NX_DISABLE_FRAGMENTATION
11910 /* Determine if fragmentation is needed. */
11911 if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
11912 {
11913
11914 /* Fragmentation is needed, call the fragment routine if available. */
11915 if (ip_ptr -> nx_ip_fragment_processing)
11916 {
11917
11918 /* Call the IP fragment processing routine. */
11919 (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
11920 }
11921 else
11922 {
11923
11924 #ifndef NX_DISABLE_IP_INFO
11925
11926 /* Increment the IP send packets dropped count. */
11927 ip_ptr -> nx_ip_send_packets_dropped++;
11928 #endif
11929
11930 /* Just release the packet. */
11931 _nx_packet_transmit_release(packet_ptr);
11932 }
11933
11934 /* In either case, this packet send is complete, just return. */
11935 return;
11936 }
11937 #endif
11938
11939 #ifndef NX_DISABLE_IP_INFO
11940
11941 /* Increment the IP packet sent count. */
11942 ip_ptr -> nx_ip_total_packets_sent++;
11943
11944 /* Increment the IP bytes sent count. */
11945 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
11946 #endif
11947
11948 /* Send the IP packet out on the network via the attached driver. */
11949 (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
11950
11951 /* Return to caller. */
11952 return;
11953 }
11954 else
11955 {
11956
11957 /* We don't have physical mapping. */
11958
11959 /* Disable interrupts. */
11960 TX_DISABLE
11961
11962 /* Ensure the current packet's queue next pointer to NULL. */
11963 packet_ptr -> nx_packet_queue_next = NX_NULL;
11964
11965 /* Determine if the queue is empty. */
11966 if (arp_ptr -> nx_arp_packets_waiting == NX_NULL)
11967 {
11968
11969 /* Yes, we have an empty ARP packet queue. Simply place the
11970 packet at the head of the list. */
11971 arp_ptr -> nx_arp_packets_waiting = packet_ptr;
11972
11973 /* Restore interrupts. */
11974 TX_RESTORE
11975 }
11976 else
11977 {
11978
11979
11980 /* Determine how many packets are on the ARP entry's packet
11981 queue and remember the last packet in the queue. We know
11982 there is at least one on the queue and another that is
11983 going to be queued. */
11984 last_packet = arp_ptr -> nx_arp_packets_waiting;
11985 queued_count = 0;
11986 while (last_packet -> nx_packet_queue_next)
11987 {
11988
11989 /* Increment the queued count. */
11990 queued_count++;
11991
11992 /* Move to the next packet in the queue. */
11993 last_packet = last_packet -> nx_packet_queue_next;
11994 }
11995
11996 /* Place the packet at the end of the list. */
11997 last_packet -> nx_packet_queue_next = packet_ptr;
11998
11999 /* Default the remove packet pointer to NULL. */
12000 remove_packet = NX_NULL;
12001
12002 /* Determine if the packets queued has exceeded the queue
12003 depth. */
12004 if (queued_count >= NX_ARP_MAX_QUEUE_DEPTH)
12005 {
12006
12007 /* Save the packet pointer at the head of the list. */
12008 remove_packet = arp_ptr -> nx_arp_packets_waiting;
12009
12010 /* Remove the packet from the ARP queue. */
12011 arp_ptr -> nx_arp_packets_waiting = remove_packet -> nx_packet_queue_next;
12012
12013 /* Clear the remove packet queue next pointer. */
12014 remove_packet -> nx_packet_queue_next = NX_NULL;
12015
12016 #ifndef NX_DISABLE_IP_INFO
12017
12018 /* Increment the IP transmit resource error count. */
12019 ip_ptr -> nx_ip_transmit_resource_errors++;
12020
12021 /* Increment the IP send packets dropped count. */
12022 ip_ptr -> nx_ip_send_packets_dropped++;
12023 #endif
12024 }
12025
12026 /* Restore interrupts. */
12027 TX_RESTORE
12028
12029 /* Determine if there is a packet to remove. */
12030 if (remove_packet)
12031 {
12032
12033 /* Yes, the packet queue depth for this ARP entry was exceeded
12034 so release the packet that was removed from the queue. */
12035 _nx_packet_transmit_release(remove_packet);
12036 }
12037 }
12038
12039 /* Return to caller. */
12040 return;
12041 }
12042 }
12043 else
12044 {
12045
12046 /* No ARP entry was found. We need to allocate a new ARP entry, populate it, and
12047 initiate an ARP request to get the specific physical mapping. */
12048
12049 /* Allocate a new ARP entry. */
12050 if ((!ip_ptr -> nx_ip_arp_allocate) ||
12051 ((ip_ptr -> nx_ip_arp_allocate)(ip_ptr, &(ip_ptr -> nx_ip_arp_table[index]), NX_FALSE)))
12052 {
12053
12054 /* Error, release the protection and the packet. */
12055
12056 #ifndef NX_DISABLE_IP_INFO
12057
12058 /* Increment the IP transmit resource error count. */
12059 ip_ptr -> nx_ip_transmit_resource_errors++;
12060
12061 /* Increment the IP send packets dropped count. */
12062 ip_ptr -> nx_ip_send_packets_dropped++;
12063 #endif
12064
12065 /* Release the packet. */
12066 _nx_packet_transmit_release(packet_ptr);
12067
12068 /* Just return! */
12069 return;
12070 }
12071
12072 /* Otherwise, setup a pointer to the new ARP entry. */
12073 arp_ptr = (ip_ptr -> nx_ip_arp_table[index]) -> nx_arp_active_previous;
12074
12075 /* Setup the IP address and clear the physical mapping. */
12076 arp_ptr -> nx_arp_ip_address = destination_ip;
12077 arp_ptr -> nx_arp_physical_address_msw = 0;
12078 arp_ptr -> nx_arp_physical_address_lsw = 0;
12079 arp_ptr -> nx_arp_entry_next_update = NX_ARP_EXPIRATION_RATE;
12080 arp_ptr -> nx_arp_retries = 0;
12081 arp_ptr -> nx_arp_ip_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
12082
12083 /* Ensure the queue next pointer is NULL for the packet before it
12084 is placed on the ARP waiting queue. */
12085 packet_ptr -> nx_packet_queue_next = NX_NULL;
12086
12087 /* Queue the packet for output. */
12088 arp_ptr -> nx_arp_packets_waiting = packet_ptr;
12089
12090 /* Call ARP send to send an ARP request. */
12091 (ip_ptr -> nx_ip_arp_packet_send)(ip_ptr, destination_ip, packet_ptr -> nx_packet_address.nx_packet_interface_ptr);
12092 return;
12093 }
12094 }
12095 }
12096 else
12097 {
12098
12099 /* This IP instance does not require any IP-to-physical mapping. */
12100
12101 /* Determine if we have a loopback address. */
12102 if ((((destination_ip >= NX_IP_LOOPBACK_FIRST) &&
12103 (destination_ip <= NX_IP_LOOPBACK_LAST))) ||
12104 (destination_ip == packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_address))
12105 {
12106
12107 /* Yes, we have an internal loopback address. */
12108
12109 /* Copy the packet so it can be enqueued properly by the receive
12110 processing. */
12111 if (_nx_packet_copy(packet_ptr, &packet_copy, ip_ptr -> nx_ip_default_packet_pool, NX_NO_WAIT) == NX_SUCCESS)
12112 {
12113
12114 #ifndef NX_DISABLE_IP_INFO
12115
12116 /* Increment the IP packet sent count. */
12117 ip_ptr -> nx_ip_total_packets_sent++;
12118
12119 /* Increment the IP bytes sent count. */
12120 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
12121 #endif
12122
12123 /* Send the packet to this IP's receive processing like it came in from the
12124 driver. */
12125 _nx_ip_packet_deferred_receive(ip_ptr, packet_copy);
12126 }
12127 #ifndef NX_DISABLE_IP_INFO
12128 else
12129 {
12130
12131 /* Increment the IP transmit resource error count. */
12132 ip_ptr -> nx_ip_transmit_resource_errors++;
12133
12134 /* Increment the IP send packets dropped count. */
12135 ip_ptr -> nx_ip_send_packets_dropped++;
12136 }
12137 #endif
12138
12139 /* Release the transmit packet. */
12140 _nx_packet_transmit_release(packet_ptr);
12141 return;
12142 }
12143
12144 /* Build the driver request. */
12145 driver_request.nx_ip_driver_ptr = ip_ptr;
12146 driver_request.nx_ip_driver_command = NX_LINK_PACKET_SEND;
12147 driver_request.nx_ip_driver_packet = packet_ptr;
12148 driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_address.nx_packet_interface_ptr;
12149
12150 #ifndef NX_DISABLE_FRAGMENTATION
12151 /* Determine if fragmentation is needed. */
12152 if (packet_ptr -> nx_packet_length > packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_mtu_size)
12153 {
12154
12155 /* Fragmentation is needed, call the fragment routine if available. */
12156 if (ip_ptr -> nx_ip_fragment_processing)
12157 {
12158
12159 /* Call the IP fragment processing routine. */
12160 (ip_ptr -> nx_ip_fragment_processing) (&driver_request);
12161 }
12162 else
12163 {
12164
12165 #ifndef NX_DISABLE_IP_INFO
12166
12167 /* Increment the IP send packets dropped count. */
12168 ip_ptr -> nx_ip_send_packets_dropped++;
12169 #endif
12170
12171 /* Just release the packet. */
12172 _nx_packet_transmit_release(packet_ptr);
12173 }
12174
12175 /* In either case, this packet send is complete, just return. */
12176 return;
12177 }
12178 #endif
12179
12180 #ifndef NX_DISABLE_IP_INFO
12181
12182 /* Increment the IP packet sent count. */
12183 ip_ptr -> nx_ip_total_packets_sent++;
12184
12185 /* Increment the IP bytes sent count. */
12186 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV4_HEADER);
12187
12188 #endif
12189
12190 /* No mapping driver. Just send the packet out! */
12191 (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_link_driver_entry) (&driver_request);
12192 }
12193 }
12194 #endif /*NX_DISABLE_IPV4 */
12195
12196 #ifdef FEATURE_NX_IPV6
12197 /**************************************************************************/
12198 /* */
12199 /* FUNCTION RELEASE */
12200 /* */
12201 /* _nxd_bsd_ipv6_packet_send PORTABLE C */
12202 /* 6.1 */
12203 /* AUTHOR */
12204 /* */
12205 /* Yuxin Zhou, Microsoft Corporation */
12206 /* */
12207 /* DESCRIPTION */
12208 /* */
12209 /* This function forwards the input packet directly to the appropriate */
12210 /* link driver. The caller needs to fill in the correct */
12211 /* source and destination addresses into the packet source and */
12212 /* destination address. The caller also makes sure that the packet */
12213 /* interface address is valid (not in tentative state), and source */
12214 /* address is not unspecified e.g. NULL. */
12215 /* */
12216 /* INPUT */
12217 /* */
12218 /* packet_ptr Pointer to packet to send */
12219 /* src_addr Pointer to source address */
12220 /* dest_addr Pointer to dest address */
12221 /* */
12222 /* OUTPUT */
12223 /* */
12224 /* None */
12225 /* */
12226 /* CALLS */
12227 /* */
12228 /* _nx_packet_transmit_release Release transmit packet */
12229 /* _nx_nd_cache_add_entry Add new entry to ND Cache */
12230 /* IPv6_Address_Type Find IPv6 address type */
12231 /* _nx_packet_copy Packet copy */
12232 /* _nx_ip_packet_deferred_receive Places received packets in */
12233 /* deferred packet queue */
12234 /* _nx_icmpv6_send_ns Send neighbor solicitation */
12235 /* _nxd_ipv6_search_onlink Find onlink match */
12236 /* _nx_ipv6_fragment_processing Fragment processing */
12237 /* (ip_link_driver) User supplied link driver */
12238 /* */
12239 /* CALLED BY */
12240 /* */
12241 /* nx_bsd_send_internal */
12242 /* */
12243 /* RELEASE HISTORY */
12244 /* */
12245 /* DATE NAME DESCRIPTION */
12246 /* */
12247 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12248 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12249 /* resulting in version 6.1 */
12250 /* */
12251 /**************************************************************************/
_nxd_bsd_ipv6_packet_send(NX_PACKET * packet_ptr,ULONG * src_addr,ULONG * dest_addr)12252 static VOID _nxd_bsd_ipv6_packet_send(NX_PACKET *packet_ptr, ULONG *src_addr, ULONG *dest_addr)
12253 {
12254
12255 UINT status;
12256 ULONG address_type;
12257 NX_IP_DRIVER driver_request;
12258 NX_PACKET *remove_packet;
12259 NX_PACKET *packet_copy;
12260 UINT same_address;
12261 NX_INTERFACE *if_ptr;
12262 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
12263 NX_IPV6_HEADER *ip_header_ptr;
12264 #endif
12265 NX_IPV6_DESTINATION_ENTRY *dest_entry_ptr;
12266 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
12267 UINT next_hop_path_mtu;
12268 NX_IPV6_DESTINATION_ENTRY *next_hop_dest_entry_ptr;
12269 #endif
12270 NX_IP *ip_ptr;
12271
12272 ip_ptr = nx_bsd_default_ip;
12273 #ifndef NX_DISABLE_IP_INFO
12274
12275 /* Increment the total send requests counter. */
12276 ip_ptr -> nx_ip_total_packet_send_requests++;
12277 #endif
12278
12279 if_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached;
12280
12281
12282 /* If the interface IP address is not valid (in DAD state), only ICMP is allowed */
12283 if(packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_state != NX_IPV6_ADDR_STATE_VALID)
12284 {
12285
12286 #ifndef NX_DISABLE_IP_INFO
12287
12288 /* Increment the IP invalid packet error. */
12289 ip_ptr -> nx_ip_invalid_transmit_packets++;
12290 #endif
12291
12292 /* Release the packet. */
12293 _nx_packet_transmit_release(packet_ptr);
12294
12295 /* Return... nothing more can be done! */
12296 return;
12297 }
12298
12299 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
12300 /* Build the IP header. */
12301 ip_header_ptr = (NX_IPV6_HEADER*)packet_ptr -> nx_packet_prepend_ptr;
12302 #endif
12303
12304 /* Check if the host is sending itself a packet. */
12305 same_address = (UINT)CHECK_IPV6_ADDRESSES_SAME(dest_addr, src_addr);
12306
12307 /* If it is, consider this a loopback address. */
12308 if (same_address == 1)
12309 {
12310
12311 address_type = IPV6_ADDRESS_LOOPBACK;
12312 }
12313 else
12314 {
12315
12316 /* Otherwise check if this packet sending to a known loopback address. */
12317 address_type = IPv6_Address_Type(dest_addr);
12318 }
12319
12320 /* Handle the internal loopback case. */
12321 if(address_type == IPV6_ADDRESS_LOOPBACK)
12322 {
12323
12324 if(_nx_packet_copy(packet_ptr, &packet_copy, ip_ptr -> nx_ip_default_packet_pool, NX_NO_WAIT) == NX_SUCCESS)
12325 {
12326 #ifndef NX_DISABLE_IP_INFO
12327
12328 /* Increment the IP packet sent count. */
12329 ip_ptr -> nx_ip_total_packets_sent++;
12330
12331 /* Increment the IP bytes sent count. */
12332 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV6_HEADER);
12333 #endif
12334
12335 /* Send the packet to this IP's receive processing like it came in from the driver. */
12336 _nx_ip_packet_deferred_receive(ip_ptr, packet_copy);
12337 }
12338 #ifndef NX_DISABLE_IP_INFO
12339 else
12340 {
12341 /* Increment the IP send packets dropped count. */
12342 ip_ptr -> nx_ip_send_packets_dropped++;
12343
12344 /* Increment the IP transmit resource error count. */
12345 ip_ptr -> nx_ip_transmit_resource_errors++;
12346 }
12347 #endif
12348 /* Release the transmit packet. */
12349 _nx_packet_transmit_release(packet_ptr);
12350 return;
12351
12352 }
12353
12354 /* Is this packet a multicast ? */
12355 if((dest_addr[0] & 0xFF000000) == 0xFF000000)
12356 {
12357
12358
12359 /* Set up the driver request. */
12360 driver_request.nx_ip_driver_ptr = ip_ptr;
12361 driver_request.nx_ip_driver_command = NX_LINK_PACKET_SEND;
12362 driver_request.nx_ip_driver_packet = packet_ptr;
12363 driver_request.nx_ip_driver_physical_address_msw = 0x00003333;
12364 driver_request.nx_ip_driver_physical_address_lsw = dest_addr[3];
12365 driver_request.nx_ip_driver_interface = if_ptr;
12366
12367 #ifndef NX_DISABLE_IP_INFO
12368
12369 /* Increment the IP packet sent count. */
12370 ip_ptr -> nx_ip_total_packets_sent++;
12371
12372 /* Increment the IP bytes sent count. */
12373 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV6_HEADER);
12374 #endif
12375
12376 /* Check if fragmentation is enabled. */
12377 #ifndef NX_DISABLE_FRAGMENTATION
12378
12379 /* It is; is path MTU enabled? */
12380 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
12381
12382 /* It is. We will check the path MTU for the packet destination to
12383 determine if we need to fragment the packet. */
12384
12385 /* Get a pointer to the packet IP header. */
12386 ip_header_ptr = (NX_IPV6_HEADER *)packet_ptr -> nx_packet_prepend_ptr;
12387
12388 /* Lookup the multicast destination in the destination table. */
12389 status = _nx_icmpv6_dest_table_find(ip_ptr, ip_header_ptr -> nx_ip_header_destination_ip, &dest_entry_ptr, 0, 0);
12390
12391 /* Did we find it in the table? */
12392 if ((status == NX_SUCCESS) && (dest_entry_ptr != NX_NULL))
12393 {
12394
12395 /* Yes; Check the destination path MTU if fragmentation is needed. */
12396 if ((dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu > 0) && (packet_ptr -> nx_packet_length >
12397 dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu))
12398 {
12399
12400 /* Yes we must fragment the payload. */
12401 _nx_ipv6_fragment_process(&driver_request, dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu);
12402
12403 /* This packet send is complete, just return. */
12404 return;
12405 }
12406
12407 /* Packet should drop through and be checked against the IP mtu. */
12408 }
12409
12410 #endif /* NX_ENABLE_IPV6_PATH_MTU_DISCOVERY */
12411
12412
12413 /* Does the packet payload exceed our IP instance MTU? */
12414 if (packet_ptr -> nx_packet_length > if_ptr -> nx_interface_ip_mtu_size)
12415 {
12416 /* Yes; ok to fragment the packet payload. */
12417 _nx_ipv6_fragment_process(&driver_request, if_ptr -> nx_interface_ip_mtu_size);
12418
12419 /* This packet send is complete, just return. */
12420 return;
12421 }
12422
12423 /* Packet will go out unfragmented. */
12424
12425 #endif /* NX_DISABLE_FRAGMENTATION */
12426
12427
12428 /* Send the IP packet out on the network via the attached driver. */
12429 (if_ptr -> nx_interface_link_driver_entry) (&driver_request);
12430
12431 /* Return to caller. */
12432 return;
12433 }
12434
12435 /* Determine if physical mapping is needed by this link driver. */
12436 if( if_ptr && if_ptr -> nx_interface_address_mapping_needed )
12437 {
12438
12439 /* Obtain MAC address */
12440 ND_CACHE_ENTRY *NDCacheEntry = NX_NULL;
12441 ULONG next_hop_address[4];
12442
12443 SET_UNSPECIFIED_ADDRESS(next_hop_address);
12444
12445 /* Lookup the packet destination in the destination table. */
12446 status = _nx_icmpv6_dest_table_find(ip_ptr, dest_addr, &dest_entry_ptr, 0, 0);
12447
12448 /* Was a matching entry found? */
12449 if(status != NX_SUCCESS)
12450 {
12451
12452 /* No; If the packet is either onlink or there is no default router,
12453 just copy the packet destination address to the 'next hop' address. */
12454
12455 if(_nxd_ipv6_search_onlink(ip_ptr, dest_addr))
12456 {
12457 COPY_IPV6_ADDRESS(dest_addr, next_hop_address);
12458
12459 /* Add the next_hop in destination table. */
12460 status = _nx_icmpv6_dest_table_add(ip_ptr, dest_addr, &dest_entry_ptr,
12461 next_hop_address, if_ptr -> nx_interface_ip_mtu_size,
12462 NX_WAIT_FOREVER, packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr);
12463
12464 /* Get the NDCacheEntry. */
12465 if(status == NX_SUCCESS)
12466 NDCacheEntry = dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry;
12467 }
12468
12469 /* Check whether or not we have a default router. */
12470 else if(_nxd_ipv6_router_lookup(ip_ptr, if_ptr, next_hop_address, (VOID**)&NDCacheEntry) == NX_SUCCESS)
12471 {
12472 /* Add the next_hop in destination table. */
12473 status = _nx_icmpv6_dest_table_add(ip_ptr, dest_addr, &dest_entry_ptr,
12474 next_hop_address, if_ptr -> nx_interface_ip_mtu_size,
12475 NX_WAIT_FOREVER, packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr);
12476
12477 /* If the default router did not has a reachable ND_CACHE_ENTRY. Get the NDCacheEntry. */
12478 if(!NDCacheEntry)
12479 NDCacheEntry = dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry;
12480 }
12481
12482 /* Can not find next_hop or the destination table add failed. */
12483 if(status || ((next_hop_address[0] == 0) && (next_hop_address[1] == 0) && (next_hop_address[2] == 0) && (next_hop_address[3] == 0)))
12484 {
12485
12486 /* Release the packet. */
12487 _nx_packet_release(packet_ptr);
12488
12489 /* Can't send it. */
12490 return;
12491 }
12492
12493 }
12494
12495 /* Find a valid destination cache, set the nd cache and next hop address. */
12496 else
12497 {
12498
12499 /* Check the NDCacheEntry is valid. */
12500 if(dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry -> nx_nd_cache_nd_status == ND_CACHE_STATE_INVALID)
12501 {
12502 if(_nx_nd_cache_add_entry(ip_ptr, dest_addr, packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr, &dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry))
12503 {
12504 /* Release the packet. */
12505 _nx_packet_release(packet_ptr);
12506
12507 /* Can't send it. */
12508 return;
12509 }
12510
12511 }
12512
12513 /* Get the destination and next hop address. */
12514 NDCacheEntry = dest_entry_ptr -> nx_ipv6_destination_entry_nd_entry;
12515 COPY_IPV6_ADDRESS(dest_entry_ptr -> nx_ipv6_destination_entry_next_hop, next_hop_address);
12516 }
12517
12518 /* According RFC2461 ch 7.3.3, as long as the entry is valid and not in INCOMPLETE state,
12519 the IP layer should use the cached link layer address. */
12520 if((NDCacheEntry -> nx_nd_cache_nd_status >= ND_CACHE_STATE_REACHABLE) &&
12521 (NDCacheEntry -> nx_nd_cache_nd_status <= ND_CACHE_STATE_PROBE))
12522 {
12523
12524 UCHAR *mac_addr;
12525
12526 mac_addr = NDCacheEntry -> nx_nd_cache_mac_addr;
12527
12528 /* Assume we find the mac */
12529 driver_request.nx_ip_driver_ptr = ip_ptr;
12530 driver_request.nx_ip_driver_command = NX_LINK_PACKET_SEND;
12531 driver_request.nx_ip_driver_packet = packet_ptr;
12532 driver_request.nx_ip_driver_physical_address_msw = (ULONG)((mac_addr[0] << 8) | mac_addr[1]);
12533 driver_request.nx_ip_driver_physical_address_lsw =
12534 (ULONG)((mac_addr[2] << 24) | (mac_addr[3] << 16) | (mac_addr[4] << 8) | mac_addr[5]);
12535 driver_request.nx_ip_driver_interface = if_ptr;
12536
12537 #ifndef NX_DISABLE_FRAGMENTATION
12538
12539 /* If the packet size is bigger than MTU, NetX Duo is enabled to fragment
12540 the packet payload. */
12541
12542 /* Check if path MTU Discovery is enabled first. */
12543
12544 #ifdef NX_ENABLE_IPV6_PATH_MTU_DISCOVERY
12545
12546 /* It is. To know if we need to fragment this packet we need the path MTU for the packet
12547 destination. */
12548
12549 /* If this destination has a non null next hop, we need to ascertain the next hop MTU. */
12550
12551 /* Get the path MTU for the actual destination. */
12552 next_hop_path_mtu = dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu;
12553
12554
12555 /* Find the next hop in the destination table. */
12556 status = _nx_icmpv6_dest_table_find(ip_ptr, next_hop_address, &next_hop_dest_entry_ptr, 0, 0);
12557
12558 if (status == NX_SUCCESS)
12559 {
12560
12561 /* Now compare the destination path MTU with the next hop path MTU*/
12562 if ((next_hop_dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu > 0) &&
12563 (next_hop_path_mtu > next_hop_dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu))
12564 {
12565
12566 /* Update the path mtu to reflect the next hop route. */
12567 next_hop_path_mtu = next_hop_dest_entry_ptr -> nx_ipv6_destination_entry_path_mtu;
12568 }
12569 }
12570
12571 /* Yes; Check the destination path MTU if fragmentation is needed. */
12572 if ((next_hop_path_mtu > 0) &&
12573 (packet_ptr -> nx_packet_length > next_hop_path_mtu))
12574 {
12575
12576 /* Yes we must fragment the payload. */
12577 _nx_ipv6_fragment_process(&driver_request, next_hop_path_mtu);
12578
12579 /* This packet send is complete, just return. */
12580 return;
12581 }
12582 #endif /* NX_ENABLE_IPV6_PATH_MTU_DISCOVERY */
12583
12584 /* Send packet unfragmented. */
12585
12586 /* If we didn't find anything in the destination table, let the packet drop through. NetX Duo
12587 will check our IP instance MTU if fragmentation is needed before sending. */
12588
12589
12590 /* Does the packet payload exceed our IP instance MTU? */
12591 if (packet_ptr -> nx_packet_length > if_ptr -> nx_interface_ip_mtu_size)
12592 {
12593 /* Yes; ok to fragment the packet payload. */
12594 _nx_ipv6_fragment_process(&driver_request, if_ptr -> nx_interface_ip_mtu_size);
12595
12596 /* This packet send is complete, just return. */
12597 return;
12598 }
12599
12600 /* The packet requires no fragmentation. Proceed with sending the packet. */
12601
12602 #endif /* NX_DISABLE_FRAGMENTATION */
12603
12604
12605 #ifndef NX_DISABLE_IP_INFO
12606
12607 /* Increment the IP packet sent count. */
12608 ip_ptr -> nx_ip_total_packets_sent++;
12609
12610 /* Increment the IP bytes sent count. */
12611 ip_ptr -> nx_ip_total_bytes_sent += packet_ptr -> nx_packet_length - sizeof(NX_IPV6_HEADER);
12612 #endif
12613
12614 /* Send the IP packet out on the network via the attached driver. */
12615 (if_ptr -> nx_interface_link_driver_entry) (&driver_request);
12616
12617 /* If the entry is in STALE state, move it to DELAY state. */
12618 if(NDCacheEntry -> nx_nd_cache_nd_status == ND_CACHE_STATE_STALE)
12619 {
12620 NDCacheEntry -> nx_nd_cache_nd_status = ND_CACHE_STATE_DELAY;
12621
12622 /* Start the Delay first probe timer */
12623 NDCacheEntry -> nx_nd_cache_timer_tick = NX_DELAY_FIRST_PROBE_TIME;
12624
12625 }
12626
12627 /* Return to caller. */
12628 return;
12629 }
12630
12631 /* No MAC address was found in our cache table. Start the Neighbor Discovery (ND)
12632 process to get it. */
12633
12634 /* Ensure the current packet's queue next pointer to NULL */
12635 packet_ptr -> nx_packet_queue_next = NX_NULL;
12636
12637 /* Determine if the queue is empty. */
12638 if(NDCacheEntry -> nx_nd_cache_packet_waiting_head == NX_NULL)
12639 {
12640 /* ICMPv6 is enabled */
12641 if(ip_ptr -> nx_ip_icmpv6_packet_process)
12642 {
12643
12644 /* Queue up this packet */
12645 NDCacheEntry -> nx_nd_cache_packet_waiting_head = packet_ptr;
12646 NDCacheEntry -> nx_nd_cache_packet_waiting_tail = packet_ptr;
12647 NDCacheEntry -> nx_nd_cache_packet_waiting_queue_length = 1;
12648
12649 /* Set the outgoing address and interface to the cache entry. */
12650 NDCacheEntry -> nx_nd_cache_outgoing_address = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr;
12651 NDCacheEntry -> nx_nd_cache_interface_ptr = if_ptr;
12652
12653 /* Is this a new entry? */
12654 if(NDCacheEntry -> nx_nd_cache_nd_status == ND_CACHE_STATE_CREATED)
12655 {
12656
12657 /* Start Neighbor discovery process by advancing to the incomplete state. */
12658 NDCacheEntry -> nx_nd_cache_nd_status = ND_CACHE_STATE_INCOMPLETE;
12659 }
12660
12661 _nx_icmpv6_send_ns(ip_ptr, next_hop_address,
12662 1, packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr, 0, NX_NULL);
12663
12664 NDCacheEntry -> nx_nd_cache_num_solicit = NX_MAX_MULTICAST_SOLICIT - 1;
12665 NDCacheEntry -> nx_nd_cache_timer_tick = ip_ptr -> nx_ipv6_retrans_timer_ticks;
12666
12667 }
12668 else
12669 {
12670
12671 _nx_packet_transmit_release(packet_ptr);
12672 #ifndef NX_DISABLE_IP_INFO
12673
12674 /* Increment the IP transmit resource error count. */
12675 ip_ptr -> nx_ip_transmit_resource_errors++;
12676
12677 /* Increment the IP send packets dropped count. */
12678 ip_ptr -> nx_ip_send_packets_dropped++;
12679 #endif
12680 }
12681 return;
12682 }
12683
12684 /* The ND process already started. Simply queue up this packet */
12685 NDCacheEntry -> nx_nd_cache_packet_waiting_tail -> nx_packet_queue_next = packet_ptr;
12686 NDCacheEntry -> nx_nd_cache_packet_waiting_tail = packet_ptr;
12687 NDCacheEntry -> nx_nd_cache_packet_waiting_queue_length++;
12688
12689 /* Check if the number of packets enqueued exceeds the allowed number. */
12690 if(NDCacheEntry -> nx_nd_cache_packet_waiting_queue_length > NX_ND_MAX_QUEUE_DEPTH)
12691 {
12692
12693 /* Yes, so delete the first packet. */
12694 remove_packet = NDCacheEntry -> nx_nd_cache_packet_waiting_head;
12695
12696 NDCacheEntry -> nx_nd_cache_packet_waiting_head = remove_packet -> nx_packet_queue_next;
12697
12698 /* Update the queued packet count for this cache entry. */
12699 NDCacheEntry -> nx_nd_cache_packet_waiting_queue_length--;
12700
12701 _nx_packet_transmit_release(remove_packet);
12702 #ifndef NX_DISABLE_IP_INFO
12703 /* Increment the IP transmit resource error count. */
12704 ip_ptr -> nx_ip_transmit_resource_errors++;
12705
12706 /* Increment the IP send packets dropped count. */
12707 ip_ptr -> nx_ip_send_packets_dropped++;
12708 #endif
12709 }
12710
12711 return;
12712 }
12713
12714 /* For now do nothing. Just release the packet */
12715 _nx_packet_release(packet_ptr);
12716 }
12717
12718 #endif /* FEATURE_NX_IPV6 */
12719
12720 #if defined(FEATURE_NX_IPV6) && defined(NX_ENABLE_IP_RAW_PACKET_FILTER)
12721 /**************************************************************************/
12722 /* */
12723 /* FUNCTION RELEASE */
12724 /* */
12725 /* _nxd_bsd_swap_ipv6_extension_headers PORTABLE C */
12726 /* 6.1 */
12727 /* AUTHOR */
12728 /* */
12729 /* Yuxin Zhou, Microsoft Corporation */
12730 /* */
12731 /* DESCRIPTION */
12732 /* */
12733 /* This function performs endian swap operations on the IPv6 */
12734 /* extension headers. */
12735 /* */
12736 /* INPUT */
12737 /* */
12738 /* packet_ptr Pointer to packet */
12739 /* header_type Type of the first extension */
12740 /* header */
12741 /* */
12742 /* OUTPUT */
12743 /* */
12744 /* None */
12745 /* */
12746 /* CALLS */
12747 /* */
12748 /* NX_CHANGE_USHORT_ENDIAN Swap endian-ness on 16-bit */
12749 /* integer. */
12750 /* */
12751 /* CALLED BY */
12752 /* */
12753 /* NetX Duo BSD Layer Source Code */
12754 /* */
12755 /* RELEASE HISTORY */
12756 /* */
12757 /* DATE NAME DESCRIPTION */
12758 /* */
12759 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12760 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12761 /* resulting in version 6.1 */
12762 /* */
12763 /**************************************************************************/
_nxd_bsd_swap_ipv6_extension_headers(NX_PACKET * packet_ptr,UCHAR header_type)12764 static VOID _nxd_bsd_swap_ipv6_extension_headers(NX_PACKET *packet_ptr, UCHAR header_type)
12765 {
12766 UCHAR *scan_ptr;
12767 ULONG remaining_bytes;
12768 ULONG header_length = 40;
12769 NX_IPV6_HEADER_OPTION *option;
12770
12771
12772 remaining_bytes = (ULONG)packet_ptr -> nx_packet_prepend_ptr - (ULONG)packet_ptr -> nx_packet_ip_header;
12773
12774 scan_ptr = packet_ptr -> nx_packet_ip_header;
12775
12776 remaining_bytes -= header_length;
12777 scan_ptr += header_length;
12778
12779 while(remaining_bytes)
12780 {
12781 option = (NX_IPV6_HEADER_OPTION*)scan_ptr;
12782 switch(header_type)
12783 {
12784 case NX_PROTOCOL_NEXT_HEADER_HOP_BY_HOP:
12785
12786 break;
12787
12788 case NX_PROTOCOL_NEXT_HEADER_DESTINATION:
12789
12790 break;
12791
12792 case NX_PROTOCOL_NEXT_HEADER_ROUTING:
12793 break;
12794
12795
12796 case NX_PROTOCOL_NEXT_HEADER_FRAGMENT:
12797 NX_CHANGE_USHORT_ENDIAN(((NX_IPV6_HEADER_FRAGMENT_OPTION *)scan_ptr) -> nx_ipv6_header_fragment_option_offset_flag);
12798 break;
12799
12800 default:
12801
12802 break;
12803 }
12804
12805 header_type = option -> nx_ipv6_header_option_next_header;
12806
12807 if(header_type == NX_PROTOCOL_NEXT_HEADER_AUTHENTICATION)
12808 header_length = (ULONG)((option -> nx_ipv6_header_option_ext_length << 2) + 2);
12809 else
12810 header_length = (ULONG)((option -> nx_ipv6_header_option_ext_length + 1) << 3);
12811
12812
12813 remaining_bytes -= header_length;
12814 scan_ptr += header_length;
12815 }
12816 }
12817 #endif /* defined(FEATURE_NX_IPV6) && defined(NX_ENABLE_IP_RAW_PACKET_FILTER) */
12818 #ifdef NX_BSD_RAW_PPPOE_SUPPORT
12819
12820
12821 /**************************************************************************/
12822 /* */
12823 /* FUNCTION RELEASE */
12824 /* */
12825 /* nx_bsd_pppoe_internal_sendto PORTABLE C */
12826 /* 6.3.0 */
12827 /* AUTHOR */
12828 /* */
12829 /* Yuxin Zhou, Microsoft Corporation */
12830 /* */
12831 /* DESCRIPTION */
12832 /* */
12833 /* This function sends raw PPPOE packet to driver directly. */
12834 /* */
12835 /* INPUT */
12836 /* */
12837 /* bsd_socket_ptr Pointer to bsd socket */
12838 /* msg Message to send */
12839 /* msgLength Length of message */
12840 /* flags Flags */
12841 /* destAddr Pointer to destination address*/
12842 /* destAddrLen Length of destination address */
12843 /* */
12844 /* OUTPUT */
12845 /* */
12846 /* msgLength On success */
12847 /* NX_SOC_ERROR (-1) On failure */
12848 /* */
12849 /* CALLS */
12850 /* */
12851 /* nx_packet_allocate Allocate a packet */
12852 /* nx_packet_data_append Append data to the packet */
12853 /* nx_packet_release Release the packet on error */
12854 /* tx_mutex_get Obtain exclusive access to */
12855 /* tx_mutex_put Release exclusive access */
12856 /* */
12857 /* CALLED BY */
12858 /* */
12859 /* Application Code */
12860 /* */
12861 /* RELEASE HISTORY */
12862 /* */
12863 /* DATE NAME DESCRIPTION */
12864 /* */
12865 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
12866 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
12867 /* resulting in version 6.1 */
12868 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
12869 /* used new API/structs naming,*/
12870 /* resulting in version 6.3.0 */
12871 /* */
12872 /**************************************************************************/
nx_bsd_pppoe_internal_sendto(NX_BSD_SOCKET * bsd_socket_ptr,CHAR * msg,INT msgLength,INT flags,struct nx_bsd_sockaddr * destAddr,INT destAddrLen)12873 static INT nx_bsd_pppoe_internal_sendto(NX_BSD_SOCKET *bsd_socket_ptr, CHAR *msg, INT msgLength, INT flags, struct nx_bsd_sockaddr* destAddr, INT destAddrLen)
12874 {
12875 UINT if_index;
12876 struct nx_bsd_sockaddr_ll
12877 *destAddr_ll;
12878 #if 0
12879 ULONG src_mac_msw;
12880 ULONG src_mac_lsw;
12881 #endif
12882 NX_IP_DRIVER driver_request;
12883 UINT status;
12884 NX_PACKET *packet_ptr = NX_NULL;
12885
12886 NX_PARAMETER_NOT_USED(bsd_socket_ptr);
12887 NX_PARAMETER_NOT_USED(flags);
12888
12889 /* Validate the parameters. */
12890 if(destAddr == NX_NULL)
12891 {
12892 /* Set the socket error if extended socket options enabled. */
12893 nx_bsd_set_errno(EINVAL);
12894
12895 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12896 return(NX_SOC_ERROR);
12897 }
12898
12899 if(destAddr -> sa_family != AF_PACKET)
12900 {
12901 /* Set the socket error if extended socket options enabled. */
12902 nx_bsd_set_errno(EINVAL);
12903
12904 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12905 return(NX_SOC_ERROR);
12906 }
12907
12908 if(destAddrLen != sizeof(struct nx_bsd_sockaddr_ll))
12909 {
12910 /* Set the socket error if extended socket options enabled. */
12911 nx_bsd_set_errno(EINVAL);
12912
12913 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12914 return(NX_SOC_ERROR);
12915 }
12916
12917 destAddr_ll = (struct nx_bsd_sockaddr_ll*)destAddr;
12918
12919 if((destAddr_ll -> sll_protocol != ETHERTYPE_PPPOE_SESS) && (destAddr_ll -> sll_protocol != ETHERTYPE_PPPOE_DISC))
12920 {
12921 /* Set the socket error if extended socket options enabled. */
12922 nx_bsd_set_errno(EINVAL);
12923
12924 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12925 return(NX_SOC_ERROR);
12926 }
12927
12928 /* Validate the interface ID */
12929 if_index = (UINT)(destAddr_ll -> sll_ifindex);
12930 if(if_index >= NX_MAX_IP_INTERFACES)
12931 {
12932 /* Set the socket error if extended socket options enabled. */
12933 nx_bsd_set_errno(EINVAL);
12934
12935 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12936 return(NX_SOC_ERROR);
12937 }
12938
12939 if(nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_valid == 0)
12940 {
12941 /* Set the socket error if extended socket options enabled. */
12942 nx_bsd_set_errno(EINVAL);
12943
12944 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12945 return(NX_SOC_ERROR);
12946 }
12947
12948 #if 0
12949 /* Pickup the source MAC address */
12950 src_mac_msw = nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_physical_address_msw;
12951 src_mac_lsw = nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_physical_address_lsw;
12952 #endif
12953
12954
12955
12956 /* Validate the packet length */
12957 if(msgLength > (INT)(nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_ip_mtu_size + 14))
12958 {
12959 /* Set the socket error if extended socket options enabled. */
12960 nx_bsd_set_errno(EINVAL);
12961
12962 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
12963 return(NX_SOC_ERROR);
12964 }
12965
12966 /* FIXME: If the socket is non-blocking, Timeout value should be set to 0 */
12967 status = nx_packet_allocate(nx_bsd_default_packet_pool, &packet_ptr, NX_PHYSICAL_HEADER, NX_NO_WAIT);
12968
12969 /* Check for errors. */
12970 if (status != NX_SUCCESS)
12971 {
12972
12973 /* Set the socket error. */
12974 nx_bsd_set_errno(ENOBUFS);
12975
12976 /* Return an error status.*/
12977 NX_BSD_ERROR(status, __LINE__);
12978 return(NX_SOC_ERROR);
12979 }
12980
12981
12982
12983 /* Now copy the data into the NetX packet. */
12984 status = nx_packet_data_append(packet_ptr, (VOID *) msg, (ULONG)msgLength, nx_bsd_default_packet_pool, NX_NO_WAIT);
12985
12986 /* Was the data copy successful? */
12987 if (status != NX_SUCCESS)
12988 {
12989
12990 nx_packet_release(packet_ptr);
12991
12992 /* Set the socket error. */
12993 nx_bsd_set_errno(ENOBUFS);
12994
12995 /* Return an error status.*/
12996 NX_BSD_ERROR(status, __LINE__);
12997 return(NX_SOC_ERROR);
12998 }
12999
13000 /* Now ready to transmit this packet. */
13001 driver_request.nx_ip_driver_ptr = nx_bsd_default_ip;
13002 if(destAddr_ll -> sll_protocol == ETHERTYPE_PPPOE_SESS)
13003 driver_request.nx_ip_driver_command = NX_LINK_PACKET_PPPOE_SESS_SEND;
13004 else
13005 driver_request.nx_ip_driver_command = NX_LINK_PACKET_PPPOE_DISC_SEND;
13006 driver_request.nx_ip_driver_packet = packet_ptr;
13007 driver_request.nx_ip_driver_interface = &nx_bsd_default_ip -> nx_ip_interface[if_index];
13008
13009 /* Obtain the BSD lock. */
13010 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
13011
13012 /* Check the status. */
13013 if (status != NX_SUCCESS)
13014 {
13015
13016 nx_packet_release(packet_ptr);
13017
13018 /* Set the socket error if extended socket options enabled. */
13019 nx_bsd_set_errno(EACCES);
13020
13021 /* Return an error. */
13022 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
13023 return(NX_SOC_ERROR);
13024 }
13025
13026 (driver_request.nx_ip_driver_interface -> nx_interface_link_driver_entry)(&driver_request);
13027
13028 /* Release the mutex. */
13029 tx_mutex_put(nx_bsd_protection_ptr);
13030
13031 return(msgLength);
13032 }
13033
13034
13035 /**************************************************************************/
13036 /* */
13037 /* FUNCTION RELEASE */
13038 /* */
13039 /* _nx_bsd_pppoe_packet_received PORTABLE C */
13040 /* 6.1 */
13041 /* AUTHOR */
13042 /* */
13043 /* Yuxin Zhou, Microsoft Corporation */
13044 /* */
13045 /* DESCRIPTION */
13046 /* */
13047 /* This function receives raw PPPOE packet from driver directly. */
13048 /* */
13049 /* INPUT */
13050 /* */
13051 /* packet_ptr Pointer to received packet */
13052 /* frame_type Type of frame */
13053 /* interface_id Interface ID */
13054 /* */
13055 /* OUTPUT */
13056 /* */
13057 /* NX_SUCCESS */
13058 /* */
13059 /* CALLS */
13060 /* */
13061 /* nx_bsd_select_wakeup Wake up any asychronous */
13062 /* receive call */
13063 /* nx_packet_release Release the packet on error */
13064 /* */
13065 /* CALLED BY */
13066 /* */
13067 /* Application Code */
13068 /* */
13069 /* RELEASE HISTORY */
13070 /* */
13071 /* DATE NAME DESCRIPTION */
13072 /* */
13073 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13074 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13075 /* resulting in version 6.1 */
13076 /* */
13077 /**************************************************************************/
_nx_bsd_pppoe_packet_received(NX_PACKET * packet_ptr,UINT frame_type,UINT interface_id)13078 UINT _nx_bsd_pppoe_packet_received(NX_PACKET *packet_ptr, UINT frame_type, UINT interface_id)
13079 {
13080
13081 UINT i;
13082 UINT sockid = NX_BSD_MAX_SOCKETS;
13083 UINT create_id = 0xFFFFFFFF;
13084 NX_BSD_SOCKET *bsd_ptr;
13085
13086 NX_PARAMETER_NOT_USED(interface_id);
13087
13088 /* Find the socket with the lowest create-ID. Put the packet into the socket's recevie queue. */
13089 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
13090 {
13091 if((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE) &&
13092 /*
13093 (nx_bsd_socket_array[i].nx_bsd_raw_socket_enabled == NX_TRUE) &&
13094 */
13095 (nx_bsd_socket_array[i].nx_bsd_socket_family == AF_PACKET) &&
13096 (nx_bsd_socket_array[i].nx_bsd_socket_protocol == frame_type))
13097 {
13098 if(nx_bsd_socket_array[i].nx_bsd_socket_create_id < create_id)
13099 {
13100 sockid = i;
13101 create_id = nx_bsd_socket_array[i].nx_bsd_socket_create_id;
13102 }
13103 }
13104 }
13105 if(sockid == NX_BSD_MAX_SOCKETS)
13106 {
13107 /* No BSD sockets are avaialble for this frame type. */
13108 nx_packet_release(packet_ptr);
13109 return(NX_SUCCESS);
13110 }
13111 /* Now we need to put the packet into the socket. */
13112 bsd_ptr = &nx_bsd_socket_array[sockid];
13113
13114 /* Drop the packet if the receive queue exceeds max depth. */
13115 if(bsd_ptr -> nx_bsd_socket_received_packet_count >=
13116 bsd_ptr -> nx_bsd_socket_received_packet_count_max)
13117 {
13118 nx_packet_release(packet_ptr);
13119 return(NX_SUCCESS);
13120 }
13121
13122 if(bsd_ptr -> nx_bsd_socket_received_packet)
13123 {
13124 bsd_ptr -> nx_bsd_socket_received_packet_tail -> nx_packet_queue_next = packet_ptr;
13125 }
13126 else
13127 {
13128 bsd_ptr -> nx_bsd_socket_received_packet = packet_ptr;
13129 bsd_ptr -> nx_bsd_socket_received_packet_offset = 0;
13130 }
13131
13132 bsd_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
13133 bsd_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
13134 bsd_ptr -> nx_bsd_socket_received_packet_count ++;
13135
13136 nx_bsd_select_wakeup(sockid, FDSET_READ);
13137
13138 return 0;
13139 }
13140 #endif /* NX_BSD_RAW_PPPOE_SUPPORT */
13141
13142 #ifdef NX_BSD_RAW_SUPPORT
13143
13144 /**************************************************************************/
13145 /* */
13146 /* FUNCTION RELEASE */
13147 /* */
13148 /* _nx_bsd_hardware_internal_sendto PORTABLE C */
13149 /* 6.4.0 */
13150 /* AUTHOR */
13151 /* */
13152 /* Yuxin Zhou, Microsoft Corporation */
13153 /* */
13154 /* DESCRIPTION */
13155 /* */
13156 /* This function sends raw packet to driver directly. */
13157 /* */
13158 /* INPUT */
13159 /* */
13160 /* bsd_socket_ptr Pointer to bsd socket */
13161 /* msg Message to send */
13162 /* msgLength Length of message */
13163 /* flags Flags */
13164 /* destAddr Pointer to destination address*/
13165 /* destAddrLen Length of destination address */
13166 /* */
13167 /* OUTPUT */
13168 /* */
13169 /* msgLength On success */
13170 /* NX_SOC_ERROR (-1) On failure */
13171 /* */
13172 /* CALLS */
13173 /* */
13174 /* nx_packet_allocate Allocate a packet */
13175 /* nx_packet_data_append Append data to the packet */
13176 /* nx_packet_release Release the packet on error */
13177 /* tx_mutex_get Obtain exclusive access to */
13178 /* tx_mutex_put Release exclusive access */
13179 /* */
13180 /* CALLED BY */
13181 /* */
13182 /* Application Code */
13183 /* */
13184 /* RELEASE HISTORY */
13185 /* */
13186 /* DATE NAME DESCRIPTION */
13187 /* */
13188 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13189 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13190 /* resulting in version 6.1 */
13191 /* 12-31-2023 Yanwu Cai Modified comment(s), */
13192 /* added nx_link layer, */
13193 /* resulting in version 6.4.0 */
13194 /* */
13195 /**************************************************************************/
_nx_bsd_hardware_internal_sendto(NX_BSD_SOCKET * bsd_socket_ptr,CHAR * msg,INT msgLength,INT flags,struct nx_bsd_sockaddr * destAddr,INT destAddrLen)13196 static INT _nx_bsd_hardware_internal_sendto(NX_BSD_SOCKET *bsd_socket_ptr, CHAR *msg, INT msgLength, INT flags, struct nx_bsd_sockaddr* destAddr, INT destAddrLen)
13197 {
13198 UINT if_index;
13199 struct nx_bsd_sockaddr_ll
13200 *destAddr_ll;
13201 UINT status;
13202 NX_PACKET *packet_ptr = NX_NULL;
13203
13204 NX_PARAMETER_NOT_USED(bsd_socket_ptr);
13205 NX_PARAMETER_NOT_USED(flags);
13206
13207 /* Validate the parameters. */
13208 if(destAddr == NX_NULL)
13209 {
13210 /* Set the socket error if extended socket options enabled. */
13211 nx_bsd_set_errno(EINVAL);
13212
13213 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
13214 return(NX_SOC_ERROR);
13215 }
13216
13217 if(destAddr -> sa_family != AF_PACKET)
13218 {
13219 /* Set the socket error if extended socket options enabled. */
13220 nx_bsd_set_errno(EINVAL);
13221
13222 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
13223 return(NX_SOC_ERROR);
13224 }
13225
13226 if(destAddrLen != sizeof(struct nx_bsd_sockaddr_ll))
13227 {
13228 /* Set the socket error if extended socket options enabled. */
13229 nx_bsd_set_errno(EINVAL);
13230
13231 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
13232 return(NX_SOC_ERROR);
13233 }
13234
13235 destAddr_ll = (struct nx_bsd_sockaddr_ll*)destAddr;
13236
13237 /* Validate the interface ID */
13238 if_index = (UINT)(destAddr_ll -> sll_ifindex);
13239 if(if_index >= NX_MAX_IP_INTERFACES)
13240 {
13241 /* Set the socket error if extended socket options enabled. */
13242 nx_bsd_set_errno(EINVAL);
13243
13244 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
13245 return(NX_SOC_ERROR);
13246 }
13247
13248 if(nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_valid == 0)
13249 {
13250 /* Set the socket error if extended socket options enabled. */
13251 nx_bsd_set_errno(EINVAL);
13252
13253 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
13254 return(NX_SOC_ERROR);
13255 }
13256
13257 /* Validate the packet length */
13258 if(msgLength > (INT)(nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_ip_mtu_size + 18))
13259 {
13260 /* Set the socket error if extended socket options enabled. */
13261 nx_bsd_set_errno(EINVAL);
13262
13263 NX_BSD_ERROR(NX_SOC_ERROR, __LINE__);
13264 return(NX_SOC_ERROR);
13265 }
13266
13267 status = nx_packet_allocate(nx_bsd_default_packet_pool, &packet_ptr, NX_PHYSICAL_HEADER, NX_NO_WAIT);
13268
13269 /* Check for errors. */
13270 if (status != NX_SUCCESS)
13271 {
13272
13273 /* Set the socket error. */
13274 nx_bsd_set_errno(ENOBUFS);
13275
13276 /* Return an error status.*/
13277 NX_BSD_ERROR(status, __LINE__);
13278 return(NX_SOC_ERROR);
13279 }
13280
13281 /* Set IP interface. */
13282 packet_ptr -> nx_packet_ip_interface = &nx_bsd_default_ip -> nx_ip_interface[if_index];
13283
13284 /* Now copy the data into the NetX packet. */
13285 status = nx_packet_data_append(packet_ptr, (VOID *) msg, (ULONG)msgLength, nx_bsd_default_packet_pool, NX_NO_WAIT);
13286
13287 /* Was the data copy successful? */
13288 if (status != NX_SUCCESS)
13289 {
13290
13291 nx_packet_release(packet_ptr);
13292
13293 /* Set the socket error. */
13294 nx_bsd_set_errno(ENOBUFS);
13295
13296 /* Return an error status.*/
13297 NX_BSD_ERROR(status, __LINE__);
13298 return(NX_SOC_ERROR);
13299 }
13300
13301 #if defined(__PRODUCT_NETXDUO__) && defined(NX_ENABLE_INTERFACE_CAPABILITY)
13302 packet_ptr -> nx_packet_interface_capability_flag = nx_bsd_default_ip -> nx_ip_interface[if_index].nx_interface_capability_flag;
13303 #endif /* defined(__PRODUCT_NETXDUO__) && defined(NX_ENABLE_INTERFACE_CAPABILITY) */
13304
13305 /* Obtain the BSD lock. */
13306 status = tx_mutex_get(nx_bsd_protection_ptr, NX_BSD_TIMEOUT);
13307
13308 /* Check the status. */
13309 if (status != NX_SUCCESS)
13310 {
13311
13312 nx_packet_release(packet_ptr);
13313
13314 /* Set the socket error if extended socket options enabled. */
13315 nx_bsd_set_errno(EACCES);
13316
13317 /* Return an error. */
13318 NX_BSD_ERROR(NX_BSD_MUTEX_ERROR, __LINE__);
13319 return(NX_SOC_ERROR);
13320 }
13321
13322 #ifdef NX_ENABLE_VLAN
13323 nx_link_raw_packet_send(nx_bsd_default_ip, if_index, packet_ptr);
13324 #else
13325 _nx_driver_hardware_packet_send(packet_ptr);
13326 #endif /* NX_ENABLE_VLAN */
13327
13328 /* Release the mutex. */
13329 tx_mutex_put(nx_bsd_protection_ptr);
13330
13331 return(msgLength);
13332 }
13333
13334
13335 /**************************************************************************/
13336 /* */
13337 /* FUNCTION RELEASE */
13338 /* */
13339 /* _nx_bsd_hardware_packet_received PORTABLE C */
13340 /* 6.1 */
13341 /* AUTHOR */
13342 /* */
13343 /* Yuxin Zhou, Microsoft Corporation */
13344 /* */
13345 /* DESCRIPTION */
13346 /* */
13347 /* This function receives raw packet from driver directly. */
13348 /* */
13349 /* INPUT */
13350 /* */
13351 /* packet_ptr Pointer to received packet */
13352 /* consumed Return packet consumed or not */
13353 /* */
13354 /* OUTPUT */
13355 /* */
13356 /* None */
13357 /* */
13358 /* CALLS */
13359 /* */
13360 /* nx_bsd_select_wakeup Wake up any asychronous */
13361 /* receive call */
13362 /* */
13363 /* CALLED BY */
13364 /* */
13365 /* Application Code */
13366 /* */
13367 /* RELEASE HISTORY */
13368 /* */
13369 /* DATE NAME DESCRIPTION */
13370 /* */
13371 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13372 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13373 /* resulting in version 6.1 */
13374 /* */
13375 /**************************************************************************/
_nx_bsd_hardware_packet_received(NX_PACKET * packet_ptr,UCHAR * consumed)13376 static VOID _nx_bsd_hardware_packet_received(NX_PACKET *packet_ptr, UCHAR *consumed)
13377 {
13378
13379 UINT i;
13380 UINT sockid = NX_BSD_MAX_SOCKETS;
13381 NX_BSD_SOCKET *bsd_ptr;
13382
13383 /* Initialize the consumed to be false. */
13384 *consumed = NX_FALSE;
13385
13386 /* Find the socket with the matching interface. Put the packet into the socket's recevie queue. */
13387 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
13388 {
13389 if((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE) &&
13390 (nx_bsd_socket_array[i].nx_bsd_socket_family == AF_PACKET) &&
13391 ((nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY) ||
13392 (nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface == (ULONG)(packet_ptr -> nx_packet_ip_interface))))
13393 {
13394 sockid = i;
13395 }
13396 }
13397 if(sockid == NX_BSD_MAX_SOCKETS)
13398 {
13399 /* No BSD sockets are avaialble for this frame type. */
13400 return;
13401 }
13402 /* Now we need to put the packet into the socket. */
13403 bsd_ptr = &nx_bsd_socket_array[sockid];
13404
13405 /* Drop the packet if the receive queue exceeds max depth. */
13406 if(bsd_ptr -> nx_bsd_socket_received_packet_count >=
13407 bsd_ptr -> nx_bsd_socket_received_packet_count_max)
13408 {
13409 return;
13410 }
13411
13412 #ifndef NX_DISABLE_BSD_RAW_PACKET_DUPLICATE
13413 /* Duplicate the packet. */
13414 if (nx_packet_copy(packet_ptr, &packet_ptr, nx_bsd_default_packet_pool, NX_NO_WAIT) != NX_SUCCESS)
13415 {
13416 return;
13417 }
13418 #else
13419 /* Consume the packet. IP layer will not see it. */
13420 *consumed = NX_TRUE;
13421 #endif /* NX_DISABLE_BSD_RAW_PACKET_DUPLICATE */
13422
13423 if(bsd_ptr -> nx_bsd_socket_received_packet)
13424 {
13425 bsd_ptr -> nx_bsd_socket_received_packet_tail -> nx_packet_queue_next = packet_ptr;
13426 }
13427 else
13428 {
13429 bsd_ptr -> nx_bsd_socket_received_packet = packet_ptr;
13430 bsd_ptr -> nx_bsd_socket_received_packet_offset = 0;
13431 }
13432
13433 bsd_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
13434 bsd_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
13435 bsd_ptr -> nx_bsd_socket_received_packet_count ++;
13436
13437 nx_bsd_select_wakeup(sockid, FDSET_READ);
13438
13439 return;
13440 }
13441
13442 #ifdef NX_ENABLE_VLAN
13443 /**************************************************************************/
13444 /* */
13445 /* FUNCTION RELEASE */
13446 /* */
13447 /* _nx_bsd_ethernet_receive_notify PORTABLE C */
13448 /* 6.4.0 */
13449 /* AUTHOR */
13450 /* */
13451 /* Yanwu Cai, Microsoft Corporation */
13452 /* */
13453 /* DESCRIPTION */
13454 /* */
13455 /* This function receives raw packet from NetX Link layer. */
13456 /* */
13457 /* INPUT */
13458 /* */
13459 /* ip_ptr Pointer to IP struct */
13460 /* interface_index Interface index */
13461 /* packet_ptr Pointer to received packet */
13462 /* physical_address_msw Pyhsical address */
13463 /* physical_address_lsw Pyhsical address */
13464 /* packet_type Type of received packet */
13465 /* header_size Header size */
13466 /* context Pointer to context */
13467 /* time_ptr Pointer to NX_LINK_TIME_STRUCT*/
13468 /* */
13469 /* OUTPUT */
13470 /* */
13471 /* NX_SUCCESS The packet is consumed */
13472 /* NX_SOC_ERROR Error occured and the packet */
13473 /* is not consumed */
13474 /* */
13475 /* CALLS */
13476 /* */
13477 /* nx_bsd_select_wakeup Wake up any asychronous */
13478 /* receive call */
13479 /* */
13480 /* CALLED BY */
13481 /* */
13482 /* Application Code */
13483 /* */
13484 /* RELEASE HISTORY */
13485 /* */
13486 /* DATE NAME DESCRIPTION */
13487 /* */
13488 /* 12-31-2023 Yanwu Cai Initial Version 6.4.0 */
13489 /* */
13490 /**************************************************************************/
_nx_bsd_ethernet_receive_notify(NX_IP * ip_ptr,UINT interface_index,NX_PACKET * packet_ptr,ULONG physical_address_msw,ULONG physical_address_lsw,UINT packet_type,UINT header_size,VOID * context,struct NX_LINK_TIME_STRUCT * time_ptr)13491 static UINT _nx_bsd_ethernet_receive_notify(NX_IP *ip_ptr, UINT interface_index, NX_PACKET *packet_ptr,
13492 ULONG physical_address_msw, ULONG physical_address_lsw,
13493 UINT packet_type, UINT header_size, VOID *context,
13494 struct NX_LINK_TIME_STRUCT *time_ptr)
13495 {
13496 UINT i;
13497 UINT sockid = NX_BSD_MAX_SOCKETS;
13498 NX_BSD_SOCKET *bsd_ptr;
13499
13500
13501 /* Find the socket with the matching interface. Put the packet into the socket's recevie queue. */
13502 for(i = 0; i < NX_BSD_MAX_SOCKETS; i++)
13503 {
13504 if((nx_bsd_socket_array[i].nx_bsd_socket_status_flags & NX_BSD_SOCKET_IN_USE) &&
13505 (nx_bsd_socket_array[i].nx_bsd_socket_family == AF_PACKET) &&
13506 ((nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface == NX_BSD_LOCAL_IF_INADDR_ANY) ||
13507 (nx_bsd_socket_array[i].nx_bsd_socket_local_bind_interface == (ULONG)(packet_ptr -> nx_packet_ip_interface))))
13508 {
13509 sockid = i;
13510 }
13511 }
13512 if(sockid == NX_BSD_MAX_SOCKETS)
13513 {
13514 /* No BSD sockets are avaialble for this frame type. */
13515 return(NX_SOC_ERROR);
13516 }
13517 /* Now we need to put the packet into the socket. */
13518 bsd_ptr = &nx_bsd_socket_array[sockid];
13519
13520 /* Drop the packet if the receive queue exceeds max depth. */
13521 if(bsd_ptr -> nx_bsd_socket_received_packet_count >=
13522 bsd_ptr -> nx_bsd_socket_received_packet_count_max)
13523 {
13524 return(NX_SOC_ERROR);
13525 }
13526
13527 #ifndef NX_DISABLE_BSD_RAW_PACKET_DUPLICATE
13528 /* Duplicate the packet. */
13529 if (nx_packet_copy(packet_ptr, &packet_ptr, nx_bsd_default_packet_pool, NX_NO_WAIT) != NX_SUCCESS)
13530 {
13531 return(NX_SOC_ERROR);
13532 }
13533
13534 #endif /* NX_DISABLE_BSD_RAW_PACKET_DUPLICATE */
13535
13536 #ifdef NX_ENABLE_VLAN
13537 if (header_size == NX_LINK_ETHERNET_HEADER_SIZE + NX_LINK_VLAN_HEADER_SIZE)
13538 {
13539 memmove(packet_ptr -> nx_packet_prepend_ptr + NX_LINK_VLAN_HEADER_SIZE,
13540 packet_ptr -> nx_packet_prepend_ptr,
13541 NX_LINK_ETHERNET_HEADER_SIZE - 2); /* use case of memmove is verified. */
13542 packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - NX_LINK_VLAN_HEADER_SIZE;
13543 packet_ptr -> nx_packet_prepend_ptr += NX_LINK_VLAN_HEADER_SIZE;
13544 }
13545 #endif /* NX_ENABLE_VLAN */
13546
13547 if(bsd_ptr -> nx_bsd_socket_received_packet)
13548 {
13549 bsd_ptr -> nx_bsd_socket_received_packet_tail -> nx_packet_queue_next = packet_ptr;
13550 }
13551 else
13552 {
13553 bsd_ptr -> nx_bsd_socket_received_packet = packet_ptr;
13554 bsd_ptr -> nx_bsd_socket_received_packet_offset = 0;
13555 }
13556
13557 bsd_ptr -> nx_bsd_socket_received_packet_tail = packet_ptr;
13558 bsd_ptr -> nx_bsd_socket_received_byte_count += packet_ptr -> nx_packet_length;
13559 bsd_ptr -> nx_bsd_socket_received_packet_count ++;
13560
13561 nx_bsd_select_wakeup(sockid, FDSET_READ);
13562
13563 return(NX_SUCCESS);
13564
13565 }
13566 #endif
13567 #endif /* NX_BSD_RAW_SUPPORT */
13568
13569
13570
13571 /**************************************************************************/
13572 /* */
13573 /* FUNCTION RELEASE */
13574 /* */
13575 /* inet_pton PORTABLE C */
13576 /* 6.3.0 */
13577 /* AUTHOR */
13578 /* */
13579 /* Yuxin Zhou, Microsoft Corporation */
13580 /* */
13581 /* DESCRIPTION */
13582 /* */
13583 /* This function converts an IP address from presentation to numeric. */
13584 /* */
13585 /* INPUT */
13586 /* */
13587 /* af Either AF_INET or AF_INET6 */
13588 /* src A pointer pointing to the */
13589 /* presentation of IP address */
13590 /* dst A pointer pointing to the */
13591 /* destination memory */
13592 /* */
13593 /* OUTPUT */
13594 /* */
13595 /* status 1 OK */
13596 /* 0 invalid presentation */
13597 /* -1 error */
13598 /* */
13599 /* CALLS */
13600 /* */
13601 /* inet_aton Convert IPv4 address from */
13602 /* presentation to numeric */
13603 /* */
13604 /* CALLED BY */
13605 /* */
13606 /* Application Code */
13607 /* */
13608 /* RELEASE HISTORY */
13609 /* */
13610 /* DATE NAME DESCRIPTION */
13611 /* */
13612 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13613 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13614 /* resulting in version 6.1 */
13615 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
13616 /* used new API/structs naming,*/
13617 /* resulting in version 6.3.0 */
13618 /* */
13619 /**************************************************************************/
nx_bsd_inet_pton(INT af,const CHAR * src,VOID * dst)13620 INT nx_bsd_inet_pton(INT af, const CHAR *src, VOID *dst)
13621 {
13622 CHAR ch;
13623 USHORT value;
13624 /* A number used to convert a character in '0123456789abcdefABCDEF' to a number. */
13625 UINT minuend;
13626 /* A counter used to recoder the number of digits between 2 colons. */
13627 UINT digit_counter;
13628
13629 UCHAR *colon_location;
13630 /* A pointer used to traverse the destination memory. */
13631 UCHAR *dst_cur_ptr;
13632 /* A pointer to the end of the destination memory. */
13633 UCHAR *dst_end_ptr;
13634 ULONG *dst_long_ptr;
13635
13636 const CHAR *ipv4_addr_start = src;
13637 UINT n, i;
13638
13639 struct nx_bsd_in_addr ipv4_addr;
13640
13641 if(af == AF_INET)
13642 {
13643 /* Convert IPv4 address from presentation to numeric. */
13644 if(nx_bsd_inet_aton(src, &ipv4_addr))
13645 {
13646 /* Copy the IPv4 address to the destination. */
13647 *((ULONG *)dst) = ipv4_addr.s_addr;
13648 return 1;
13649 }
13650 return 0;
13651 }
13652 else if(af == AF_INET6)
13653 {
13654 /* If : is at the beginning, the next value must be : .*/
13655 if(*src == ':')
13656 if(*src++ != ':')
13657 return 0;
13658
13659 /* Initialization. */
13660 value = 0;
13661 digit_counter = 0;
13662 colon_location = NX_NULL;
13663 dst_cur_ptr = dst;
13664 /* Calculate the end of the destination memory. */
13665 dst_end_ptr = (UCHAR*)dst + 15;
13666 /* Clear the destination memory. */
13667 memset(dst_cur_ptr, 0, 16);
13668
13669 while(*src != 0)
13670 {
13671 /* Get the current character. */
13672 ch = *src++;
13673
13674 /* Judge which minuend to use.
13675 * '0' - 48 == 0
13676 * 'a' - 87 == 10
13677 * 'A' - 55 == 10
13678 */
13679 minuend = 0;
13680 if(ch >= '0' && ch <= '9')
13681 minuend = 48;
13682 else if(ch >= 'a' && ch <= 'f')
13683 minuend = 87;
13684 else if(ch >= 'A' && ch <= 'F')
13685 minuend = 55;
13686
13687 /* if minuend is not 0, then ch is character in "0123456789abcdefABCDEF" */
13688 if(minuend)
13689 {
13690 /* Convert the character to number. */
13691 value = (USHORT)(value << 4);
13692 value = (USHORT)(value | ((UINT)ch - minuend));
13693
13694 /* The max number of digits between 2 colons is 4. */
13695 if(++digit_counter > 4)
13696 return 0;
13697
13698 continue;
13699 }
13700
13701 if(ch == ':')
13702 {
13703 ipv4_addr_start = src;
13704
13705 /* Is there a digit before the colon? */
13706 if(!digit_counter)
13707 {
13708 /* There is no digit before the colon. */
13709
13710 /* If there are 2 "::", Invalid Presentation Format.
13711 * IF there is a ":::", Invalid Presention Format. */
13712 if(colon_location)
13713 return 0;
13714
13715 /* Record the colon location. */
13716 colon_location = dst_cur_ptr;
13717 continue;
13718 }
13719 else if(*src == '\0')
13720 {
13721 /* The colon is at the end of src, Invalid Presention Format. */
13722 return 0;
13723 }
13724
13725 if(dst_cur_ptr + 1 > dst_end_ptr)
13726 {
13727 /* Invalid Presentation Format. */
13728 return 0;
13729 }
13730
13731 /* Store the value to the dst memory. */
13732 *(dst_cur_ptr++) = (UCHAR) (value >> 8) & 0xff;
13733 *(dst_cur_ptr++) = (UCHAR) (value) & 0xff;
13734
13735 /* Reset the value and digit counter. */
13736 digit_counter = 0;
13737 value = 0;
13738
13739 continue;
13740
13741 }
13742 else if(ch == '.')
13743 {
13744 /* Process the dotted-decimal string in IPv4-mapped IPv6 address and IPv4-compatible IPv6 address. */
13745
13746 if(dst_cur_ptr + 3 > dst_end_ptr)
13747 {
13748 /* Invalid Presentation Format. */
13749 return 0;
13750 }
13751
13752 /* Convert the ipv4 address from presentation to numeric. */
13753 if(nx_bsd_inet_aton(ipv4_addr_start, &ipv4_addr))
13754 {
13755
13756 /* Make sure the result is in network byte order. */
13757 ipv4_addr.s_addr = ntohl(ipv4_addr.s_addr);
13758 NX_CHANGE_ULONG_ENDIAN(ipv4_addr.s_addr);
13759
13760 /* Store the value to the dst memory. */
13761 *(ULONG *)dst_cur_ptr = ipv4_addr.s_addr;
13762
13763 dst_cur_ptr += 4;
13764 digit_counter = 0;
13765
13766 break;
13767 }
13768 else
13769 return 0;
13770
13771
13772 }
13773 else
13774 {
13775 return 0;
13776 }
13777 }
13778
13779 if(digit_counter)
13780 {
13781
13782 /* Invalid Presentation Format. */
13783 if(dst_cur_ptr + 1 > dst_end_ptr)
13784 return 0;
13785
13786 /* Store the value to the dst memory. */
13787 *(dst_cur_ptr++) = (UCHAR) (value >> 8) & 0xff;
13788 *(dst_cur_ptr++) = (UCHAR) (value) & 0xff;
13789
13790 }
13791
13792 if(colon_location)
13793 {
13794 /* There is a :: in the IPv6 address presentation. */
13795
13796 /* Calculate how many octets should be moved to the end of the dst memory. */
13797 n = (UINT)(dst_cur_ptr - colon_location);
13798
13799 if(dst_cur_ptr == dst_end_ptr)
13800 return 0;
13801
13802 /* Move the data to the end of dst memory.
13803 * ----------- -----------
13804 * |aabb0000000| ----> |aa0000000bb|
13805 * ----------- -----------
13806 */
13807 for(i = 1; i <=n; i++)
13808 {
13809 *(dst_end_ptr--) = colon_location[n - i];
13810 colon_location[n-i] = 0;
13811 }
13812
13813 dst_cur_ptr = dst_end_ptr + 1;
13814 }
13815
13816 if(dst_cur_ptr != (dst_end_ptr + 1))
13817 return 0;
13818
13819 dst_long_ptr = (ULONG *)dst;
13820
13821 /* First convert it to host byte order. */
13822 NX_CHANGE_ULONG_ENDIAN(dst_long_ptr[0]);
13823 NX_CHANGE_ULONG_ENDIAN(dst_long_ptr[1]);
13824 NX_CHANGE_ULONG_ENDIAN(dst_long_ptr[2]);
13825 NX_CHANGE_ULONG_ENDIAN(dst_long_ptr[3]);
13826
13827 /* Convert it to network byte order by BSD macros. */
13828 dst_long_ptr[0] = htonl(dst_long_ptr[0]);
13829 dst_long_ptr[1] = htonl(dst_long_ptr[1]);
13830 dst_long_ptr[2] = htonl(dst_long_ptr[2]);
13831 dst_long_ptr[3] = htonl(dst_long_ptr[3]);
13832 return 1;
13833 }
13834 else
13835 {
13836 /* Error. */
13837 return -1;
13838 }
13839 }
13840
13841 /**************************************************************************/
13842 /* */
13843 /* FUNCTION RELEASE */
13844 /* */
13845 /* inet_ntop PORTABLE C */
13846 /* 6.3.0 */
13847 /* AUTHOR */
13848 /* */
13849 /* Yuxin Zhou, Microsoft Corporation */
13850 /* */
13851 /* DESCRIPTION */
13852 /* */
13853 /* This function converts an IP address from numeric to presentation. */
13854 /* */
13855 /* INPUT */
13856 /* */
13857 /* af Either AF_INET or AF_INET6 */
13858 /* src A void pointer pointing to */
13859 /* network byte order IP address*/
13860 /* dst A char pointer pointing to */
13861 /* the destination buffer */
13862 /* size The size of the destination */
13863 /* buffer */
13864 /* */
13865 /* OUTPUT */
13866 /* */
13867 /* dst The destination buffer */
13868 /* */
13869 /* CALLS */
13870 /* */
13871 /* inet_ntoa_internal Convert IPv4 address from */
13872 /* numeric to presentation */
13873 /* */
13874 /* CALLED BY */
13875 /* */
13876 /* Application Code */
13877 /* */
13878 /* RELEASE HISTORY */
13879 /* */
13880 /* DATE NAME DESCRIPTION */
13881 /* */
13882 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
13883 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
13884 /* resulting in version 6.1 */
13885 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
13886 /* used new API/structs naming,*/
13887 /* resulting in version 6.3.0 */
13888 /* */
13889 /**************************************************************************/
nx_bsd_inet_ntop(INT af,const VOID * src,CHAR * dst,nx_bsd_socklen_t size)13890 const CHAR *nx_bsd_inet_ntop(INT af, const VOID *src, CHAR *dst, nx_bsd_socklen_t size)
13891 {
13892
13893 INT shorthand_index;
13894 INT shorthand_len;
13895 INT current_index;
13896 INT current_len;
13897
13898 INT i;
13899 INT index;
13900 UINT rt_size;
13901
13902
13903 if(af == AF_INET)
13904 {
13905 /* Convert IPv4 address from numeric to presentation. */
13906 if(inet_ntoa_internal(src, dst, size))
13907 return dst;
13908 else
13909 return NX_NULL;
13910 }
13911 else if(af == AF_INET6)
13912 {
13913 USHORT temp[8];
13914 temp[0] = (USHORT)(ntohl(*((ULONG *)src)) >> 16);
13915 temp[1] = (USHORT)(ntohl(*((ULONG *)src)) & 0xFFFF);
13916 temp[2] = (USHORT)(ntohl(*(((ULONG *)src) + 1)) >> 16);
13917 temp[3] = (USHORT)(ntohl(*(((ULONG *)src) + 1)) & 0xFFFF);
13918 temp[4] = (USHORT)(ntohl(*(((ULONG *)src) + 2)) >> 16);
13919 temp[5] = (USHORT)(ntohl(*(((ULONG *)src) + 2)) & 0xFFFF);
13920 temp[6] = (USHORT)(ntohl(*(((ULONG *)src) + 3)) >> 16);
13921 temp[7] = (USHORT)(ntohl(*(((ULONG *)src) + 3)) & 0xFFFF);
13922
13923 /* Initialization. */
13924 shorthand_index = -1;
13925 shorthand_len = 0;
13926 current_index = -1;
13927 current_len = 0;
13928
13929 /* Find the longest 0x00 in src for ::
13930 * 16 * 8 == 128 */
13931 for(i = 0; i < 8; i++)
13932 {
13933 if(temp[i] == 0)
13934 {
13935 if(current_index == -1)
13936 {
13937 /* Record the index of 0x00, Initialize the length to 1. */
13938 current_index = i;
13939 current_len = 1;
13940 }
13941 else
13942 {
13943 current_len++;
13944 }
13945 }
13946 else
13947 {
13948 /* Not 0x00 . */
13949
13950 if(current_index != -1)
13951 {
13952 /* Not equal -1, means there is record of 0x00s . */
13953
13954 if(shorthand_index == -1 || current_len > shorthand_len)
13955 {
13956 /* Record the longest 0x00s. */
13957 shorthand_index = current_index;
13958 shorthand_len = current_len;
13959 }
13960
13961 /* Reset the index. */
13962 current_index = -1;
13963 }
13964
13965 }
13966 }
13967
13968
13969 if(current_len > shorthand_len)
13970 {
13971 /* Record the longest 0x00s. */
13972 shorthand_index = current_index;
13973 shorthand_len = current_len;
13974 }
13975
13976 /* If length is less than 2, no need for shorthand. */
13977 if(shorthand_len < 2)
13978 {
13979 shorthand_index = -1;
13980 }
13981
13982 index = 0;
13983 /* Format the result. */
13984 for(i = 0; i < 8; i++)
13985 {
13986 /* Is i in the range of :: */
13987 if((shorthand_index != -1) &&
13988 (i >= shorthand_index) &&
13989 (i < (shorthand_index + shorthand_len)))
13990 {
13991 if(i == shorthand_index)
13992 {
13993 /* Check if there is enough memory to store a character. */
13994 if((size - (ULONG)index) < 1)
13995 return NX_NULL;
13996
13997 dst[index++] = ':';
13998 }
13999 continue;
14000 }
14001
14002 if(i != 0)
14003 {
14004 /* Check if there is enough memory to store a character. */
14005 if((size - (ULONG)index) < 1)
14006 return NX_NULL;
14007
14008 dst[index++] = ':';
14009 }
14010
14011 /* Does this address contain IPv4 address. */
14012 if(i == 6 && shorthand_index == 0 &&
14013 (shorthand_len == 6 || /* IPv4-mapped IPv6 address -----> ::1.2.3.4 */
14014 (shorthand_len == 5 && temp[5] == 0xffff))) /* IPv4-compatible IPv6 address -----> ::ffff:1.2.3.4 */
14015 {
14016 /* Convert ipv4 address to string. 12 == 16 - 4*/
14017 rt_size = (UINT)inet_ntoa_internal((UCHAR*)src + 12, &dst[index], size - (ULONG)index);
14018
14019 /* Check the return size, 0 means error. */
14020 if(rt_size)
14021 index += (INT)rt_size;
14022 else
14023 return NX_NULL;
14024 }
14025
14026 /* Convert hex number to string */
14027 rt_size = bsd_number_convert(temp[i], &dst[index], size - (ULONG)index, 16);
14028 if(!rt_size)
14029 return NX_NULL;
14030
14031 /* Increment the index. */
14032 index += (INT)rt_size;
14033
14034 }
14035
14036 /* Is there a trailing : */
14037 if((shorthand_index != -1) && (shorthand_index + shorthand_len == 8))
14038 {
14039 /* Check if there is enough memory to store a character. */
14040 if((size - (ULONG)index) < 1)
14041 return NX_NULL;
14042
14043 dst[index++] = ':';
14044
14045 }
14046
14047 /* Check if there is enough memory to store a character. */
14048 if((size - (ULONG)index) < 1)
14049 return NX_NULL;
14050
14051 dst[index] = '\0';
14052
14053 return dst;
14054 }
14055 else
14056 {
14057 return NX_NULL;
14058 }
14059 }
14060
14061 /**************************************************************************/
14062 /* */
14063 /* FUNCTION RELEASE */
14064 /* */
14065 /* inet_ntoa_internal PORTABLE C */
14066 /* 6.1 */
14067 /* AUTHOR */
14068 /* */
14069 /* Yuxin Zhou, Microsoft Corporation */
14070 /* */
14071 /* DESCRIPTION */
14072 /* */
14073 /* This function converts an IPv4 address to a string and returns the */
14074 /* size of the string. */
14075 /* */
14076 /* INPUT */
14077 /* */
14078 /* src A void pointer pointing to */
14079 /* IPv4 address */
14080 /* dst A char pointer pointing to */
14081 /* the destination buffer */
14082 /* dst_size The size of the destination */
14083 /* buffer */
14084 /* */
14085 /* OUTPUT */
14086 /* */
14087 /* index The size of the IPv4 address */
14088 /* string */
14089 /* */
14090 /* CALLS */
14091 /* */
14092 /* memset Set the memory to 0 */
14093 /* bsd_number_convert Convert a number to string */
14094 /* */
14095 /* CALLED BY */
14096 /* */
14097 /* NetX Duo BSD Layer Source Code */
14098 /* */
14099 /* RELEASE HISTORY */
14100 /* */
14101 /* DATE NAME DESCRIPTION */
14102 /* */
14103 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14104 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
14105 /* resulting in version 6.1 */
14106 /* */
14107 /**************************************************************************/
14108
inet_ntoa_internal(const VOID * src,CHAR * dst,ULONG dst_size)14109 static INT inet_ntoa_internal(const VOID *src, CHAR *dst, ULONG dst_size)
14110 {
14111 ULONG temp;
14112 UINT size;
14113 UINT index = 0;
14114
14115
14116 /* Set a local pointer to move up the buffer. */
14117 temp = ntohl(*((ULONG *)src));
14118
14119 memset(dst, 0, dst_size);
14120
14121 /* Convert the first number to a string. */
14122 size = bsd_number_convert((temp >> 24), &dst[0], dst_size - index, 10);
14123
14124 if(!size)
14125 return 0;
14126
14127 /* Move up the index and buffer pointer. */
14128 index += size;
14129
14130 /* Check the rest of the dst buffer. */
14131 if((dst_size - index) < 1)
14132 return 0;
14133
14134 /* Add the decimal. */
14135 dst[index++] = '.';
14136
14137 /* And repeat three more times...*/
14138 size = bsd_number_convert((temp >> 16) & 0xff, &dst[index], dst_size - index, 10);
14139
14140 if(!size)
14141 return 0;
14142
14143 index += size;
14144
14145 if((dst_size - index) < 1)
14146 return 0;
14147
14148 dst[index++] = '.';
14149
14150 size = bsd_number_convert((temp >> 8) & 0xff, &dst[index], dst_size - index, 10);
14151
14152 if(!size)
14153 return 0;
14154
14155 index += size;
14156
14157 if((dst_size - index) < 1)
14158 return 0;
14159
14160 dst[index++] = '.';
14161
14162 size = bsd_number_convert(temp & 0xff, &dst[index], dst_size - index, 10);
14163
14164 if(!size)
14165 return 0;
14166
14167 index += size;
14168
14169 if((dst_size - index) < 1)
14170 return 0;
14171
14172 dst[index++] = '\0';
14173
14174 /* Return the size of the dst string. */
14175 return((INT)(index));
14176 }
14177
14178
14179 /**************************************************************************/
14180 /* */
14181 /* FUNCTION RELEASE */
14182 /* */
14183 /* getaddrinfo PORTABLE C */
14184 /* 6.3.0 */
14185 /* AUTHOR */
14186 /* */
14187 /* Yuxin Zhou, Microsoft Corporation */
14188 /* */
14189 /* DESCRIPTION */
14190 /* */
14191 /* This function returns one or more addrinfo structures according to */
14192 /* the specified node and service. */
14193 /* */
14194 /* INPUT */
14195 /* */
14196 /* node Node is either a hostname or */
14197 /* an address string(dotted- */
14198 /* decimal for IPv4 or a hex */
14199 /* string for IPv6). */
14200 /* service Service is either a service */
14201 /* name or a decimal port number*/
14202 /* string. */
14203 /* hints Hints is either a null pointer*/
14204 /* or a pointer to an addrinfo */
14205 /* structure that the caller */
14206 /* fills in with hints about the*/
14207 /* types of information the */
14208 /* caller wants returned. */
14209 /* res Pointer to the returned */
14210 /* addrinfo list. */
14211 /* */
14212 /* OUTPUT */
14213 /* */
14214 /* status 0 if OK, nonzero on errors */
14215 /* */
14216 /* CALLS */
14217 /* */
14218 /* bsd_string_to_number Convert a string to a number */
14219 /* htons Host byte order to network */
14220 /* byte order */
14221 /* memcmp Memory compare */
14222 /* inet_pton Convert IP address from */
14223 /* presentation to numeric */
14224 /* tx_block_allocate Allocate memory for address or*/
14225 /* addrinfo */
14226 /* memset Set the memory to 0 */
14227 /* freeaddrinfo Release addrinfo memory */
14228 /* nx_dns_ipv4_address_by_name_get Get ipv4 addr by name via dns */
14229 /* nxd_dns_ipv6_address_by_name_get Get ipv6 addr by name via dns */
14230 /* */
14231 /* CALLED BY */
14232 /* */
14233 /* Application Code */
14234 /* */
14235 /* RELEASE HISTORY */
14236 /* */
14237 /* DATE NAME DESCRIPTION */
14238 /* */
14239 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14240 /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */
14241 /* buffer length verification, */
14242 /* verified memcpy use cases, */
14243 /* fixed compiler errors, */
14244 /* resulting in version 6.1 */
14245 /* 07-29-2022 Yuxin Zhou Modified comment(s), and */
14246 /* fixed compiler warnings, */
14247 /* resulting in version 6.1.12 */
14248 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
14249 /* used new API/structs naming,*/
14250 /* resulting in version 6.3.0 */
14251 /* */
14252 /**************************************************************************/
nx_bsd_getaddrinfo(const CHAR * node,const CHAR * service,const struct nx_bsd_addrinfo * hints,struct nx_bsd_addrinfo ** res)14253 INT nx_bsd_getaddrinfo(const CHAR *node, const CHAR *service, const struct nx_bsd_addrinfo *hints, struct nx_bsd_addrinfo **res)
14254 {
14255
14256 UINT status;
14257 #ifdef NX_BSD_ENABLE_DNS
14258 UINT status2;
14259 #endif
14260 UINT pton_flag;
14261 UINT port;
14262 UINT i, j;
14263 INT addr_family;
14264 UINT ipv4_addr_count = 0;
14265 UINT ipv6_addr_count = 0;
14266 UINT match_service_count;
14267 UINT match_service_socktype[3];
14268 UINT match_service_protocol[3];
14269 struct nx_bsd_addrinfo
14270 *addrinfo_cur_ptr = NX_NULL;
14271 struct nx_bsd_addrinfo
14272 *addrinfo_head_ptr = NX_NULL;
14273 struct nx_bsd_addrinfo
14274 *addrinfo_tail_ptr = NX_NULL;
14275 struct nx_bsd_sockaddr
14276 *sockaddr_ptr = NX_NULL;
14277 UCHAR *cname_buffer = NX_NULL;
14278
14279 /* When hints is a null pointer, use the default value below. */
14280 static struct nx_bsd_addrinfo default_hints = {0, AF_UNSPEC, 0, 0, 0, NX_NULL, NX_NULL, NX_NULL};
14281
14282
14283
14284 /* if node and service are null return an error, invalid input. */
14285 if((node == NX_NULL) && (service == NX_NULL))
14286 return EAI_NONAME;
14287
14288 if(hints)
14289 {
14290
14291 /* Check if the address family is valid. */
14292 if((hints -> ai_family != AF_INET) &&
14293 (hints -> ai_family != AF_INET6) &&
14294 (hints -> ai_family != AF_UNSPEC))
14295 return EAI_FAMILY;
14296
14297 /* Check if the socket type is valid. */
14298 if((hints -> ai_socktype != SOCK_DGRAM) &&
14299 (hints -> ai_socktype != SOCK_STREAM) &&
14300 (hints -> ai_socktype != 0))
14301 return EAI_SOCKTYPE;
14302
14303 /* If socktype and protocol are both specified, check if they are meaningful. */
14304 if((hints -> ai_socktype != 0) && (hints -> ai_protocol != 0))
14305 {
14306 if(((hints -> ai_socktype == SOCK_STREAM) && (hints -> ai_protocol != IPPROTO_TCP)) ||
14307 ((hints -> ai_socktype == SOCK_DGRAM) && (hints -> ai_protocol != IPPROTO_UDP)) ||
14308 ((hints -> ai_socktype == SOCK_RAW) && (hints -> ai_protocol != IPPROTO_RAW)))
14309 return EAI_SOCKTYPE;
14310 }
14311
14312 }
14313 else
14314 {
14315 hints = &default_hints;
14316 }
14317
14318 /* Sock type specified? */
14319 if(hints -> ai_socktype == 0)
14320 {
14321
14322 /* No; is protocol specified? */
14323 if(hints -> ai_protocol == 0)
14324 {
14325
14326 /* No, protocol is not specified. */
14327
14328 /* Set default socktype and protocol. */
14329 match_service_count = 3;
14330 match_service_socktype[0] = SOCK_STREAM;
14331 match_service_protocol[0] = IPPROTO_TCP;
14332 match_service_socktype[1] = SOCK_DGRAM;
14333 match_service_protocol[1] = IPPROTO_UDP;
14334 match_service_socktype[2] = SOCK_RAW;
14335 match_service_protocol[2] = 0;
14336 }
14337 else
14338 {
14339
14340 /* protocol is specified. */
14341 match_service_count = 1;
14342 match_service_protocol[0] = (UINT)(hints -> ai_protocol);
14343
14344 /* Set default socktype according to protocol. */
14345 if(hints -> ai_protocol == IPPROTO_TCP)
14346 match_service_socktype[0] = SOCK_STREAM;
14347 else if(hints -> ai_protocol == IPPROTO_UDP)
14348 match_service_socktype[0] = SOCK_DGRAM;
14349 }
14350 }
14351 else
14352 {
14353
14354 /* Socktype is specified. */
14355 match_service_count = 1;
14356 match_service_socktype[0] = (UINT)(hints -> ai_socktype);
14357
14358 if(hints -> ai_protocol == 0)
14359 {
14360
14361 /* Protocol is not specified. */
14362
14363 /* Set default protocol according to socktype. */
14364 if(hints -> ai_socktype == SOCK_STREAM)
14365 match_service_protocol[0] = IPPROTO_TCP;
14366 else if(hints -> ai_socktype == SOCK_DGRAM)
14367 match_service_protocol[0] = IPPROTO_UDP;
14368 else if(hints -> ai_socktype == SOCK_RAW)
14369 match_service_protocol[0] = 0;
14370 }
14371 else
14372 {
14373
14374 /* Protocol is specififed. */
14375 match_service_protocol[0] = (UINT)(hints -> ai_protocol);
14376 }
14377 }
14378
14379 if(service)
14380 {
14381
14382 /* Service is not null. */
14383 if(bsd_string_to_number(service, &port) != NX_SOC_ERROR)
14384 {
14385
14386 /* Service is a decimal port number string, and has been converted to a numeric port successfully. */
14387
14388 /* Convert port from host byte order to network byte order. */
14389 port = htons((USHORT)port);
14390 }
14391 else
14392 {
14393
14394 /* Service is an address name, not a decimal port number string. */
14395
14396 /* Check if numeric service flag is set. If so this is an invalid string. */
14397 if(hints -> ai_flags & AI_NUMERICSERV)
14398 return EAI_NONAME;
14399
14400 match_service_count = 0;
14401
14402 /* Look for a match of name, protocol and socket type for a match in the service list. */
14403 for(i = 0; i < _nx_bsd_serv_list_len; i++)
14404 {
14405
14406 /* Check if there is a match. */
14407 if(!memcmp(_nx_bsd_serv_list_ptr[i].service_name, service, _nx_bsd_string_length((CHAR *)service)) &&
14408 ((_nx_bsd_serv_list_ptr[i].service_socktype == hints -> ai_socktype) ||(hints -> ai_socktype == 0)) &&
14409 ((_nx_bsd_serv_list_ptr[i].service_protocol == hints -> ai_protocol) ||(hints -> ai_protocol == 0)))
14410 {
14411 match_service_socktype[match_service_count] = (UINT)(_nx_bsd_serv_list_ptr[i].service_socktype);
14412 match_service_protocol[match_service_count++] = (UINT)(_nx_bsd_serv_list_ptr[i].service_protocol);
14413
14414 /* Convert host byte order to network byte order. */
14415 port = htons(_nx_bsd_serv_list_ptr[i].service_port);
14416 }
14417 }
14418
14419 /* Service is not available. */
14420 if(match_service_count == 0)
14421 return EAI_SERVICE;
14422 }
14423 }
14424 else
14425 {
14426
14427 /* Convert host byte order to network byte order. */
14428 port = htons(0);
14429 }
14430
14431 if(node)
14432 {
14433
14434 /* Node is not null. */
14435
14436 /* Determine the address family. */
14437 addr_family = AF_INET;
14438
14439 for(i = 0; i < _nx_bsd_string_length((CHAR *)node); i++)
14440 {
14441 if(node[i] == ':')
14442 {
14443 /* There is a colon, so it is an IPv6 address. */
14444 addr_family = AF_INET6;
14445 break;
14446 }
14447 }
14448
14449 /* Initialize to 0, default to pton failing. */
14450 pton_flag = 0;
14451
14452 if(addr_family == AF_INET)
14453 {
14454
14455 /* Convert node from a string presentation to a numeric address. */
14456 if(nx_bsd_inet_pton(addr_family, node, &(nx_bsd_ipv4_addr_buffer[0])) == 1)
14457 {
14458 /* pton has successful completion. */
14459 pton_flag = 1;
14460
14461 /* Check if the address and the specified family match. */
14462 if((hints -> ai_family != AF_INET) && (hints -> ai_family != AF_UNSPEC))
14463 return EAI_ADDRFAMILY;
14464
14465 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv4_addr_buffer[0]);
14466 ipv4_addr_count = 1;
14467 }
14468 }
14469 else
14470 {
14471
14472 /* Convert node from a string presentation to a numeric address. */
14473 if(nx_bsd_inet_pton(addr_family, node, &(nx_bsd_ipv6_addr_buffer[0])) == 1)
14474 {
14475 /* pton completed successfully. */
14476 pton_flag = 1;
14477
14478 /* Check is the address and the specified family matches. */
14479 if((hints -> ai_family != AF_INET6) && (hints -> ai_family != AF_UNSPEC))
14480 return EAI_ADDRFAMILY;
14481
14482 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv6_addr_buffer[0]);
14483 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv6_addr_buffer[1]);
14484 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv6_addr_buffer[2]);
14485 NX_CHANGE_ULONG_ENDIAN(nx_bsd_ipv6_addr_buffer[3]);
14486 ipv6_addr_count = 1;
14487 }
14488 }
14489
14490 if(pton_flag == 1)
14491 {
14492
14493 /* pton completed successfull. Host (node) is an address string. */
14494
14495 #if defined(NX_BSD_ENABLE_DNS) && defined (NX_DNS_ENABLE_EXTENDED_RR_TYPES)
14496 /* DNS supports extended services including Canonical name queries. */
14497 if((hints -> ai_flags & AI_CANONNAME) && !(hints -> ai_flags & AI_NUMERICHOST))
14498 {
14499
14500 /* Allocate a block for canonical name. */
14501 status = tx_block_allocate(&nx_bsd_cname_block_pool, (VOID *) &cname_buffer, NX_BSD_TIMEOUT);
14502
14503 /* Check for error status. */
14504 if (status != TX_SUCCESS)
14505 {
14506 /* Set the error. */
14507 nx_bsd_set_errno(ENOMEM);
14508
14509 /* Error getting NetX socket memory. */
14510 NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
14511
14512 /* Return memory allocation error. */
14513 return(EAI_MEMORY);
14514 }
14515
14516 /* Verify buffer size. */
14517 if (_nx_bsd_string_length((CHAR *)node) > NX_DNS_NAME_MAX)
14518 return(EAI_OVERFLOW);
14519
14520 memcpy(cname_buffer, node, _nx_bsd_string_length((CHAR *)node)); /* Use case of memcpy is verified. */
14521
14522 }
14523 #endif /* NX_BSD_ENABLE_DNS && NX_DNS_ENABLE_EXTENDED_RR_TYPES */
14524
14525 }
14526 else
14527 {
14528
14529 /* Presentation to numeric format fails, node may be a hostname, not a numeric IP address. */
14530
14531 /* Check if numeric host flag is set. */
14532 if(hints -> ai_flags & AI_NUMERICHOST)
14533 return EAI_NONAME;
14534
14535 #ifdef NX_BSD_ENABLE_DNS
14536 if(hints -> ai_family == AF_INET)
14537 {
14538
14539 /* Get IPv4 address by hostname. */
14540 status = nx_dns_ipv4_address_by_name_get(_nx_dns_instance_ptr, (UCHAR *)node, &nx_bsd_ipv4_addr_buffer[0],
14541 NX_BSD_IPV4_ADDR_PER_HOST * 4, &ipv4_addr_count, NX_BSD_TIMEOUT);
14542
14543 if(status != NX_SUCCESS)
14544 {
14545
14546 /* Just return EAI_FAIL, because we can't discriminate between DNS FAIL and the situation where the specified
14547 network host exists but does not have any network addresses defined. It would be better to return EAI_FAIL
14548 for DNS FAIL, and EAI_NODATA for the latter situation. */
14549 return EAI_FAIL;
14550 }
14551 }
14552 else if(hints -> ai_family == AF_INET6)
14553 {
14554
14555 /* Get IPv6 address by hostname. */
14556 status = nxd_dns_ipv6_address_by_name_get(_nx_dns_instance_ptr, (UCHAR *)node, &nx_bsd_ipv6_addr_buffer[0],
14557 NX_BSD_IPV6_ADDR_PER_HOST * 16, &ipv6_addr_count, NX_BSD_TIMEOUT);
14558
14559 if(status != NX_SUCCESS)
14560 {
14561 /* Just return EAI_FAIL, because we can't discriminate between DNS FAIL and the situation where the specified
14562 network host exists but does not have any network addresses defined. It would be better to return EAI_FAIL
14563 for DNS FAIL, and EAI_NODATA for the latter situation. */
14564 return EAI_FAIL;
14565 }
14566 }
14567 else
14568 {
14569
14570 /* Address family is not specified. Query for both IPv4 and IPv6 address. */
14571
14572 /* Get IPv4 address by hostname. */
14573 status = nx_dns_ipv4_address_by_name_get(_nx_dns_instance_ptr, (UCHAR *)node, &nx_bsd_ipv4_addr_buffer[0],
14574 NX_BSD_IPV4_ADDR_PER_HOST * 4, &ipv4_addr_count, NX_BSD_TIMEOUT);
14575
14576 /* Get IPv6 address by hostname. */
14577 status2 = nxd_dns_ipv6_address_by_name_get(_nx_dns_instance_ptr, (UCHAR *)node, &nx_bsd_ipv6_addr_buffer[0],
14578 NX_BSD_IPV6_ADDR_PER_HOST * 16, &ipv6_addr_count, NX_BSD_TIMEOUT);
14579
14580 if((status != NX_SUCCESS) && status2 != NX_SUCCESS)
14581 {
14582 /* Just return EAI_FAIL, because we can't discriminate between DNS FAIL and the situation that the specified
14583 network host exists, but does not have any network addresses defined. It would be better to return EAI_FAIL
14584 for DNS FAIL, and EAI_NODATA for the latter situation. */
14585 return EAI_FAIL;
14586 }
14587 }
14588
14589 if(hints -> ai_flags & AI_CANONNAME)
14590 {
14591
14592 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14593 /* Allocate a block for canonical name. */
14594 status = tx_block_allocate(&nx_bsd_cname_block_pool, (VOID *) &cname_buffer, NX_BSD_TIMEOUT);
14595
14596 /* Check for error status. */
14597 if (status != TX_SUCCESS)
14598 {
14599 /* Set the error. */
14600 set_errno(ENOMEM);
14601
14602 /* Error getting NetX socket memory. */
14603 NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
14604
14605 /* Return memory allocation error. */
14606 return(EAI_MEMORY);
14607 }
14608
14609 status = nx_dns_cname_get(_nx_dns_instance_ptr, (UCHAR *)node, cname_buffer,
14610 nx_bsd_cname_block_pool.tx_block_pool_block_size, NX_BSD_TIMEOUT);
14611 if(status != NX_SUCCESS)
14612 {
14613
14614 /* Verify buffer size. */
14615 if (_nx_bsd_string_length((CHAR *)node) > NX_DNS_NAME_MAX)
14616 return(EAI_OVERFLOW);
14617
14618 memcpy(cname_buffer, node, _nx_bsd_string_length((CHAR *)node)); /* Use case of memcpy is verified. */
14619 }
14620
14621 #else
14622 cname_buffer = (UCHAR *)node;
14623 #endif
14624 }
14625 #else
14626 return EAI_FAIL;
14627 #endif
14628
14629 }
14630 }
14631 else
14632 {
14633
14634 /* Node is null. */
14635 if(hints -> ai_flags & AI_PASSIVE)
14636 {
14637 /* The caller wiil use the socket for a passive open. */
14638
14639 nx_bsd_ipv4_addr_buffer[0] = INADDR_ANY;
14640
14641 nx_bsd_ipv6_addr_buffer[0] = 0;
14642 nx_bsd_ipv6_addr_buffer[1] = 0;
14643 nx_bsd_ipv6_addr_buffer[2] = 0;
14644 nx_bsd_ipv6_addr_buffer[3] = 0;
14645 }
14646 else
14647 {
14648
14649 /* Localhost address. */
14650 nx_bsd_ipv4_addr_buffer[0] = 0x7F000001;
14651
14652 nx_bsd_ipv6_addr_buffer[0] = 0;
14653 nx_bsd_ipv6_addr_buffer[1] = 0;
14654 nx_bsd_ipv6_addr_buffer[2] = 0;
14655 nx_bsd_ipv6_addr_buffer[3] = 1;
14656 }
14657
14658 if (hints -> ai_family != AF_INET6)
14659 {
14660 ipv4_addr_count = 1;
14661 }
14662 ipv6_addr_count = 1;
14663 }
14664
14665
14666 for(i = 0; i < ipv4_addr_count + ipv6_addr_count; i++)
14667 {
14668
14669 /* Allocate a block for ipv4 address. */
14670 status = tx_block_allocate(&nx_bsd_addrinfo_block_pool, (VOID *) &sockaddr_ptr, NX_BSD_TIMEOUT);
14671
14672 /* Check for error status. */
14673 if (status != TX_SUCCESS)
14674 {
14675
14676 /* Set the error. */
14677 nx_bsd_set_errno(ENOMEM);
14678
14679 /* If head is not null, free the memory. */
14680 if(addrinfo_head_ptr)
14681 nx_bsd_freeaddrinfo(addrinfo_head_ptr);
14682
14683 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14684 if(hints -> ai_flags & AI_CANONNAME)
14685 tx_block_release((VOID *)cname_buffer);
14686 #endif
14687
14688 /* Error getting NetX socket memory. */
14689 NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
14690
14691 /* Return memory allocation error. */
14692 return(EAI_MEMORY);
14693 }
14694
14695 /* Clear the memory. */
14696 memset((VOID*)sockaddr_ptr, 0, sizeof(struct nx_bsd_addrinfo));
14697
14698 if(i < ipv4_addr_count)
14699 {
14700
14701 /* Process IPv4 address. */
14702 ((struct nx_bsd_sockaddr_in*)sockaddr_ptr) -> sin_family = AF_INET;
14703 ((struct nx_bsd_sockaddr_in*)sockaddr_ptr) -> sin_port = (USHORT)port;
14704 ((struct nx_bsd_sockaddr_in*)sockaddr_ptr) -> sin_addr.s_addr = nx_bsd_ipv4_addr_buffer[i];
14705
14706 NX_CHANGE_ULONG_ENDIAN(((struct nx_bsd_sockaddr_in*)sockaddr_ptr) -> sin_addr.s_addr);
14707 }
14708 else
14709 {
14710
14711 /* Process IPv6 address. */
14712 ((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_family = AF_INET6;
14713 ((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_port = (USHORT)port;
14714 memcpy(&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr), &nx_bsd_ipv6_addr_buffer[(i - ipv4_addr_count)*4], 16); /* Use case of memcpy is verified. */
14715
14716 NX_CHANGE_ULONG_ENDIAN(*(ULONG*)&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr.s6_addr32[0]));
14717 NX_CHANGE_ULONG_ENDIAN(*(ULONG*)&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr.s6_addr32[1]));
14718 NX_CHANGE_ULONG_ENDIAN(*(ULONG*)&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr.s6_addr32[2]));
14719 NX_CHANGE_ULONG_ENDIAN(*(ULONG*)&(((struct nx_bsd_sockaddr_in6*)sockaddr_ptr) -> sin6_addr.s6_addr32[3]));
14720
14721 }
14722
14723 for(j = 0; j < match_service_count; j++)
14724 {
14725
14726 /* Allocate a block from the addrinfo block pool. */
14727 status = tx_block_allocate(&nx_bsd_addrinfo_block_pool, (VOID *) &addrinfo_cur_ptr, NX_BSD_TIMEOUT);
14728
14729 /* Check for error status. */
14730 if (status != TX_SUCCESS)
14731 {
14732
14733 /* Set the error. */
14734 nx_bsd_set_errno(ENOMEM);
14735
14736 /* If head is not null, free the memory. */
14737 if(addrinfo_head_ptr)
14738 nx_bsd_freeaddrinfo(addrinfo_head_ptr);
14739
14740 tx_block_release((VOID *)sockaddr_ptr);
14741
14742 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14743 if(hints -> ai_flags & AI_CANONNAME)
14744 tx_block_release((VOID *)cname_buffer);
14745 #endif
14746
14747 /* Error getting NetX socket memory. */
14748 NX_BSD_ERROR(NX_BSD_BLOCK_POOL_ERROR, __LINE__);
14749
14750 /* Return memory allocation error. */
14751 return(EAI_MEMORY);
14752 }
14753
14754 /* Clear the socket memory. */
14755 memset((VOID*)addrinfo_cur_ptr, 0, sizeof(struct nx_bsd_addrinfo));
14756
14757 if(i < ipv4_addr_count)
14758 {
14759
14760 /* IPv4 */
14761 addrinfo_cur_ptr -> ai_family = AF_INET;
14762 addrinfo_cur_ptr -> ai_addrlen = sizeof(struct nx_bsd_sockaddr_in);
14763 }
14764 else
14765 {
14766
14767 /* IPv6 */
14768 addrinfo_cur_ptr -> ai_family = AF_INET6;
14769 addrinfo_cur_ptr -> ai_addrlen = sizeof(struct nx_bsd_sockaddr_in6);
14770 }
14771
14772 addrinfo_cur_ptr -> ai_socktype = (INT)(match_service_socktype[j]);
14773 addrinfo_cur_ptr -> ai_protocol = (INT)(match_service_protocol[j]);
14774 addrinfo_cur_ptr -> ai_addr = sockaddr_ptr;
14775 if((i == 0) && (j == 0) && (hints -> ai_flags & AI_CANONNAME))
14776 addrinfo_cur_ptr -> ai_canonname = (CHAR *)cname_buffer;
14777 else
14778 addrinfo_cur_ptr -> ai_canonname = NX_NULL;
14779 addrinfo_cur_ptr -> ai_next = NX_NULL;
14780
14781 /* Make a list. */
14782 if(addrinfo_head_ptr == NX_NULL)
14783 addrinfo_head_ptr = addrinfo_cur_ptr;
14784 else
14785 addrinfo_tail_ptr -> ai_next = addrinfo_cur_ptr;
14786
14787 addrinfo_tail_ptr = addrinfo_cur_ptr;
14788
14789 }
14790 }
14791
14792 *res = addrinfo_head_ptr;
14793
14794 return 0;
14795 }
14796
14797 /**************************************************************************/
14798 /* */
14799 /* FUNCTION RELEASE */
14800 /* */
14801 /* freeaddrinfo PORTABLE C */
14802 /* 6.3.0 */
14803 /* AUTHOR */
14804 /* */
14805 /* Yuxin Zhou, Microsoft Corporation */
14806 /* */
14807 /* DESCRIPTION */
14808 /* */
14809 /* This function releases the memory allocated by getaddrinfo. */
14810 /* */
14811 /* INPUT */
14812 /* */
14813 /* res Pointer to a addrinfo struct */
14814 /* */
14815 /* OUTPUT */
14816 /* */
14817 /* None */
14818 /* */
14819 /* CALLS */
14820 /* */
14821 /* tx_block_release Release socket memory */
14822 /* */
14823 /* CALLED BY */
14824 /* */
14825 /* Application Code */
14826 /* */
14827 /* RELEASE HISTORY */
14828 /* */
14829 /* DATE NAME DESCRIPTION */
14830 /* */
14831 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14832 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
14833 /* resulting in version 6.1 */
14834 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
14835 /* used new API/structs naming,*/
14836 /* resulting in version 6.3.0 */
14837 /* */
14838 /**************************************************************************/
nx_bsd_freeaddrinfo(struct nx_bsd_addrinfo * res)14839 VOID nx_bsd_freeaddrinfo(struct nx_bsd_addrinfo *res)
14840 {
14841
14842 struct nx_bsd_addrinfo *next_addrinfo;
14843 struct nx_bsd_sockaddr *ai_addr_ptr = NX_NULL;
14844 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14845 CHAR *ai_canonname_ptr = NX_NULL;
14846 #endif
14847
14848 while(res)
14849 {
14850 #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES
14851 if((res -> ai_canonname) &&
14852 (res -> ai_canonname != ai_canonname_ptr))
14853 {
14854
14855 /* Release the CNAME memory. */
14856 tx_block_release((VOID *)res -> ai_canonname);
14857
14858 ai_canonname_ptr = res -> ai_canonname;
14859 }
14860 #endif
14861 if((res -> ai_addr) &&
14862 (res -> ai_addr != ai_addr_ptr))
14863 {
14864
14865 /* Release the address memory. */
14866 tx_block_release((VOID *)res -> ai_addr);
14867
14868 ai_addr_ptr = res -> ai_addr;
14869 }
14870
14871 /* Move next. */
14872 next_addrinfo = res -> ai_next;
14873
14874 /* Release the addrinfo memory. */
14875 tx_block_release((VOID *)res);
14876
14877 res = next_addrinfo;
14878 }
14879 }
14880
14881
14882 /**************************************************************************/
14883 /* */
14884 /* FUNCTION RELEASE */
14885 /* */
14886 /* bsd_string_to_number PORTABLE C */
14887 /* 6.1 */
14888 /* AUTHOR */
14889 /* */
14890 /* Yuxin Zhou, Microsoft Corporation */
14891 /* */
14892 /* DESCRIPTION */
14893 /* */
14894 /* This function converts string to number. */
14895 /* */
14896 /* INPUT */
14897 /* */
14898 /* string Pointer to a string */
14899 /* number Pointer to a number */
14900 /* */
14901 /* OUTPUT */
14902 /* */
14903 /* status */
14904 /* */
14905 /* CALLS */
14906 /* */
14907 /* nx_bsd_isdigit Indicate char is a number */
14908 /* */
14909 /* CALLED BY */
14910 /* */
14911 /* Application Code */
14912 /* */
14913 /* RELEASE HISTORY */
14914 /* */
14915 /* DATE NAME DESCRIPTION */
14916 /* */
14917 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14918 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
14919 /* resulting in version 6.1 */
14920 /* */
14921 /**************************************************************************/
bsd_string_to_number(const CHAR * string,UINT * number)14922 static INT bsd_string_to_number(const CHAR *string, UINT *number)
14923 {
14924
14925 /* Initialize the numbet to zero. */
14926 *number = 0;
14927
14928 while(*string != '\0')
14929 {
14930
14931 /* Check if the current character is a digit character. */
14932 if(!nx_bsd_isdigit((UCHAR)(*string)))
14933 return NX_SOC_ERROR;
14934
14935 *number = (*number * 10) + (UINT)(*string - 0x30);
14936
14937 string++;
14938 }
14939
14940 return NX_SOC_OK;
14941 }
14942
14943 /**************************************************************************/
14944 /* */
14945 /* FUNCTION RELEASE */
14946 /* */
14947 /* getnameinfo PORTABLE C */
14948 /* 6.3.0 */
14949 /* AUTHOR */
14950 /* */
14951 /* Yuxin Zhou, Microsoft Corporation */
14952 /* */
14953 /* DESCRIPTION */
14954 /* */
14955 /* This function converts a socket address to a corresponding host and */
14956 /* service. */
14957 /* */
14958 /* INPUT */
14959 /* */
14960 /* sa Pointer to a generic socket */
14961 /* address structure */
14962 /* salen Length of sa structure */
14963 /* host Pointer to caller-allocated */
14964 /* buffer for hostname */
14965 /* hostlen Host buffer size */
14966 /* serv Pointer to caller-allocated */
14967 /* buffer for service name */
14968 /* servlen Service buffer size */
14969 /* */
14970 /* OUTPUT */
14971 /* */
14972 /* status 0 if OK, nonzero on errors */
14973 /* */
14974 /* CALLS */
14975 /* */
14976 /* nx_dns_host_by_address_get Get hostname by IPv4 address */
14977 /* nxd_dns_host_by_address_get Get hostname by IPv6 address */
14978 /* */
14979 /* CALLED BY */
14980 /* */
14981 /* Application Code */
14982 /* */
14983 /* RELEASE HISTORY */
14984 /* */
14985 /* DATE NAME DESCRIPTION */
14986 /* */
14987 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
14988 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
14989 /* verified memcpy use cases, */
14990 /* resulting in version 6.1 */
14991 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), and */
14992 /* used new API/structs naming,*/
14993 /* resulting in version 6.3.0 */
14994 /* */
14995 /**************************************************************************/
nx_bsd_getnameinfo(const struct nx_bsd_sockaddr * sa,nx_bsd_socklen_t salen,char * host,size_t hostlen,char * serv,size_t servlen,int flags)14996 INT nx_bsd_getnameinfo(const struct nx_bsd_sockaddr *sa, nx_bsd_socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
14997 {
14998
14999 UINT i = 0;
15000 /* Flag used to identify whether host/service is numeric, 0 no, 1 yes. */
15001 UINT numeric_flag;
15002 USHORT *temp;
15003 #ifdef NX_BSD_ENABLE_DNS
15004 UINT status;
15005 #ifdef FEATURE_NX_IPV6
15006 NXD_ADDRESS nxd_ipv6_addr;
15007 #endif
15008 #endif
15009 const CHAR *rt_ptr;
15010
15011 if(!sa)
15012 {
15013
15014 /* sa is NULL. */
15015 return EAI_FAMILY;
15016 }
15017 else
15018 {
15019 if((sa -> sa_family != AF_INET) &&
15020 (sa -> sa_family != AF_INET6))
15021 {
15022
15023 /* sa isn't NULL, but family type is invalid. */
15024 return EAI_FAMILY;
15025 }
15026 else if((sa -> sa_family == AF_INET && salen != sizeof(struct nx_bsd_sockaddr_in)) ||
15027 (sa -> sa_family == AF_INET6 && salen != sizeof(struct nx_bsd_sockaddr_in6)))
15028 {
15029
15030 /* Address length is invalid. */
15031 return EAI_FAMILY;
15032 }
15033 }
15034
15035 /* Both host and service null are invalid */
15036 if((host == NX_NULL) && (serv == NX_NULL) && ((flags & NI_NAMEREQD) == 0))
15037 return EAI_NONAME;
15038
15039 if(serv && servlen > 0)
15040 {
15041 numeric_flag = 1;
15042
15043 /* If NUMERICSERV bit is set, set to 1. */
15044 if(flags & NI_NUMERICSERV)
15045 {
15046 numeric_flag = 1;
15047 }
15048 else if(flags & NI_DGRAM)
15049 {
15050 /* Socket type must be SOCK_DGRAM. */
15051
15052 for(i = 0; i < _nx_bsd_serv_list_len; i++)
15053 {
15054 temp = (USHORT *)(sa -> sa_data);
15055 if((_nx_bsd_serv_list_ptr[i].service_port == *temp) &&
15056 (_nx_bsd_serv_list_ptr[i].service_socktype == SOCK_DGRAM))
15057 {
15058
15059 /* Found a matched service, set numeric flag to 0. */
15060 numeric_flag = 0;
15061 break;
15062 }
15063 }
15064 }
15065 else
15066 {
15067
15068 /* Socket type is SOCK_STREAM. */
15069 for(i = 0; i < _nx_bsd_serv_list_len; i++)
15070 {
15071 temp = (USHORT *)(sa -> sa_data);
15072 if((_nx_bsd_serv_list_ptr[i].service_port == *temp) &&
15073 (_nx_bsd_serv_list_ptr[i].service_socktype == SOCK_STREAM))
15074 {
15075
15076 /* Found a matched service, set numeric flag to 0. */
15077 numeric_flag = 0;
15078 break;
15079 }
15080 }
15081 }
15082
15083 if(numeric_flag)
15084 {
15085
15086 /* Service is numeric, copy the service port. Then convert host byte order to network byte order. */
15087 temp = (USHORT *)(sa -> sa_data);
15088 if(bsd_number_convert(htons(*temp), (CHAR *)serv, servlen, 10) == 0)
15089 return EAI_OVERFLOW;
15090 }
15091 else
15092 {
15093
15094 /* Service isn't numeric, copy the service name. */
15095 if(_nx_bsd_string_length(_nx_bsd_serv_list_ptr[i].service_name) > servlen)
15096 return EAI_OVERFLOW;
15097
15098 memcpy(serv, _nx_bsd_serv_list_ptr[i].service_name, /* Use case of memcpy is verified. */
15099 _nx_bsd_string_length(_nx_bsd_serv_list_ptr[i].service_name));
15100 }
15101 }
15102
15103 if(host && hostlen > 0)
15104 {
15105 numeric_flag = 1;
15106
15107 /* If NUMERIC bit is set, set flag to 1. */
15108 if(flags & NI_NUMERICHOST)
15109 numeric_flag = 1;
15110 else
15111 {
15112
15113 #ifdef NX_BSD_ENABLE_DNS
15114 if(sa -> sa_family == AF_INET)
15115 {
15116
15117 #ifndef NX_DISABLE_IPV4
15118 /* Get host name by IPv4 address via DNS. */
15119 status = nx_dns_host_by_address_get(_nx_dns_instance_ptr, ntohl(((struct nx_bsd_sockaddr_in *)sa) -> sin_addr.s_addr),
15120 (UCHAR *)host, hostlen, NX_BSD_TIMEOUT);
15121 #else
15122 status = NX_DNS_NO_SERVER;
15123 #endif /* NX_DISABLE_IPV4 */
15124 }
15125 else
15126 {
15127 #ifdef FEATURE_NX_IPV6
15128 /* copy data from sockaddr structure to NXD_ADDRESS structure. */
15129 nxd_ipv6_addr.nxd_ip_version = NX_IP_VERSION_V6;
15130 nxd_ipv6_addr.nxd_ip_address.v6[0] = ntohl(((struct nx_bsd_sockaddr_in6 *)sa) -> sin6_addr.s6_addr32[0]);
15131 nxd_ipv6_addr.nxd_ip_address.v6[1] = ntohl(((struct nx_bsd_sockaddr_in6 *)sa) -> sin6_addr.s6_addr32[1]);
15132 nxd_ipv6_addr.nxd_ip_address.v6[2] = ntohl(((struct nx_bsd_sockaddr_in6 *)sa) -> sin6_addr.s6_addr32[2]);
15133 nxd_ipv6_addr.nxd_ip_address.v6[3] = ntohl(((struct nx_bsd_sockaddr_in6 *)sa) -> sin6_addr.s6_addr32[3]);
15134
15135 /* Get host name by IPv6 address via DNS. */
15136 status = nxd_dns_host_by_address_get(_nx_dns_instance_ptr, &nxd_ipv6_addr,
15137 (UCHAR *) host, hostlen, NX_BSD_TIMEOUT);
15138 #else
15139 status = NX_DNS_NO_SERVER;
15140 #endif
15141 }
15142
15143
15144 if(status == NX_DNS_SIZE_ERROR)
15145 return EAI_OVERFLOW;
15146 else if(status != NX_SUCCESS)
15147 {
15148
15149 /* DNS query fails. */
15150 if(flags & NI_NAMEREQD)
15151 return EAI_NONAME;
15152 }
15153 else
15154 {
15155
15156 /* DNS query succeeds. */
15157 numeric_flag = 0;
15158 }
15159 #else
15160 if(flags & NI_NAMEREQD)
15161 return EAI_NONAME;
15162 #endif
15163 }
15164
15165 if(numeric_flag)
15166 {
15167
15168 /* Host must be numeric string. Convert IP address from numeric to presentation. */
15169 if(sa -> sa_family == AF_INET)
15170 rt_ptr = nx_bsd_inet_ntop(AF_INET, &((struct nx_bsd_sockaddr_in*)sa) -> sin_addr, (CHAR *)host, hostlen);
15171 else
15172 rt_ptr = nx_bsd_inet_ntop(AF_INET6, &((struct nx_bsd_sockaddr_in6*)sa) -> sin6_addr, (CHAR *)host, hostlen);
15173
15174 if(!rt_ptr)
15175 return EAI_OVERFLOW;
15176 }
15177
15178 }
15179
15180 return 0;
15181 }
15182
15183 /**************************************************************************/
15184 /* */
15185 /* FUNCTION RELEASE */
15186 /* */
15187 /* nx_bsd_set_service_list PORTABLE C */
15188 /* 6.1 */
15189 /* AUTHOR */
15190 /* */
15191 /* Yuxin Zhou, Microsoft Corporation */
15192 /* */
15193 /* DESCRIPTION */
15194 /* */
15195 /* This function lets user set the service list used by getaddrinfo */
15196 /* */
15197 /* INPUT */
15198 /* */
15199 /* serv_list_ptr Pointer to a service list */
15200 /* serv_list_len Service list length */
15201 /* */
15202 /* OUTPUT */
15203 /* */
15204 /* None */
15205 /* */
15206 /* CALLS */
15207 /* */
15208 /* None */
15209 /* */
15210 /* CALLED BY */
15211 /* */
15212 /* Application Code */
15213 /* */
15214 /* RELEASE HISTORY */
15215 /* */
15216 /* DATE NAME DESCRIPTION */
15217 /* */
15218 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
15219 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
15220 /* resulting in version 6.1 */
15221 /* */
15222 /**************************************************************************/
nx_bsd_set_service_list(struct NX_BSD_SERVICE_LIST * serv_list_ptr,ULONG serv_list_len)15223 VOID nx_bsd_set_service_list(struct NX_BSD_SERVICE_LIST *serv_list_ptr, ULONG serv_list_len)
15224 {
15225 _nx_bsd_serv_list_ptr = serv_list_ptr;
15226 _nx_bsd_serv_list_len = serv_list_len;
15227 }
15228
15229
15230 /**************************************************************************/
15231 /* */
15232 /* FUNCTION RELEASE */
15233 /* */
15234 /* _nx_bsd_string_length PORTABLE C */
15235 /* 6.1 */
15236 /* AUTHOR */
15237 /* */
15238 /* Yuxin Zhou, Microsoft Corporation */
15239 /* */
15240 /* DESCRIPTION */
15241 /* */
15242 /* This function returns the length of string. */
15243 /* */
15244 /* INPUT */
15245 /* */
15246 /* string Pointer to a string */
15247 /* */
15248 /* OUTPUT */
15249 /* */
15250 /* ULONG String length */
15251 /* */
15252 /* CALLS */
15253 /* */
15254 /* None */
15255 /* */
15256 /* CALLED BY */
15257 /* */
15258 /* NetX Duo BSD Layer Source Code */
15259 /* */
15260 /* RELEASE HISTORY */
15261 /* */
15262 /* DATE NAME DESCRIPTION */
15263 /* */
15264 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
15265 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
15266 /* resulting in version 6.1 */
15267 /* */
15268 /**************************************************************************/
_nx_bsd_string_length(CHAR * string)15269 static ULONG _nx_bsd_string_length(CHAR * string)
15270 {
15271 int length = 0;
15272
15273 while(*string != '\0')
15274 {
15275 length++;
15276 string++;
15277 }
15278
15279 return((ULONG)length);
15280
15281 }
15282
15283
15284 /**************************************************************************/
15285 /* */
15286 /* FUNCTION RELEASE */
15287 /* */
15288 /* _nx_bsd_fast_periodic_timer_entry PORTABLE C */
15289 /* 6.1 */
15290 /* AUTHOR */
15291 /* */
15292 /* Yuxin Zhou, Microsoft Corporation */
15293 /* */
15294 /* DESCRIPTION */
15295 /* */
15296 /* This function handles BSD system clock. When the timer expires, the */
15297 /* BSD system clock is updated and then default IP fast periodic entry */
15298 /* routine is invoked. */
15299 /* */
15300 /* INPUT */
15301 /* */
15302 /* id Argument of default timer entry*/
15303 /* */
15304 /* OUTPUT */
15305 /* */
15306 /* None */
15307 /* */
15308 /* CALLS */
15309 /* */
15310 /* None */
15311 /* */
15312 /* CALLED BY */
15313 /* */
15314 /* None */
15315 /* */
15316 /* RELEASE HISTORY */
15317 /* */
15318 /* DATE NAME DESCRIPTION */
15319 /* */
15320 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
15321 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
15322 /* resulting in version 6.1 */
15323 /* */
15324 /**************************************************************************/
_nx_bsd_fast_periodic_timer_entry(ULONG id)15325 static VOID _nx_bsd_fast_periodic_timer_entry(ULONG id)
15326 {
15327
15328 /* Update the BSD system clock. */
15329 nx_bsd_system_clock += nx_bsd_timer_rate;
15330
15331 /* Call default IP fast periodic timer entry. */
15332 nx_bsd_ip_fast_periodic_timer_entry(id);
15333 }
15334
15335
15336 /**************************************************************************/
15337 /* */
15338 /* FUNCTION RELEASE */
15339 /* */
15340 /* poll PORTABLE C */
15341 /* 6.3.0 */
15342 /* AUTHOR */
15343 /* */
15344 /* Chaoqiong Xiao, Microsoft Corporation */
15345 /* */
15346 /* DESCRIPTION */
15347 /* */
15348 /* This function allows for list of sockets to be checked for incoming */
15349 /* events. */
15350 /* */
15351 /* Before invoked, each item inside fds array should be initialized, */
15352 /* pollfd::fd must be the descriptor ID to check and pollfd::events */
15353 /* must be the events (bits) to check. */
15354 /* */
15355 /* Returned, the pollfd::revents of each item is updated, to indicate */
15356 /* if the checked events happen. */
15357 /* */
15358 /* The event (bit) currently supported: */
15359 /* - POLLIN : checking socket read FD */
15360 /* - POLLOUT: checking socket write FD */
15361 /* - POLLPRI: checking socket exception FD */
15362 /* */
15363 /* NOTE: ****** When select returns NX_SOC_ERROR it won't update */
15364 /* the fds descriptor. */
15365 /* */
15366 /* INPUT */
15367 /* */
15368 /* fds Socket descriptor list to poll */
15369 /* and report actual status */
15370 /* nfds Number of socket descriptors */
15371 /* timeOut Timeout in microseconds, set */
15372 /* to below 0 to wait infinitely */
15373 /* */
15374 /* OUTPUT */
15375 /* */
15376 /* NX_SUCCESS Descriptors check ends */
15377 /* (successful completion) */
15378 /* NX_SOC_ERROR (-1) Error occured */
15379 /* */
15380 /* CALLS */
15381 /* */
15382 /* FD_ZERO Clear a socket ready list */
15383 /* FD_ISSET Check a socket is ready */
15384 /* FD_SET Set a socket */
15385 /* select Perform checks, see select() */
15386 /* set_errno Set the error code */
15387 /* */
15388 /* CALLED BY */
15389 /* */
15390 /* Application Code */
15391 /* */
15392 /* RELEASE HISTORY */
15393 /* */
15394 /* DATE NAME DESCRIPTION */
15395 /* */
15396 /* 10-31-2023 Chaoqiong Xiao Initial Version 6.3.0 */
15397 /* */
15398 /**************************************************************************/
nx_bsd_poll(struct nx_bsd_pollfd * fds,ULONG nfds,INT timeout)15399 INT nx_bsd_poll(struct nx_bsd_pollfd *fds, ULONG nfds, INT timeout)
15400 {
15401 nx_bsd_fd_set read_fds;
15402 nx_bsd_fd_set write_fds;
15403 nx_bsd_fd_set except_fds;
15404 struct nx_bsd_timeval stime;
15405 struct nx_bsd_timeval *ptime;
15406 INT n_ready_fds;
15407 INT max_fd;
15408 ULONG i;
15409 struct nx_bsd_pollfd *poll_fd;
15410
15411 /* Check input parameter. */
15412 if (fds == NX_NULL)
15413 {
15414 nx_bsd_set_errno(EFAULT);
15415 return(NX_SOC_ERROR);
15416 }
15417 if (nfds == 0)
15418 {
15419 nx_bsd_set_errno(EFAULT);
15420 return(NX_SOC_ERROR);
15421 }
15422
15423 /* Initialize local FDs. */
15424 NX_BSD_FD_ZERO(&read_fds);
15425 NX_BSD_FD_ZERO(&write_fds);
15426 NX_BSD_FD_ZERO(&except_fds);
15427
15428 /* Map the poll() FD to select() FDs. */
15429 max_fd = 0;
15430 for(i = 0; i < nfds; i ++)
15431 {
15432 poll_fd = &fds[i];
15433
15434 /* Skip bad FDs. */
15435 if (poll_fd -> fd < 0)
15436 continue;
15437
15438 /* POLLIN. */
15439 if (poll_fd -> events & POLLIN)
15440 {
15441 NX_BSD_FD_SET(poll_fd -> fd, &read_fds);
15442 }
15443
15444 /* POLLOUT. */
15445 if (poll_fd -> events & POLLOUT)
15446 {
15447 NX_BSD_FD_SET(poll_fd -> fd, &write_fds);
15448 }
15449
15450 /* POLLPRI. */
15451 if (poll_fd -> events & POLLPRI)
15452 {
15453 NX_BSD_FD_SET(poll_fd -> fd, &except_fds);
15454 }
15455
15456 /* Update max FD. */
15457 if (poll_fd -> fd > max_fd)
15458 max_fd = poll_fd -> fd;
15459 }
15460
15461 /* Map the select() timeout. */
15462 if (timeout < 0)
15463 {
15464
15465 /* select() wait infinitely. */
15466 ptime = NX_NULL;
15467 }
15468 else
15469 {
15470
15471 /* select() uses timeval option. */
15472 ptime = &stime;
15473
15474 if (timeout == 0)
15475 {
15476
15477 /* select() no wait. */
15478 ptime -> tv_sec = 0;
15479 ptime -> tv_usec = 0;
15480 }
15481 else
15482 {
15483
15484 /* select() wait specific time in ms. */
15485 ptime -> tv_sec = (timeout / 1000);
15486 ptime -> tv_usec = (timeout % 1000);
15487 }
15488
15489 }
15490
15491 /* Invoke select(). */
15492 n_ready_fds = nx_bsd_select(max_fd + 1, &read_fds, &write_fds, &except_fds, ptime);
15493
15494 /* Parse result events if FDs updated. */
15495 if (n_ready_fds)
15496 {
15497
15498 for (i = 0; i < nfds; i ++)
15499 {
15500 poll_fd = &fds[i];
15501
15502 /* Skip bad FDs. */
15503 if (poll_fd -> fd < 0)
15504 continue;
15505
15506 /* Exceptions. */
15507 if (NX_BSD_FD_ISSET(poll_fd -> fd, &except_fds))
15508 poll_fd -> revents |= POLLPRI;
15509
15510 else
15511 {
15512
15513 /* Inputs. */
15514 if (NX_BSD_FD_ISSET(poll_fd -> fd, &read_fds))
15515 poll_fd -> revents |= POLLIN;
15516 }
15517
15518 /* Outputs. */
15519 if (NX_BSD_FD_ISSET(poll_fd -> fd, &write_fds))
15520 poll_fd -> revents |= POLLOUT;
15521 }
15522 }
15523
15524 return(n_ready_fds);
15525 }
15526