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