Initial c661x version
[keystone-rtos/ibl.git] / src / driver / eth / icmp.c
1 /** 
2  *   @file  icmp.c
3  *
4  *   @brief   
5  *      The file implements the NET Module ICMP 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 <blf.h>
42 #include "netif.h"
43 #include "net_osal.h"
45 #ifdef INCLUDE_BLF_NET_MODULE
46 #ifdef INCLUDE_BLF_NET_ICMP
48 /**
49  *  @b Description
50  *  @n  
51  *       The function computes the ICMP checksum and populates the ICMP
52  *       Checksum field.
53  *
54  *  @param[in]  ptr_icmp_hdr
55  *      This is the pointer to the ICMP header.
56  *  @param[in]  size
57  *      This is the total size of the ICMP packet including header and data
58  *      payload.
59  *
60  *  @retval
61  *      Not Applicable.
62  */
63 static void icmp_checksum (ICMPHDR *ptr_icmp_hdr, Uint16 size)
64 {
65     Int32   tmp1;
66     Uint16* pw;
67     Uint32  TSum;
69     /* Checksum field is NULL in checksum calculations */
70     ptr_icmp_hdr->Checksum = 0;
72     /* Checksum the header */
73     pw = (Uint16 *)ptr_icmp_hdr;
74     TSum = 0;
75     for( tmp1=size; tmp1 > 1; tmp1 -= 2 )
76         TSum += (Uint32)*pw++;
77 #ifdef BIGENDIAN
78     if( tmp1 )
79         TSum += (Uint32)(*pw & 0xFF00);
80 #else
81     if( tmp1 )
82         TSum += (Uint32)(*pw & 0x00FF);
83 #endif
84     TSum = (TSum&0xFFFF) + (TSum>>16);
85     TSum = (TSum&0xFFFF) + (TSum>>16);
86     TSum = ~TSum;
88     /* Note checksum is Net/Host byte order independent */
89     ptr_icmp_hdr->Checksum = (Uint16)TSum;
90     return;
91 }
93 /**
94  *  @b Description
95  *  @n  
96  *       The function handles the processing of ICMP packets.
97  *
98  *  @param[in]  ptr_iphdr
99  *      This is the pointer to the IP header.
100  *
101  *  @retval
102  *      Not Applicable.
103  */
104 void icmp_receive (IPHDR* ptr_iphdr)
106     ICMPHDR*    ptr_icmphdr;
107     Uint16      checksum;
108     Uint16      l4_pkt_size;
109     ICMPHDR*    ptr_reply_hdr;
110     IPHDR*      ptr_reply_iphdr;
112     /* Get the pointer to the ICMP header. */
113     ptr_icmphdr = (ICMPHDR *) ((Uint8 *)ptr_iphdr + IPHDR_SIZE);
115     /* Compute the l4 packet size. */
116     l4_pkt_size = ntohs(ptr_iphdr->TotalLen) - IPHDR_SIZE;
118     /* We only handle ICMP echo requests */
119     if (ptr_icmphdr->Type != ICMP_ECHO_REQUEST_TYPE)
120         return;
122     /* Validate the checksum */
123     checksum = ptr_icmphdr->Checksum;
124     if (checksum == 0xFFFF)
125         checksum = 0;
126     icmp_checksum (ptr_icmphdr, l4_pkt_size);
127     if( checksum != ptr_icmphdr->Checksum )
128         return;
130     /* OK; control comes here implies that a valid ICMP ECHO request
131      * packet was received. Now we send back the ECHO reply; so lets 
132      * allocate a new transmit packet. */
133     ptr_reply_iphdr = (IPHDR *)net_alloc_tx_packet (l4_pkt_size + IPHDR_SIZE);
134     if (ptr_reply_iphdr == NULL)
135         return;
137     /* We can blindly copy the 'original' IP packet to the 'reply' IP packet. */
138     netMemcpy ((void *)ptr_reply_iphdr, (void *)ptr_iphdr, (l4_pkt_size + IPHDR_SIZE));
140     /* Get the pointer to the new header. 
141      *  The new header starts after the IP header. */
142     ptr_reply_hdr = (ICMPHDR *)((Uint8 *)ptr_reply_iphdr + IPHDR_SIZE);
144     /* This is an ECHO reply packet; so lets overwrite the field. */ 
145     ptr_reply_hdr->Type = ICMP_ECHO_REPLY_TYPE;
147     /* Compute the new ICMP checksum and overwrite it in the header. */
148     icmp_checksum (ptr_reply_hdr, l4_pkt_size);
150     /* Swap the source and destination address in the REPLY packet. */
151     ptr_reply_iphdr->IPSrc = ptr_iphdr->IPDst;
152     ptr_reply_iphdr->IPDst = ptr_iphdr->IPSrc;
154     /* Packet looks good. Send to the IP layer for transmission. */
155     ip_send (ptr_reply_iphdr, l4_pkt_size + IPHDR_SIZE);
156     return;
159 #endif /* INCLUDE_BLF_NET_ICMP */
160 #endif /* INCLUDE_BLF_NET_MODULE */