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 /**                                                                       */
15 /** NetX Component                                                        */
16 /**                                                                       */
17 /**   Internet Protocol (IP)                                              */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define NX_SOURCE_CODE
23 
24 
25 /* Include necessary system files.  */
26 
27 #include "nx_api.h"
28 #include "tx_thread.h"
29 #include "nx_ip.h"
30 #include "nx_icmp.h"
31 #include "nx_arp.h"
32 #ifdef FEATURE_NX_IPV6
33 #include "nx_nd_cache.h"
34 #endif /* FEATURE_NX_IPV6 */
35 
36 
37 /**************************************************************************/
38 /*                                                                        */
39 /*  FUNCTION                                               RELEASE        */
40 /*                                                                        */
41 /*    _nx_ip_delete                                       PORTABLE C      */
42 /*                                                           6.1          */
43 /*  AUTHOR                                                                */
44 /*                                                                        */
45 /*    Yuxin Zhou, Microsoft Corporation                                   */
46 /*                                                                        */
47 /*  DESCRIPTION                                                           */
48 /*                                                                        */
49 /*    This function deletes an Internet Protocol instance, including      */
50 /*    calling the associated driver with a link disable request.          */
51 /*                                                                        */
52 /*  INPUT                                                                 */
53 /*                                                                        */
54 /*    ip_ptr                                Pointer to IP control block   */
55 /*                                                                        */
56 /*  OUTPUT                                                                */
57 /*                                                                        */
58 /*    status                                Completion status             */
59 /*                                                                        */
60 /*  CALLS                                                                 */
61 /*                                                                        */
62 /*    _nx_ip_delete_queue_clear             Clear a packet queue          */
63 /*    _nx_ip_raw_packet_cleanup             Cleanup raw packet suspension */
64 /*    _nx_icmp_cleanup                      Cleanup for ICMP packets      */
65 /*    _nx_ip_fragment_disable               Disable fragment processing   */
66 /*    tx_mutex_delete                       Delete IP protection mutex    */
67 /*    tx_mutex_get                          Get protection mutex          */
68 /*    tx_mutex_put                          Put protection mutex          */
69 /*    tx_thread_terminate                   Terminate IP helper thread    */
70 /*    tx_event_flags_delete                 Delete IP event flags         */
71 /*    tx_thread_delete                      Delete IP helper thread       */
72 /*    _tx_thread_system_preempt_check       Check for preemption          */
73 /*    tx_timer_deactivate                   Deactivate IP-ARP timer       */
74 /*    tx_timer_delete                       Delete IP-ARP timer           */
75 /*    (ip_link_driver)                      User supplied link driver     */
76 /*                                                                        */
77 /*  CALLED BY                                                             */
78 /*                                                                        */
79 /*    Application                                                         */
80 /*                                                                        */
81 /*  RELEASE HISTORY                                                       */
82 /*                                                                        */
83 /*    DATE              NAME                      DESCRIPTION             */
84 /*                                                                        */
85 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
86 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
87 /*                                            resulting in version 6.1    */
88 /*                                                                        */
89 /**************************************************************************/
_nx_ip_delete(NX_IP * ip_ptr)90 UINT  _nx_ip_delete(NX_IP *ip_ptr)
91 {
92 
93 TX_INTERRUPT_SAVE_AREA
94 
95 UINT         i;
96 NX_IP_DRIVER driver_request;
97 NX_PACKET   *raw_packet_head;
98 NX_PACKET   *deferred_head;
99 NX_PACKET   *icmp_queue_head;
100 NX_PACKET   *tcp_queue_head;
101 #ifndef NX_DISABLE_IPV4
102 NX_PACKET   *arp_queue_head;
103 NX_PACKET   *rarp_queue_head;
104 NX_PACKET   *igmp_queue_head;
105 #endif /* !NX_DISABLE_IPV4  */
106 
107     /* If trace is enabled, insert this event into the trace buffer.  */
108     NX_TRACE_IN_LINE_INSERT(NX_TRACE_IP_DELETE, ip_ptr, 0, 0, 0, NX_TRACE_IP_EVENTS, 0, 0);
109 
110     /* Get mutex protection.  */
111     tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
112 
113     /* Determine if the IP instance has any sockets bound to it.  */
114     if ((ip_ptr -> nx_ip_udp_created_sockets_count) || (ip_ptr -> nx_ip_tcp_created_sockets_count))
115     {
116 
117         /* Still sockets bound to this IP instance.  They must all be deleted prior
118            to deleting the IP instance.  Release the mutex and return
119            an error code.  */
120         tx_mutex_put(&(ip_ptr -> nx_ip_protection));
121 
122         return(NX_SOCKETS_BOUND);
123     }
124 
125     /* Call through every link driver to disable the link.  */
126     for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
127     {
128 
129         /* Skip the invalid entries. */
130         if (!(ip_ptr -> nx_ip_interface[i].nx_interface_valid))
131         {
132             continue;
133         }
134 
135         driver_request.nx_ip_driver_ptr         =  ip_ptr;
136         driver_request.nx_ip_driver_command     =  NX_LINK_DISABLE;
137         driver_request.nx_ip_driver_interface   =  &(ip_ptr -> nx_ip_interface[i]);
138 
139         /* If trace is enabled, insert this event into the trace buffer.  */
140         NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_IO_DRIVER_LINK_DISABLE, ip_ptr, 0, 0, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0);
141 
142         /* Send the driver LINK DISABLE request. */
143         (ip_ptr -> nx_ip_interface[i].nx_interface_link_driver_entry)(&driver_request);
144 
145         /* Call the link driver to uninitialize.  */
146         driver_request.nx_ip_driver_ptr =      ip_ptr;
147         driver_request.nx_ip_driver_command =  NX_LINK_UNINITIALIZE;
148 
149         /* If trace is enabled, insert this event into the trace buffer.  */
150         NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_IO_DRIVER_UNINITIALIZE, ip_ptr, 0, 0, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0);
151 
152         /* Send the driver UNITIALIZE request. */
153         (ip_ptr -> nx_ip_interface[i].nx_interface_link_driver_entry)(&driver_request);
154     }
155 
156     /* Disable interrupts.  */
157     TX_DISABLE
158 
159     /* Remove the IP instance from the created list.  */
160 
161     /* See if the IP instance is the only one on the list.  */
162     if (ip_ptr == ip_ptr -> nx_ip_created_next)
163     {
164 
165         /* Only created IP instance, just set the created list to NULL.  */
166         _nx_ip_created_ptr =  TX_NULL;
167     }
168     else
169     {
170 
171         /* Otherwise, not the only created IP, link-up the neighbors.  */
172         (ip_ptr -> nx_ip_created_next) -> nx_ip_created_previous =
173             ip_ptr -> nx_ip_created_previous;
174         (ip_ptr -> nx_ip_created_previous) -> nx_ip_created_next =
175             ip_ptr -> nx_ip_created_next;
176 
177         /* See if we have to update the created list head pointer.  */
178         if (_nx_ip_created_ptr == ip_ptr)
179         {
180 
181             /* Yes, move the head pointer to the next link. */
182             _nx_ip_created_ptr =  ip_ptr -> nx_ip_created_next;
183         }
184     }
185 
186     /* Decrement the IP created counter.  */
187     _nx_ip_created_count--;
188 
189     /* Temporarily disable preemption.  */
190     _tx_thread_preempt_disable++;
191 
192     /* Release any raw packets queued up.  */
193     raw_packet_head =  ip_ptr ->  nx_ip_raw_received_packet_head;
194     ip_ptr ->  nx_ip_raw_received_packet_head =  NX_NULL;
195     ip_ptr ->  nx_ip_raw_received_packet_tail =  NX_NULL;
196     ip_ptr ->  nx_ip_raw_received_packet_count = 0;
197 
198     /* Release all deferred IP packets.  */
199     deferred_head =  ip_ptr ->  nx_ip_deferred_received_packet_head;
200     ip_ptr ->  nx_ip_deferred_received_packet_head =  NX_NULL;
201     ip_ptr ->  nx_ip_deferred_received_packet_tail =  NX_NULL;
202 
203     /* Release all queued ICMP packets.  */
204     icmp_queue_head =   ip_ptr ->  nx_ip_icmp_queue_head;
205     ip_ptr ->  nx_ip_icmp_queue_head =  NX_NULL;
206 
207 #ifndef NX_DISABLE_IPV4
208     /* Release all queued IGMP packets.  */
209     igmp_queue_head =   ip_ptr ->  nx_ip_igmp_queue_head;
210     ip_ptr ->  nx_ip_igmp_queue_head =  NX_NULL;
211 
212     /* Release all queued ARP packets.  */
213     arp_queue_head =  ip_ptr ->  nx_ip_arp_deferred_received_packet_head;
214     ip_ptr ->  nx_ip_arp_deferred_received_packet_head =  NX_NULL;
215     ip_ptr ->  nx_ip_arp_deferred_received_packet_tail =  NX_NULL;
216 
217     /* Release all queued RARP packets.  */
218     rarp_queue_head =  ip_ptr ->  nx_ip_rarp_deferred_received_packet_head;
219     ip_ptr ->  nx_ip_rarp_deferred_received_packet_head = NX_NULL;
220     ip_ptr ->  nx_ip_rarp_deferred_received_packet_tail = NX_NULL;
221 #endif /* !NX_DISABLE_IPV4  */
222 
223     /* Release all queued TCP packets.  */
224     tcp_queue_head =  ip_ptr ->  nx_ip_tcp_queue_head;
225     ip_ptr ->  nx_ip_tcp_queue_head =  NX_NULL;
226     ip_ptr ->  nx_ip_tcp_queue_tail =  NX_NULL;
227 
228     /* Restore interrupts.  */
229     TX_RESTORE
230 
231     /* Release mutex protection.  */
232     tx_mutex_put(&(ip_ptr -> nx_ip_protection));
233 
234     /* Deactivate and delete the IP periodic timer.  */
235     tx_timer_deactivate(&(ip_ptr -> nx_ip_periodic_timer));
236     tx_timer_delete(&(ip_ptr -> nx_ip_periodic_timer));
237 
238     /* Determine if the fast timer has been created.  */
239     if (ip_ptr -> nx_ip_fast_periodic_timer_created)
240     {
241 
242         /* Yes. Deactivate and delete the IP fast periodic timer.  */
243         tx_timer_deactivate(&(ip_ptr -> nx_ip_fast_periodic_timer));
244         tx_timer_delete(&(ip_ptr -> nx_ip_fast_periodic_timer));
245         ip_ptr -> nx_ip_fast_periodic_timer_created = 0;
246     }
247 
248     /* Terminate the internal IP thread.  */
249     tx_thread_terminate(&(ip_ptr -> nx_ip_thread));
250 
251     /* Delete the internal IP protection mutex.  */
252     tx_mutex_delete(&(ip_ptr -> nx_ip_protection));
253 
254     /* Delete the internal IP event flag object.  */
255     tx_event_flags_delete(&(ip_ptr -> nx_ip_events));
256 
257     /* Delete the internal IP thread for handling more processing intensive
258        duties.  */
259     tx_thread_delete(&(ip_ptr -> nx_ip_thread));
260 
261     /* Release any raw packets queued up.  */
262     if (raw_packet_head)
263     {
264         _nx_ip_delete_queue_clear(raw_packet_head);
265     }
266 
267     /* Release any deferred IP packets.  */
268     if (deferred_head)
269     {
270         _nx_ip_delete_queue_clear(deferred_head);
271     }
272 
273     /* Release any queued ICMP packets.  */
274     if (icmp_queue_head)
275     {
276         _nx_ip_delete_queue_clear(icmp_queue_head);
277     }
278 
279     /* Release any queued TCP packets.  */
280     if (tcp_queue_head)
281     {
282         _nx_ip_delete_queue_clear(tcp_queue_head);
283     }
284 
285 #ifndef NX_DISABLE_IPV4
286     /* Release any queued ARP packets.  */
287     if (arp_queue_head)
288     {
289         _nx_ip_delete_queue_clear(arp_queue_head);
290     }
291 
292     /* Release any queued RARP packets.  */
293     if (rarp_queue_head)
294     {
295         _nx_ip_delete_queue_clear(rarp_queue_head);
296     }
297 
298     /* Release any queued IGMP packets.  */
299     if (igmp_queue_head)
300     {
301         _nx_ip_delete_queue_clear(igmp_queue_head);
302     }
303 #endif /* !NX_DISABLE_IPV4  */
304 
305     /* Lift any suspension on RAW IP packet receives.  */
306     while (ip_ptr -> nx_ip_raw_packet_suspension_list)
307     {
308 
309         /* Release the suspended thread.  */
310         _nx_ip_raw_packet_cleanup(ip_ptr -> nx_ip_raw_packet_suspension_list NX_CLEANUP_ARGUMENT);
311     }
312 
313     /* Lift any suspension on ICMP ping requests.  */
314     while (ip_ptr -> nx_ip_icmp_ping_suspension_list)
315     {
316 
317         /* Release the suspended thread.  */
318         _nx_icmp_cleanup(ip_ptr -> nx_ip_icmp_ping_suspension_list NX_CLEANUP_ARGUMENT);
319     }
320 
321     /* Determine if fragment processing was enabled.  */
322     if (ip_ptr -> nx_ip_fragment_processing)
323     {
324 
325         /* Yes, disable fragment processing, which will release all outstanding
326            fragmented packets.  */
327         _nx_ip_fragment_disable(ip_ptr);
328     }
329 
330 #ifndef NX_DISABLE_IPV4
331     /* Invalidate dynamic ARP entries. */
332     _nx_arp_dynamic_entries_invalidate(ip_ptr);
333 #endif /* !NX_DISABLE_IPV4  */
334 
335 #ifdef FEATURE_NX_IPV6
336     /* Invalidate ND cache. */
337     _nxd_nd_cache_invalidate(ip_ptr);
338 #endif /* FEATURE_NX_IPV6 */
339 
340     /* Clear the IP ID to make it invalid.  */
341     ip_ptr -> nx_ip_id =  0;
342 
343     /* Disable interrupts.  */
344     TX_DISABLE
345 
346     /* Restore preemption.  */
347     _tx_thread_preempt_disable--;
348 
349     /* Restore interrupts.  */
350     TX_RESTORE
351 
352     /* Check for preemption.  */
353     _tx_thread_system_preempt_check();
354 
355     /* Return success to the caller.  */
356     return(NX_SUCCESS);
357 }
358 
359