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