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