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