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