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 /**************************************************************************/
15 /**                                                                       */
16 /** NetX Component                                                        */
17 /**                                                                       */
18 /**   Internet Protocol (IP)                                              */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 #define NX_SOURCE_CODE
24 
25 
26 /* Include necessary system files.  */
27 
28 #include "nx_api.h"
29 #include "nx_ip.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _nx_ip_static_route_add                             PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Yuxin Zhou, Microsoft Corporation                                   */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function adds a static routing entry to the routing table.     */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    ip_ptr                                Pointer to IP instance        */
49 /*    network_address                       Network address, in host byte */
50 /*                                            order.                      */
51 /*    net_mask                              Network Mask, in host byte    */
52 /*                                            order.                      */
53 /*    next_hop                              Next Hop address, in host     */
54 /*                                            byte order.                 */
55 /*                                                                        */
56 /*  OUTPUT                                                                */
57 /*                                                                        */
58 /*    status                                Completion status             */
59 /*                                                                        */
60 /*  CALLS                                                                 */
61 /*                                                                        */
62 /*    tx_mutex_get                          Obtain a protection mutex     */
63 /*    tx_mutex_put                          Release protection mutex      */
64 /*                                                                        */
65 /*  CALLED BY                                                             */
66 /*                                                                        */
67 /*    Application                                                         */
68 /*                                                                        */
69 /*  NOTE:                                                                 */
70 /*                                                                        */
71 /*    next hop address must be on the local network.                      */
72 /*                                                                        */
73 /*  RELEASE HISTORY                                                       */
74 /*                                                                        */
75 /*    DATE              NAME                      DESCRIPTION             */
76 /*                                                                        */
77 /*  05-19-2020     Yuxin Zhou               Initial Version 6.0           */
78 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
79 /*                                            resulting in version 6.1    */
80 /*                                                                        */
81 /**************************************************************************/
_nx_ip_static_route_add(NX_IP * ip_ptr,ULONG network_address,ULONG net_mask,ULONG next_hop)82 UINT  _nx_ip_static_route_add(NX_IP *ip_ptr, ULONG network_address,
83                               ULONG net_mask, ULONG next_hop)
84 {
85 #if !defined(NX_DISABLE_IPV4) && defined(NX_ENABLE_IP_STATIC_ROUTING)
86 INT           i;
87 NX_INTERFACE *nx_ip_interface = NX_NULL;
88 
89     /* If trace is enabled, insert this event into the trace buffer.  */
90     NX_TRACE_IN_LINE_INSERT(NX_TRACE_IP_STATIC_ROUTE_ADD, ip_ptr, network_address, net_mask, next_hop, NX_TRACE_IP_EVENTS, 0, 0);
91 
92     /* Obtain the IP mutex so we can manipulate the internal routing table. */
93     /* This routine does not need to be protected by mask off interrupt
94        because it cannot be invoked from ISR. */
95     tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER);
96 
97     /* Make sure next hop is on one of the interfaces. */
98     for (i = 0; i < NX_MAX_IP_INTERFACES; i++)
99     {
100 
101         if (ip_ptr -> nx_ip_interface[i].nx_interface_valid &&
102             ((next_hop & (ip_ptr -> nx_ip_interface[i].nx_interface_ip_network_mask)) == ip_ptr -> nx_ip_interface[i].nx_interface_ip_network))
103         {
104 
105             nx_ip_interface = &(ip_ptr -> nx_ip_interface[i]);
106 
107             /* Break out of the for loop */
108             break;
109         }
110     }
111 
112     /* If no matching interface, return the error status. */
113     if (nx_ip_interface == NX_NULL)
114     {
115 
116         /* Unlock the mutex, and return the error status. */
117         tx_mutex_put(&(ip_ptr -> nx_ip_protection));
118 
119         return(NX_IP_ADDRESS_ERROR);
120     }
121 
122     /* Obtain the network address, based on net_mask passed in. */
123     network_address = network_address & net_mask;
124 
125     /* Search through the routing table, check whether the same entry exists. */
126     for (i = 0; i < (INT)ip_ptr -> nx_ip_routing_table_entry_count; i++)
127     {
128 
129         if (ip_ptr -> nx_ip_routing_table[i].nx_ip_routing_dest_ip == network_address &&
130             ip_ptr -> nx_ip_routing_table[i].nx_ip_routing_net_mask == net_mask)
131         {
132 
133             /* Found the same entry: only need to update the next hop field */
134             ip_ptr -> nx_ip_routing_table[i].nx_ip_routing_next_hop_address = next_hop;
135 
136             /* All done.  Unlock the mutex, and return */
137             tx_mutex_put(&(ip_ptr -> nx_ip_protection));
138             return(NX_SUCCESS);
139         }
140 
141         /* The net mask that has more top bits set has a greater numerical value than the
142            one with less top bits set.  During a search we want to match smaller nets
143            (more top bits set, or larger numerical value) before matching larger nets. */
144         if (ip_ptr -> nx_ip_routing_table[i].nx_ip_routing_net_mask <= net_mask)
145         {
146 
147         INT j;
148 
149             /* Check whether the table is full. */
150             if (ip_ptr -> nx_ip_routing_table_entry_count == NX_IP_ROUTING_TABLE_SIZE)
151             {
152 
153                 tx_mutex_put(&(ip_ptr -> nx_ip_protection));
154                 return(NX_OVERFLOW);
155             }
156 
157             /* The entry pointed to by "i" is a larger network (thus smaller net mask
158                value.  The new entry needs to be inserted before "i".
159 
160                To do so, we need to make room for the new entry, by shifting entries i and
161                after one slot. */
162             for (j = (INT)ip_ptr -> nx_ip_routing_table_entry_count - 1; j >= i; j--)
163             {
164 
165                 ip_ptr -> nx_ip_routing_table[j + 1].nx_ip_routing_dest_ip =
166                     ip_ptr -> nx_ip_routing_table[j].nx_ip_routing_dest_ip;
167                 ip_ptr -> nx_ip_routing_table[j + 1].nx_ip_routing_net_mask =
168                     ip_ptr -> nx_ip_routing_table[j].nx_ip_routing_net_mask;
169                 ip_ptr -> nx_ip_routing_table[j + 1].nx_ip_routing_next_hop_address =
170                     ip_ptr -> nx_ip_routing_table[j].nx_ip_routing_next_hop_address;
171                 ip_ptr -> nx_ip_routing_table[j + 1].nx_ip_routing_entry_ip_interface =
172                     ip_ptr -> nx_ip_routing_table[j].nx_ip_routing_entry_ip_interface;
173             }
174 
175             break;
176         }
177     }
178 
179     /* Check whether the table is full. */
180     if (i == NX_IP_ROUTING_TABLE_SIZE)
181     {
182         tx_mutex_put(&(ip_ptr -> nx_ip_protection));
183         return(NX_OVERFLOW);
184     }
185 
186     ip_ptr -> nx_ip_routing_table[i].nx_ip_routing_dest_ip = network_address;
187     ip_ptr -> nx_ip_routing_table[i].nx_ip_routing_net_mask = net_mask;
188     ip_ptr -> nx_ip_routing_table[i].nx_ip_routing_next_hop_address = next_hop;
189     ip_ptr -> nx_ip_routing_table[i].nx_ip_routing_entry_ip_interface = nx_ip_interface;
190 
191     ip_ptr -> nx_ip_routing_table_entry_count++;
192 
193     /* Unlock the mutex. */
194     tx_mutex_put(&(ip_ptr -> nx_ip_protection));
195 
196     /* Return success to the caller.  */
197     return(NX_SUCCESS);
198 
199 #else /* !NX_DISABLE_IPV4 && NX_ENABLE_IP_STATIC_ROUTING  */
200     NX_PARAMETER_NOT_USED(ip_ptr);
201     NX_PARAMETER_NOT_USED(network_address);
202     NX_PARAMETER_NOT_USED(net_mask);
203     NX_PARAMETER_NOT_USED(next_hop);
204 
205     return(NX_NOT_SUPPORTED);
206 
207 #endif /* !NX_DISABLE_IPV4 && NX_ENABLE_IP_STATIC_ROUTING  */
208 }
209 
210