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 #define NX_SOURCE_CODE
13 
14 
15 /* Include necessary system files.  */
16 
17 #include "nx_api.h"
18 #include "nx_ipv6.h"
19 #include "nx_nd_cache.h"
20 
21 
22 
23 
24 #ifdef FEATURE_NX_IPV6
25 /**************************************************************************/
26 /**************************************************************************/
27 /**                                                                       */
28 /** NetX Component                                                        */
29 /**                                                                       */
30 /**   Internet Protocol version 6 Prefix Table (IPv6 prefix table)        */
31 /**                                                                       */
32 /**************************************************************************/
33 /**************************************************************************/
34 
35 
36 
37 /**************************************************************************/
38 /*                                                                        */
39 /*  FUNCTION                                               RELEASE        */
40 /*                                                                        */
41 /*    _nx_ipv6_prefix_list_delete_entry                   PORTABLE C      */
42 /*                                                           6.1          */
43 /*  AUTHOR                                                                */
44 /*                                                                        */
45 /*    Yuxin Zhou, Microsoft Corporation                                   */
46 /*                                                                        */
47 /*  DESCRIPTION                                                           */
48 /*                                                                        */
49 /*    This function deletes an entry from the prefix list.                */
50 /*                                                                        */
51 /*                                                                        */
52 /*  INPUT                                                                 */
53 /*                                                                        */
54 /*    ip_ptr                                Pointer to IP control block   */
55 /*    entry                                 Entry to be deleted           */
56 /*                                                                        */
57 /*  OUTPUT                                                                */
58 /*                                                                        */
59 /*    None                                                                */
60 /*                                                                        */
61 /*  CALLS                                                                 */
62 /*                                                                        */
63 /*    CHECK_IPV6_ADDRESS_SAME               Compare two IPv6 addresses    */
64 /*    SET_SOLICITED_NODE_MULTICAST_ADDRESS  Get the solicited-node        */
65 /*                                            multicast address           */
66 /*    _nx_ipv6_multicast_leave              Leave an IPv6 mulcast group   */
67 /*    [ipv6_address_change_notify]          User callback function        */
68 /*                                                                        */
69 /*  CALLED BY                                                             */
70 /*                                                                        */
71 /*    _nx_ipv6_prefix_list_delete           Delete a prefix entry.        */
72 /*    _nx_ipv6_prefix_router_timer_tick     Router list timeout           */
73 /*                                                                        */
74 /*  NOTE                                                                  */
75 /*                                                                        */
76 /*    This function cannot be called from ISR.                            */
77 /*                                                                        */
78 /*  RELEASE HISTORY                                                       */
79 /*                                                                        */
80 /*    DATE              NAME                      DESCRIPTION             */
81 /*                                                                        */
82 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
83 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
84 /*                                            resulting in version 6.1    */
85 /*                                                                        */
86 /**************************************************************************/
_nx_ipv6_prefix_list_delete_entry(NX_IP * ip_ptr,NX_IPV6_PREFIX_ENTRY * entry)87 VOID _nx_ipv6_prefix_list_delete_entry(NX_IP *ip_ptr, NX_IPV6_PREFIX_ENTRY *entry)
88 {
89 
90 UINT              i;
91 ULONG             address_prefix[4];
92 NXD_IPV6_ADDRESS *interface_ipv6_address_prev, *interface_ipv6_address;
93 ULONG             multicast_address[4];
94 #ifdef NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY
95 UINT              ipv6_addr_index;
96 #endif /* NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY */
97 
98     /* Invalidate the interface IP address if we obtained the
99        interface IP address based on the prefix information. */
100 
101     /* Search through each physical interface for a match. */
102     for (i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++)
103     {
104 
105         /* Get a pointer to the first address in the interface list. */
106         interface_ipv6_address = ip_ptr -> nx_ip_interface[i].nxd_interface_ipv6_address_list_head;
107         interface_ipv6_address_prev = NX_NULL;
108 
109         /* Search the address list for a match. */
110         while (interface_ipv6_address)
111         {
112 
113             /* Is this interface address valid? */
114             if (interface_ipv6_address -> nxd_ipv6_address_state != NX_IPV6_ADDR_STATE_UNKNOWN &&
115                 interface_ipv6_address -> nxd_ipv6_address_ConfigurationMethod == NX_IPV6_ADDRESS_BASED_ON_INTERFACE)
116             {
117 
118                 /* Yes.  Extract the prefix to match on. The prefix length is 64 bits. */
119                 address_prefix[0] = interface_ipv6_address -> nxd_ipv6_address[0];
120                 address_prefix[1] = interface_ipv6_address -> nxd_ipv6_address[1];
121                 address_prefix[2] = 0;
122                 address_prefix[3] = 0;
123 
124                 /* Do we have a match?  */
125                 if (CHECK_IPV6_ADDRESSES_SAME(address_prefix, entry -> nx_ipv6_prefix_entry_network_address))
126                 {
127 
128                     /* Yes, invalidate this address.  */
129                     interface_ipv6_address -> nxd_ipv6_address_valid = NX_FALSE;
130                     interface_ipv6_address -> nxd_ipv6_address_state = NX_IPV6_ADDR_STATE_UNKNOWN;
131 
132                     interface_ipv6_address -> nxd_ipv6_address_ConfigurationMethod = NX_IPV6_ADDRESS_NOT_CONFIGURED;
133 
134 #ifndef NX_DISABLE_IPV6_DAD
135                     interface_ipv6_address -> nxd_ipv6_address_DupAddrDetectTransmit = 0;
136 #endif /* NX_DISABLE_IPV6_DAD */
137 
138                     /* Update the list. */
139                     if (interface_ipv6_address_prev == NX_NULL)
140                     {
141                         ip_ptr -> nx_ip_interface[i].nxd_interface_ipv6_address_list_head = interface_ipv6_address -> nxd_ipv6_address_next;
142                     }
143                     else
144                     {
145                         interface_ipv6_address_prev -> nxd_ipv6_address_next = interface_ipv6_address -> nxd_ipv6_address_next;
146                     }
147 
148                     /* Delete the associated multicast address. */
149                     SET_SOLICITED_NODE_MULTICAST_ADDRESS(multicast_address, interface_ipv6_address -> nxd_ipv6_address);
150 
151                     _nx_ipv6_multicast_leave(ip_ptr, &multicast_address[0], interface_ipv6_address -> nxd_ipv6_address_attached);
152 
153 #ifdef NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY
154                     /* If the address change notify callback is set, invoke the callback function. */
155                     if (ip_ptr -> nx_ipv6_address_change_notify)
156                     {
157                         ipv6_addr_index = (ULONG)interface_ipv6_address -> nxd_ipv6_address_index;
158                         ip_ptr -> nx_ipv6_address_change_notify(ip_ptr, NX_IPV6_ADDRESS_LIFETIME_EXPIRED, i, ipv6_addr_index,
159                                                                 &interface_ipv6_address -> nxd_ipv6_address[0]);
160                     }
161 #endif /* NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY */
162 
163                     /* Clear the address at last. */
164                     SET_UNSPECIFIED_ADDRESS(interface_ipv6_address -> nxd_ipv6_address);
165 
166                     /* Address for this interface is found. Just break. */
167                     break;
168                 }
169             }
170 
171             /* Set the previous address. */
172             interface_ipv6_address_prev = interface_ipv6_address;
173 
174             /* Get the next address. */
175             interface_ipv6_address = interface_ipv6_address -> nxd_ipv6_address_next;
176         } /* while (interface_ipv6_address) */
177     } /* for(i = 0; i < NX_MAX_PHYSICAL_INTERFACES; i++) */
178 
179     /* Unlink the previous node, if it exists. */
180     if (entry -> nx_ipv6_prefix_entry_prev == NX_NULL)
181     {
182         ip_ptr -> nx_ipv6_prefix_list_ptr = entry -> nx_ipv6_prefix_entry_next;
183     }
184     else
185     {
186         entry -> nx_ipv6_prefix_entry_prev -> nx_ipv6_prefix_entry_next = entry -> nx_ipv6_prefix_entry_next;
187     }
188 
189     /* Unlink the next node if it exists. */
190     if (entry -> nx_ipv6_prefix_entry_next)
191     {
192         entry -> nx_ipv6_prefix_entry_next -> nx_ipv6_prefix_entry_prev = entry -> nx_ipv6_prefix_entry_prev;
193     }
194 
195     /* Clean up this entry. */
196     entry -> nx_ipv6_prefix_entry_next = NX_NULL;
197     entry -> nx_ipv6_prefix_entry_prev = NX_NULL;
198 
199     /* Put entry onto the free list.*/
200     if (ip_ptr -> nx_ipv6_prefix_entry_free_list == NX_NULL)
201     {
202         /* Free list is empty.  Set entry to be the first on the list. */
203         ip_ptr -> nx_ipv6_prefix_entry_free_list = entry;
204     }
205     else
206     {
207 
208         /* Free list is not empty.  Insert the entry to the head of the list. */
209         ip_ptr -> nx_ipv6_prefix_entry_free_list -> nx_ipv6_prefix_entry_prev = entry;
210         entry -> nx_ipv6_prefix_entry_next = ip_ptr -> nx_ipv6_prefix_entry_free_list;
211         ip_ptr -> nx_ipv6_prefix_entry_free_list = entry;
212     }
213 
214     /* All done. Return. */
215     return;
216 }
217 
218 
219 #endif /* FEATURE_NX_IPV6 */
220 
221