1 /**
2 * @file ip.c
3 *
4 * @brief
5 * The file implements the NET Module IPv4 functionality.
6 *
7 * \par
8 * NOTE:
9 * (C) Copyright 2008, Texas Instruments, Inc.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 *
18 * Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the
21 * distribution.
22 *
23 * Neither the name of Texas Instruments Incorporated nor the names of
24 * its contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 *
39 * \par
40 */
41 #include "types.h"
42 #include "iblloc.h"
43 #include "net.h"
44 #include "netif.h"
45 #include <string.h>
46 #include "net_osal.h"
49 /**
50 * @brief This is the size of the NET Boot Module Routing table.
51 * This definition should never be modified. If changed then the API
52 * for adding/deleting routes will also need to be modified.
53 */
54 #define MAX_RT_TABLE_SIZE 2
56 /**
57 * @brief This is the global routing table which is used by
58 * the stack to determine the route on which the packet needs to
59 * be transmitted.
60 */
61 RT_ENTRY rt_table[MAX_RT_TABLE_SIZE];
63 /**********************************************************************
64 **************************** IP Functions ****************************
65 **********************************************************************/
67 /**
68 * @b Description
69 * @n
70 * The function adds a route to the routing table. Default routes are
71 * always added to the last entry in the routing table. There is no
72 * duplicate route checking done here and if an entry exists it is
73 * overriden with the new values.
74 *
75 * @param[in] flag
76 * Flag properties associated with the route
77 * @param[in] ip_address
78 * IP Address associated with the route.
79 * @param[in] net_mask
80 * Network Mask associated with the route
81 * @param[in] next_hop
82 * Next Hop Address associated with the route. This is applicable
83 * for default gateways. For network routes this is ignored.
84 *
85 * @retval
86 * Success - 0
87 * @retval
88 * Error - <0
89 */
90 Int32 ip_add_route (Uint32 flag, IPN ip_address, IPN net_mask, IPN next_hop)
91 {
92 RT_ENTRY* ptr_rt;
94 /* Basic Sanity Check: The flag should be correct! */
95 if ((flag != FLG_RT_NETWORK) && (flag != FLG_RT_DEFAULT))
96 return -1;
98 /* Check if the flag is a network route being added? */
99 if (flag == FLG_RT_NETWORK)
100 {
101 /* Network route is being added. */
102 ptr_rt = &rt_table[0];
104 /* Populate the routing entry. */
105 ptr_rt->flags = FLG_RT_NETWORK;
106 ptr_rt->ip_addr = ip_address;
107 ptr_rt->net_mask = net_mask;
108 ptr_rt->net_addr = ip_address & net_mask;
109 ptr_rt->next_hop = ip_address;
110 }
111 else
112 {
113 /* Default route is being added. */
114 ptr_rt = &rt_table[1];
116 /* Populate the routing entry. */
117 ptr_rt->flags = FLG_RT_DEFAULT;
118 ptr_rt->ip_addr = 0x0;
119 ptr_rt->net_mask = 0x0;
120 ptr_rt->net_addr = 0x0;
121 ptr_rt->next_hop = next_hop;
122 }
124 /* Routes were added successfully. */
125 return 0;
126 }
128 /**
129 * @b Description
130 * @n
131 * The function checks the routing table to determine a
132 * suitable route which needs to be taken to send out the
133 * packet.
134 *
135 * @param[in] ip_address
136 * IP Address for which the route is being looked up.
137 *
138 * @retval
139 * Success - Pointer to the routing entry being used.
140 * @retval
141 * Error - NULL (There is no route which can be used)
142 */
143 RT_ENTRY* ip_lookup_route (IPN ip_address)
144 {
145 Int32 index = 0;
146 RT_ENTRY* ptr_rt;
147 IPN network_address;
149 /* Cycle through the routing table. */
150 for (index = 0; index < MAX_RT_TABLE_SIZE; index++)
151 {
152 /* Get the pointer to the routing table entry. */
153 ptr_rt = &rt_table[index];
155 /* Check if there is a valid entry or not? */
156 if (ptr_rt->flags & (FLG_RT_NETWORK | FLG_RT_DEFAULT))
157 {
158 /* Valid routing entry was found; calculate the network address
159 * with respect to the route netmask and match it. */
160 network_address = ip_address & ptr_rt->net_mask;
162 /* Check if this matches the same network to which we are sending the packet. */
163 if (network_address == ptr_rt->net_addr)
164 {
165 /* YES. Perfect; we can return this routing entry. */
166 return ptr_rt;
167 }
168 }
169 }
171 /* Control comes here indicates that there was no routing entry which could be used. */
172 return NULL;
173 }
175 /**
176 * @b Description
177 * @n
178 * The function deletes the routing table entry.
179 *
180 * @param[in] flag
181 * This is the routing entry which is being deleted.
182 *
183 * @retval
184 * Not Applicable.
185 */
186 void ip_del_route (Uint32 flag)
187 {
188 RT_ENTRY* ptr_rt;
190 /* Check if the flag is a network route being added? */
191 if (flag == FLG_RT_NETWORK)
192 {
193 /* Network route is being deleted. */
194 ptr_rt = &rt_table[0];
195 }
196 else
197 {
198 if (flag == FLG_RT_DEFAULT)
199 {
200 /* Default route is being deleted. */
201 ptr_rt = &rt_table[0];
202 }
203 else
204 {
205 /* Invalid Flag combination passed. */
206 return;
207 }
208 }
210 /* Simply reset all the fields */
211 netMemset ((void *)ptr_rt, 0, sizeof(RT_ENTRY));
212 return;
213 }
215 /**
216 * @b Description
217 * @n
218 * The function computes the IP checksum. The computed checksum
219 * is populated in the IP header.
220 *
221 * @param[in] ptr_iphdr
222 * This is the pointer to the IPv4 header for which the checksum
223 * is computed.
224 *
225 * @retval
226 * Not Applicable.
227 */
228 static void ip_checksum(IPHDR *ptr_iphdr)
229 {
230 Int32 tmp1;
231 Uint16 *pw;
232 Uint32 TSum = 0;
234 /* Get header size in 4 byte chunks */
235 tmp1 = ptr_iphdr->VerLen & 0xF;
237 /* Checksum field is NULL in checksum calculations */
238 ptr_iphdr->Checksum = 0;
240 /* Checksum the header */
241 pw = (Uint16 *)ptr_iphdr;
242 do {
243 TSum += (Uint32)*pw++;
244 TSum += (Uint32)*pw++;
245 } while( --tmp1 );
246 TSum = (TSum&0xFFFF) + (TSum>>16);
247 TSum = (TSum&0xFFFF) + (TSum>>16);
248 TSum = ~TSum;
250 /* Note checksum is Net/Host byte order independent */
251 ptr_iphdr->Checksum = (Uint16)TSum;
252 return;
253 }
255 /**
256 * @b Description
257 * @n
258 * The function handles the processing of IPv4 packets.
259 *
260 * @param[in] ptr_iphdr
261 * This is the pointer to the IPv4 header.
262 * @param[in] num_bytes
263 * This is the total number of bytes which includes the IPv4 header
264 * and data payload.
265 *
266 * @retval
267 * Success - 0
268 * @retval
269 * Error - <0
270 */
271 Int32 ip_receive (IPHDR* ptr_iphdr, Int32 num_bytes)
272 {
273 Uint32 checksum;
275 /* Basic IPv4 Packet Validations: Ensure that this is an IPv4 packet. */
276 if ((ptr_iphdr->VerLen & 0xF0) != 0x40)
277 return -1;
279 /* Validate the length of the received packet; it cannot be greater
280 * than the total length of the received packet. */
281 if (ntohs(ptr_iphdr->TotalLen) > num_bytes)
282 return -1;
284 /* Checksum validation. */
285 checksum = ptr_iphdr->Checksum;
286 if (checksum == 0xFFFF )
287 checksum = 0;
288 ip_checksum (ptr_iphdr);
289 if (checksum != ptr_iphdr->Checksum )
290 return -1;
292 /* We dont handle any IP option processing.
293 * Thus if the IP header length is greater than 20 bytes the packet is dropped. */
294 if (((ptr_iphdr->VerLen & 0xF) << 2) != IPHDR_SIZE)
295 return -1;
297 /* We accept only the following packets:-
298 * a) Destination Address is the address of the NET Boot module.
299 * b) Destination Address is the a special 255.255.255.255 address for BOOTP Reply*/
300 if (netmcb.net_device.use_bootp_server_ip == 0)
301 if ((ptr_iphdr->IPDst != netmcb.net_device.ip_address) && (ptr_iphdr->IPDst != 0xFFFFFFFF))
302 return -1;
304 /* Pass the packet to the layer4 receive handlers. */
305 switch (ptr_iphdr->Protocol)
306 {
307 #ifdef INCLUDE_BLF_NET_ICMP
308 case IPPROTO_ICMP:
309 {
310 icmp_receive (ptr_iphdr);
311 break;
312 }
313 #endif /* INCLUDE_BLF_NET_ICMP */
314 case IPPROTO_UDP:
315 {
316 /* UDP Packet. */
317 if (udp_receive (ptr_iphdr) < 0)
318 net_stats.rx_udp_dropped++;
319 break;
320 }
321 default:
322 {
323 /* No other protocol is handled. */
324 return -1;
325 }
326 }
328 /* Packet has been successfully processed at the IP layer. */
329 return 0;
330 }
332 /**
333 * @b Description
334 * @n
335 * The function is called from the layer4 protocol to send
336 * out an IPv4 packet.
337 *
338 * @param[in] ptr_iphdr
339 * This is the pointer to the IPv4 header + payload which includes
340 * the layer4 header and actual data payload.
341 * The layer4 protocol is supposed to populate the following IPv4 fields:-
342 * - Protocol
343 * - Destination IP
344 * The rest of the fields in the IPv4 header are populated by this function.
345 *
346 * @param[in] size
347 * This is the total number of bytes which includes the layer4 header
348 * and data payload and the IPv4 header.
349 *
350 * @retval
351 * Not Applicable.
352 */
353 void ip_send (IPHDR* ptr_iphdr, Uint16 size)
354 {
355 RT_ENTRY* ptr_rt;
356 IPN next_hop_address;
358 /* Special Case: If the IP Address of the packet is 255.255.255.255
359 * we dont need to check the routing table. */
360 if (ptr_iphdr->IPDst != 0xFFFFFFFF)
361 {
362 /* Lookup the routing table for a routing entry. */
363 ptr_rt = ip_lookup_route (ptr_iphdr->IPDst);
364 if (ptr_rt == NULL)
365 {
366 /* There is no route which exists to send the packet. Drop it! */
367 net_free_tx_packet ((Uint8 *)ptr_iphdr);
368 return;
369 }
371 /* Control comes here indicating that a route exists and the packet
372 * can be sent out. There are 2 types of routes in the system:-
373 * a) Network Routes which are directly attached and in this case
374 * the next hop ip address is the same as the destination IP address
375 * b) Default Routes which is the address of the default gateway to which
376 * we need to send the packet since the destination network is not
377 * directly connected.
378 * So here we determine the next hop address based on the route type. */
379 if (ptr_rt->flags == FLG_RT_NETWORK)
380 next_hop_address = ptr_iphdr->IPDst;
381 else
382 next_hop_address = ptr_rt->next_hop;
383 }
384 else
385 {
386 /* This is a BOOTP request being sent out to 255.255.255.255. Set the
387 * next hop address to be the same. */
388 next_hop_address = ptr_iphdr->IPDst;
389 }
391 /* Ensure all the fields in the IPv4 header are populated correctly */
392 ptr_iphdr->VerLen = 0x45;
393 ptr_iphdr->Tos = 0;
394 ptr_iphdr->Id = netmcb.ipID++;
395 ptr_iphdr->FlagOff = 0;
396 ptr_iphdr->Ttl = 64;
397 ptr_iphdr->TotalLen = htons(size);
398 ptr_iphdr->IPSrc = netmcb.net_device.ip_address;
400 /* Here we recompute the IP Checksum. */
401 ip_checksum (ptr_iphdr);
403 /* Layer2 resolution is done on the Next hop address. */
404 arp_resolve (next_hop_address, ptr_iphdr, size);
405 return;
406 }
408 /**
409 * @b Description
410 * @n
411 * The function initializes the IP Module in the NET Boot module.
412 *
413 * @retval
414 * Not Applicable
415 */
416 void ip_init (void)
417 {
418 /* Reset the routing table */
419 netMemset (&rt_table, 0, sizeof(rt_table));
420 return;
421 }