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