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