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 /** Internet Protocol (IP) */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define NX_SOURCE_CODE
24
25 /* Include necessary system files. */
26
27 #include "nx_api.h"
28 #include "nx_tcp.h"
29 #include "nx_arp.h"
30 #include "nx_igmp.h"
31 #include "nx_ip.h"
32 #include "nx_packet.h"
33 #ifdef FEATURE_NX_IPV6
34 #include "nx_icmpv6.h"
35 #endif /* FEATURE_NX_IPV6 */
36
37 /**************************************************************************/
38 /* */
39 /* FUNCTION RELEASE */
40 /* */
41 /* _nx_ip_interface_detach PORTABLE C */
42 /* 6.1 */
43 /* AUTHOR */
44 /* */
45 /* Yuxin Zhou, Microsoft Corporation */
46 /* */
47 /* DESCRIPTION */
48 /* */
49 /* This function detaches a physical network interface from the IP */
50 /* instance. */
51 /* */
52 /* INPUT */
53 /* */
54 /* ip_ptr Pointer to IP control block */
55 /* index IP interface index */
56 /* */
57 /* OUTPUT */
58 /* */
59 /* status Completion status */
60 /* */
61 /* CALLS */
62 /* */
63 /* tx_mutex_get Obtain protection mutex */
64 /* tx_mutex_put Release protection mutex */
65 /* _nx_tcp_socket_connection_reset Reset TCP connection */
66 /* _nx_arp_interface_entries_delete Remove specified ARP entries */
67 /* _nx_invalidate_destination_entry Invalidate the entry in the */
68 /* destination */
69 /* _nx_nd_cache_interface_entries_delete Delete ND cache entries */
70 /* associated with specific */
71 /* interface */
72 /* link_driver_entry Link driver */
73 /* memset Zero out the interface */
74 /* */
75 /* CALLED BY */
76 /* */
77 /* Application */
78 /* */
79 /* RELEASE HISTORY */
80 /* */
81 /* DATE NAME DESCRIPTION */
82 /* */
83 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
84 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
85 /* resulting in version 6.1 */
86 /* */
87 /**************************************************************************/
_nx_ip_interface_detach(NX_IP * ip_ptr,UINT index)88 UINT _nx_ip_interface_detach(NX_IP *ip_ptr, UINT index)
89 {
90
91 NX_INTERFACE *interface_ptr;
92 NX_IP_DRIVER driver_request;
93 NX_TCP_SOCKET *socket_ptr;
94 NXD_IPV6_ADDRESS *next_ipv6_address;
95 NXD_IPV6_ADDRESS *ipv6_address;
96 UINT i;
97 #ifdef NX_ENABLE_IP_STATIC_ROUTING
98 UINT j;
99 #endif
100
101 #ifdef FEATURE_NX_IPV6
102 NX_IPV6_DEFAULT_ROUTER_ENTRY *rt_entry;
103 #endif
104
105
106 interface_ptr = &(ip_ptr -> nx_ip_interface[index]);
107
108 /* Check interface status. */
109 if (interface_ptr -> nx_interface_valid == NX_FALSE)
110 {
111
112 /* Invalid interface. */
113 return(NX_INVALID_INTERFACE);
114 }
115
116 /* Obtain the IP internal mutex before calling the driver. */
117 tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
118
119 /* Loop through the list of created TCP sockets for this IP instance. */
120 socket_ptr = ip_ptr -> nx_ip_tcp_created_sockets_ptr;
121 if (socket_ptr != NX_NULL)
122 {
123 do
124 {
125 /* Reset TCP connection which is established or in progress on this interface. */
126 if (socket_ptr -> nx_tcp_socket_connect_interface == interface_ptr)
127 {
128 _nx_tcp_socket_connection_reset(socket_ptr);
129 }
130
131 /* Move to the next. */
132 socket_ptr = socket_ptr -> nx_tcp_socket_created_next;
133 } while (socket_ptr != ip_ptr -> nx_ip_tcp_created_sockets_ptr);
134 }
135
136 /* Release the IP internal mutex. */
137 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
138
139 #ifndef NX_DISABLE_IPV4
140 /* Remove ARP entries associated with this interface from ARP table. */
141 _nx_arp_interface_entries_delete(ip_ptr, index);
142 #endif /* !NX_DISABLE_IPV4 */
143
144 #ifdef FEATURE_NX_IPV6
145 /* Delete ND cache entries associated with this interface. */
146 _nx_nd_cache_interface_entries_delete(ip_ptr, index);
147 #endif /* FEATURE_NX_IPV6 */
148
149 /* Obtain the IP internal mutex before calling the driver. */
150 tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
151
152 #ifndef NX_DISABLE_IPV4
153 #ifdef NX_ENABLE_IP_STATIC_ROUTING
154 /* Remove router iterms associated with the interface that will be detached from route table. */
155 for (i = 0; i < ip_ptr -> nx_ip_routing_table_entry_count; i++)
156 {
157
158 /* Is this router iterm related to the interface to be detached. */
159 if (ip_ptr -> nx_ip_routing_table[i].nx_ip_routing_entry_ip_interface == interface_ptr)
160 {
161
162 /* Yes, we need to remove this iterm. */
163 /* If the entry is not the last one, we need to shift the table to fill the hole. */
164 for (j = i; j < ip_ptr -> nx_ip_routing_table_entry_count; j++)
165 {
166 ip_ptr -> nx_ip_routing_table[j].nx_ip_routing_dest_ip =
167 ip_ptr -> nx_ip_routing_table[j + 1].nx_ip_routing_dest_ip;
168 ip_ptr -> nx_ip_routing_table[j].nx_ip_routing_net_mask =
169 ip_ptr -> nx_ip_routing_table[j + 1].nx_ip_routing_net_mask;
170 ip_ptr -> nx_ip_routing_table[j].nx_ip_routing_next_hop_address =
171 ip_ptr -> nx_ip_routing_table[j + 1].nx_ip_routing_next_hop_address;
172 ip_ptr -> nx_ip_routing_table[j].nx_ip_routing_entry_ip_interface =
173 ip_ptr -> nx_ip_routing_table[j + 1].nx_ip_routing_entry_ip_interface;
174 }
175
176 ip_ptr -> nx_ip_routing_table[j - 1].nx_ip_routing_dest_ip = 0;
177 ip_ptr -> nx_ip_routing_table[j - 1].nx_ip_routing_net_mask = 0;
178 ip_ptr -> nx_ip_routing_table[j - 1].nx_ip_routing_next_hop_address = 0;
179 ip_ptr -> nx_ip_routing_table[j - 1].nx_ip_routing_entry_ip_interface = NX_NULL;
180
181 ip_ptr -> nx_ip_routing_table_entry_count--;
182 }
183 }
184 #endif /* NX_ENABLE_IP_STATIC_ROUTING */
185 #endif /* !NX_DISABLE_IPV4 */
186
187 #ifdef FEATURE_NX_IPV6
188 /* Remove IPv6 routers associated with this interface. */
189 for (i = 0; i < NX_IPV6_DEFAULT_ROUTER_TABLE_SIZE; i++)
190 {
191 /* Set local pointer for convenience. */
192 rt_entry = &ip_ptr -> nx_ipv6_default_router_table[i];
193
194 /* Does this slot contain a router. */
195 if (rt_entry -> nx_ipv6_default_router_entry_flag & NX_IPV6_ROUTE_TYPE_VALID)
196 {
197 /* Is this router iterm related to the interface to be detached. */
198 if (rt_entry -> nx_ipv6_default_router_entry_interface_ptr == interface_ptr)
199 {
200
201 /* Yes, we need to remove this router iterm. */
202 /* Clean any entries in the destination table for this router. */
203 _nx_invalidate_destination_entry(ip_ptr, rt_entry -> nx_ipv6_default_router_entry_router_address);
204
205 /* Mark the entry as empty. */
206 rt_entry -> nx_ipv6_default_router_entry_flag = 0;
207
208 /* Clear the interface pointer .*/
209 rt_entry -> nx_ipv6_default_router_entry_interface_ptr = NX_NULL;
210
211 /* Decrease the count of available routers. */
212 ip_ptr -> nx_ipv6_default_router_table_size--;
213 }
214 }
215 }
216 #endif
217
218 #ifndef NX_DISABLE_IPV4
219 /* Clear gateway address related to the interface to be detached. */
220 if (ip_ptr -> nx_ip_gateway_interface == interface_ptr)
221 {
222 ip_ptr -> nx_ip_gateway_interface = NX_NULL;
223 ip_ptr -> nx_ip_gateway_address = 0;
224 }
225
226
227 /* Leave multicast groups related to the interface to be detached. */
228 for (i = 0; i < NX_MAX_MULTICAST_GROUPS; i++)
229 {
230
231 /* Skip entries not related to the interface. */
232 if (ip_ptr -> nx_ipv4_multicast_entry[i].nx_ipv4_multicast_join_interface_list != interface_ptr)
233 {
234 continue;
235 }
236
237 /* Set join count to 1 so force send multicast leave command. */
238 ip_ptr -> nx_ipv4_multicast_entry[i].nx_ipv4_multicast_join_count = 1;
239
240 /* Leave the multicast group. */
241 _nx_igmp_multicast_interface_leave_internal(ip_ptr,
242 ip_ptr -> nx_ipv4_multicast_entry[i].nx_ipv4_multicast_join_list,
243 index);
244 }
245 #endif /* !NX_DISABLE_IPV4 */
246
247 #ifdef NX_ENABLE_IPV6_MULTICAST
248 /* Leave IPv6 multicast groups related to the interface to be detached. */
249 for (i = 0; i < NX_MAX_MULTICAST_GROUPS; i++)
250 {
251 if (ip_ptr -> nx_ipv6_multicast_entry[i].nx_ip_mld_join_interface_list == interface_ptr)
252 {
253 ip_ptr -> nx_ipv6_multicast_entry[i].nx_ip_mld_join_count = 0;
254
255 /* Clear the group join value. */
256 memset(ip_ptr -> nx_ipv6_multicast_entry[i].nx_ip_mld_join_list, 0, 4 * sizeof(ULONG));
257
258 /* Decrement the MLD groups joined count. */
259 ip_ptr -> nx_ipv6_multicast_groups_joined--;
260
261 /* Un-register the new multicast group with the underlying driver. */
262 driver_request.nx_ip_driver_ptr = ip_ptr;
263 driver_request.nx_ip_driver_command = NX_LINK_MULTICAST_LEAVE;
264 driver_request.nx_ip_driver_physical_address_msw = 0x00003333;
265 driver_request.nx_ip_driver_physical_address_lsw =
266 ip_ptr -> nx_ipv6_multicast_entry[i].nx_ip_mld_join_list[3];
267 driver_request.nx_ip_driver_interface = interface_ptr;
268
269 (interface_ptr -> nx_interface_link_driver_entry)(&driver_request);
270
271 /* Now clear the interface entry. */
272 ip_ptr -> nx_ipv6_multicast_entry[i].nx_ip_mld_join_interface_list = NX_NULL;
273 }
274 }
275 #endif
276
277 /* Detach the interface. */
278 /* First detach the interface from the device. */
279 driver_request.nx_ip_driver_ptr = ip_ptr;
280 driver_request.nx_ip_driver_command = NX_LINK_INTERFACE_DETACH;
281 driver_request.nx_ip_driver_interface = interface_ptr;
282
283 (interface_ptr -> nx_interface_link_driver_entry)(&driver_request);
284
285 /* Release the IP internal mutex. */
286 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
287
288 /* Clear out IPv6 address. */
289 next_ipv6_address = interface_ptr -> nxd_interface_ipv6_address_list_head;
290
291 while (next_ipv6_address)
292 {
293 ipv6_address = next_ipv6_address;
294 next_ipv6_address = next_ipv6_address -> nxd_ipv6_address_next;
295 memset(ipv6_address, 0, sizeof(NXD_IPV6_ADDRESS));
296 }
297
298 /* Zero out the interface. */
299 memset(interface_ptr, 0, sizeof(NX_INTERFACE));
300
301 /* reserve the index. */
302 interface_ptr -> nx_interface_index = (UCHAR)index;
303
304 return(NX_SUCCESS);
305 }
306
307