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 /** NetX Component */
15 /** */
16 /** Internet Protocol version 6 Default Router Table (IPv6 router) */
17 /** */
18 /**************************************************************************/
19 /**************************************************************************/
20 #define NX_SOURCE_CODE
21
22
23 /* Include necessary system files. */
24
25 #include "nx_api.h"
26 #include "nx_ipv6.h"
27 #include "nx_nd_cache.h"
28
29
30 #ifdef FEATURE_NX_IPV6
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _nxd_ipv6_default_router_add_interanl PORTABLE C */
36 /* 6.1 */
37 /* AUTHOR */
38 /* */
39 /* Yuxin Zhou, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function sets IPv6 routing table entry. */
44 /* */
45 /* INPUT */
46 /* */
47 /* ip_ptr IP instance pointer */
48 /* router_addr Destination Network addr */
49 /* router_lifetime Life time information */
50 /* if_ptr Pointer to the interface */
51 /* router_type dynamic or static */
52 /* _ret Return value, indicates where */
53 /* the new entry is located. */
54 /* */
55 /* OUTPUT */
56 /* */
57 /* status Completion status */
58 /* */
59 /* CALLS */
60 /* */
61 /* COPY_IPV6_ADDRESS Copy IP addresses */
62 /* */
63 /* CALLED BY */
64 /* */
65 /* _nxd_ipv6_default_router_add Add default router to IP */
66 /* default router list */
67 /* _nx_icmpv6_process_redirect Process ICMPv6 redirect */
68 /* message */
69 /* _nx_icmpv6_process_ra Process incoming Router */
70 /* Advertisement packets */
71 /* */
72 /* NOTE */
73 /* */
74 /* Make sure nx_ip_prortection mutex is obtained before entering this */
75 /* function. */
76 /* */
77 /* This function cannot be called from ISR. */
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 /**************************************************************************/
_nxd_ipv6_default_router_add_internal(NX_IP * ip_ptr,ULONG * router_addr,ULONG router_lifetime,NX_INTERFACE * if_ptr,INT router_type,NX_IPV6_DEFAULT_ROUTER_ENTRY ** _ret)88 UINT _nxd_ipv6_default_router_add_internal(NX_IP *ip_ptr,
89 ULONG *router_addr,
90 ULONG router_lifetime,
91 NX_INTERFACE *if_ptr,
92 INT router_type,
93 NX_IPV6_DEFAULT_ROUTER_ENTRY **_ret)
94 {
95
96 UINT i;
97 UINT first_available = (UINT)0xFFFFFFFF;
98 ULONG address_type;
99 NX_IPV6_DEFAULT_ROUTER_ENTRY *ret = NX_NULL;
100 NXD_IPV6_ADDRESS *ipv6_address;
101
102
103 /* If a router pointer is provided, initialize it to NULL. */
104 if (_ret)
105 {
106 *_ret = NX_NULL;
107 }
108
109 /* Verify gateway address is reachable. */
110 address_type = IPv6_Address_Type(router_addr);
111 if (address_type & IPV6_ADDRESS_UNICAST)
112 {
113
114 /* It is a unicast address. */
115 if (address_type & IPV6_ADDRESS_GLOBAL)
116 {
117
118 /* It is a global address. */
119 /* Point to the first address unit in the interface. */
120 ipv6_address = if_ptr -> nxd_interface_ipv6_address_list_head;
121 while (ipv6_address)
122 {
123
124 /* Check whether destination is on link. */
125 if (_nxd_ipv6_find_max_prefix_length(router_addr, ipv6_address -> nxd_ipv6_address,
126 ipv6_address -> nxd_ipv6_address_prefix_length) >= ipv6_address -> nxd_ipv6_address_prefix_length)
127 {
128
129 /* Router address is on link. */
130 break;
131 }
132
133 /* Point to the next address unit. */
134 ipv6_address = ipv6_address -> nxd_ipv6_address_next;
135 }
136
137 if (ipv6_address == NX_NULL)
138 {
139
140 /* Gateway address is unreachable. */
141 return(NX_IP_ADDRESS_ERROR);
142 }
143 }
144 }
145 else
146 {
147
148 /* Gateway address is unreachable. */
149 return(NX_IP_ADDRESS_ERROR);
150 }
151
152 /* Search through the list for an already existing entry. */
153 for (i = 0; i < NX_IPV6_DEFAULT_ROUTER_TABLE_SIZE; i++)
154 {
155
156 /* Does this slot contain a valid router? */
157 if (ip_ptr -> nx_ipv6_default_router_table[i].nx_ipv6_default_router_entry_flag)
158 {
159
160 /* Check for matching router address. */
161 if (CHECK_IPV6_ADDRESSES_SAME(router_addr, ip_ptr -> nx_ipv6_default_router_table[i].nx_ipv6_default_router_entry_router_address) &&
162 if_ptr == ip_ptr -> nx_ipv6_default_router_table[i].nx_ipv6_default_router_entry_interface_ptr)
163 {
164
165 /* Its a match! */
166 ret = &ip_ptr -> nx_ipv6_default_router_table[i];
167
168 /* Update the router lifetime with the specified input. */
169 ret -> nx_ipv6_default_router_entry_life_time = (USHORT)router_lifetime;
170
171 /* Set a pointer to the router location in the table. */
172 if (_ret)
173 {
174 *_ret = ret;
175 }
176
177 return(NX_SUCCESS);
178 }
179 }
180 else
181 {
182
183 /* Flag this as a slot we can use to add the new router. */
184 if (first_available == (UINT)0xFFFFFFFF)
185 {
186 first_available = i;
187 }
188 }
189 }
190
191 /* Did we find an empty slot in the table? */
192 if (first_available != (UINT)0xFFFFFFFF)
193 {
194
195 /* Set up local pointer. */
196 ret = &ip_ptr -> nx_ipv6_default_router_table[first_available];
197
198 /* Copy the router's address into the router table. */
199 COPY_IPV6_ADDRESS(router_addr, ret -> nx_ipv6_default_router_entry_router_address);
200
201 /* Add the specified input to the router record. */
202 ret -> nx_ipv6_default_router_entry_flag = (UCHAR)(router_type | NX_IPV6_ROUTE_TYPE_VALID);
203 ret -> nx_ipv6_default_router_entry_life_time = (USHORT)router_lifetime;
204
205 /* Set the interface index. */
206 ret -> nx_ipv6_default_router_entry_interface_ptr = if_ptr;
207
208 /* Has no entry in the cache table. Neighbor Discovery process handles this
209 automaticaly. */
210 ret -> nx_ipv6_default_router_entry_neighbor_cache_ptr = NX_NULL;
211
212 /* Update the count of routers currently in the table. */
213 ip_ptr -> nx_ipv6_default_router_table_size++;
214 }
215 else
216 {
217
218 /* No empty slot. */
219 return(NX_NO_MORE_ENTRIES);
220 }
221
222 /* If a router pointer was supplied, set it to the location of the router
223 we just added to the table. */
224 if (_ret)
225 {
226 *_ret = ret;
227 }
228
229 /* Successful completion, we're done! */
230 return(NX_SUCCESS);
231 }
232
233
234 #endif /* FEATURE_NX_IPV6 */
235
236