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