1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** NetX Component */
17 /** */
18 /** User Datagram Protocol (UDP) */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define NX_SOURCE_CODE
24
25
26 /* Include necessary system files. */
27
28 #include "nx_api.h"
29 #include "nx_udp.h"
30
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _nx_udp_free_port_find PORTABLE C */
37 /* 6.1 */
38 /* AUTHOR */
39 /* */
40 /* Yuxin Zhou, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function finds the first available UDP port, starting from the */
45 /* supplied port. If no available ports are found, an error is */
46 /* returned. */
47 /* */
48 /* INPUT */
49 /* */
50 /* ip_ptr IP instance pointer */
51 /* port Starting port */
52 /* free_port_ptr Pointer to return free port */
53 /* */
54 /* OUTPUT */
55 /* */
56 /* status Completion status */
57 /* */
58 /* CALLS */
59 /* */
60 /* tx_mutex_get Obtain protection mutex */
61 /* tx_mutex_put Release protection mutex */
62 /* */
63 /* CALLED BY */
64 /* */
65 /* Application Code */
66 /* */
67 /* RELEASE HISTORY */
68 /* */
69 /* DATE NAME DESCRIPTION */
70 /* */
71 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
72 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
73 /* resulting in version 6.1 */
74 /* */
75 /**************************************************************************/
_nx_udp_free_port_find(NX_IP * ip_ptr,UINT port,UINT * free_port_ptr)76 UINT _nx_udp_free_port_find(NX_IP *ip_ptr, UINT port, UINT *free_port_ptr)
77 {
78
79 UINT index;
80 UINT bound;
81 UINT starting_port;
82 NX_UDP_SOCKET *search_ptr;
83 NX_UDP_SOCKET *end_ptr;
84
85 #ifdef TX_ENABLE_EVENT_TRACE
86 TX_TRACE_BUFFER_ENTRY *trace_event;
87 ULONG trace_timestamp;
88 #endif
89
90
91 /* If trace is enabled, insert this event into the trace buffer. */
92 NX_TRACE_IN_LINE_INSERT(NX_TRACE_UDP_FREE_PORT_FIND, ip_ptr, port, 0, 0, NX_TRACE_UDP_EVENTS, &trace_event, &trace_timestamp);
93
94 /* Save the original port. */
95 starting_port = port;
96
97 /* Loop through the UDP ports until a free entry is found. */
98 do
99 {
100
101 /* Calculate the hash index in the UDP port array of the associated IP instance. */
102 index = (UINT)((port + (port >> 8)) & NX_UDP_PORT_TABLE_MASK);
103
104 /* Obtain the IP mutex so we can figure out whether or not the port has already
105 been bound to. */
106 tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
107
108 /* Pickup the head of the UDP ports bound list. */
109 search_ptr = ip_ptr -> nx_ip_udp_port_table[index];
110
111 /* Set the bound flag to false. */
112 bound = NX_FALSE;
113
114 /* Determine if we need to perform a list search. */
115 if (search_ptr)
116 {
117
118 /* Walk through the circular list of UDP sockets that are already
119 bound. */
120 end_ptr = search_ptr;
121 do
122 {
123
124 /* Determine if this entry is the same as the requested port. */
125 if (search_ptr -> nx_udp_socket_port == port)
126 {
127
128 /* Set the bound flag. */
129 bound = NX_TRUE;
130
131 /* Get out of the loop. */
132 break;
133 }
134
135 /* Move to the next entry in the list. */
136 search_ptr = search_ptr -> nx_udp_socket_bound_next;
137 } while (search_ptr != end_ptr);
138 }
139
140 #ifdef NX_NAT_ENABLE
141 if (bound == NX_FALSE)
142 {
143
144 /* Check if this IP interface has a NAT service. */
145 if (ip_ptr -> nx_ip_nat_port_verify)
146 {
147
148 /* Yes, so check the port by NAT handler. If NAT does not use this port, allow NetX to use it. */
149 bound = (ip_ptr -> nx_ip_nat_port_verify)(ip_ptr, NX_PROTOCOL_UDP, port);
150 }
151 }
152 #endif
153
154 /* Release protection. */
155 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
156
157 /* Determine if the port is available. */
158 if (!bound)
159 {
160
161 /* Setup the return port number. */
162 *free_port_ptr = port;
163
164 /* Update the trace event with the status. */
165 NX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, NX_TRACE_UDP_FREE_PORT_FIND, 0, 0, port, 0);
166
167 /* Return success. */
168 return(NX_SUCCESS);
169 }
170
171 /* Move to the next port. */
172 port++;
173
174 /* Determine if we need to wrap. */
175 if (port > NX_MAX_PORT)
176 {
177
178 /* Yes, we need to wrap around. */
179 port = NX_SEARCH_PORT_START;
180 }
181 } while (starting_port != port);
182
183 /* A free port was not found, return an error. */
184 return(NX_NO_FREE_PORTS);
185 }
186
187