]> git.sur5r.net Git - freertos/blob - Demo/lwIP_Demo_Rowley_ARM7/lwip-1.1.0/src/core/ipv4/icmp.c
Start to re-arrange files to include FreeRTOS+ in main download.
[freertos] / Demo / lwIP_Demo_Rowley_ARM7 / lwip-1.1.0 / src / core / ipv4 / icmp.c
1 /*\r
2  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.\r
3  * All rights reserved.\r
4  *\r
5  * Redistribution and use in source and binary forms, with or without modification,\r
6  * are permitted provided that the following conditions are met:\r
7  *\r
8  * 1. Redistributions of source code must retain the above copyright notice,\r
9  *    this list of conditions and the following disclaimer.\r
10  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
11  *    this list of conditions and the following disclaimer in the documentation\r
12  *    and/or other materials provided with the distribution.\r
13  * 3. The name of the author may not be used to endorse or promote products\r
14  *    derived from this software without specific prior written permission.\r
15  *\r
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\r
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\r
19  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\r
21  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\r
24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY\r
25  * OF SUCH DAMAGE.\r
26  *\r
27  * This file is part of the lwIP TCP/IP stack.\r
28  *\r
29  * Author: Adam Dunkels <adam@sics.se>\r
30  *\r
31  */\r
32 \r
33 /* Some ICMP messages should be passed to the transport protocols. This\r
34    is not implemented. */\r
35 \r
36 #include "lwip/opt.h"\r
37 \r
38 #include "lwip/icmp.h"\r
39 #include "lwip/inet.h"\r
40 #include "lwip/ip.h"\r
41 #include "lwip/def.h"\r
42 \r
43 #include "lwip/stats.h"\r
44 \r
45 #include "lwip/snmp.h"\r
46 \r
47 #include <string.h>\r
48 \r
49 void\r
50 icmp_input(struct pbuf *p, struct netif *inp)\r
51 {\r
52   unsigned char type;\r
53   unsigned char code;\r
54   struct icmp_echo_hdr *iecho;\r
55   struct ip_hdr *iphdr;\r
56   struct ip_addr tmpaddr;\r
57   u16_t hlen;\r
58 \r
59   ICMP_STATS_INC(icmp.recv);\r
60   snmp_inc_icmpinmsgs();\r
61 \r
62 \r
63   iphdr = p->payload;\r
64   hlen = IPH_HL(iphdr) * 4;\r
65   if (pbuf_header(p, -((s16_t)hlen)) || (p->tot_len < sizeof(u16_t)*2)) {\r
66     LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%u bytes) received\n", p->tot_len));\r
67     pbuf_free(p);\r
68     ICMP_STATS_INC(icmp.lenerr);\r
69     snmp_inc_icmpinerrors();\r
70     return;\r
71   }\r
72 \r
73   type = *((u8_t *)p->payload);\r
74   code = *(((u8_t *)p->payload)+1);\r
75   switch (type) {\r
76   case ICMP_ECHO:\r
77     /* broadcast or multicast destination address? */\r
78     if (ip_addr_isbroadcast(&iphdr->dest, inp) || ip_addr_ismulticast(&iphdr->dest)) {\r
79       LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n"));\r
80       ICMP_STATS_INC(icmp.err);\r
81       pbuf_free(p);\r
82       return;\r
83     }\r
84     LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));\r
85     if (p->tot_len < sizeof(struct icmp_echo_hdr)) {\r
86       LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));\r
87       pbuf_free(p);\r
88       ICMP_STATS_INC(icmp.lenerr);\r
89       snmp_inc_icmpinerrors();\r
90 \r
91       return;\r
92     }\r
93     iecho = p->payload;\r
94     if (inet_chksum_pbuf(p) != 0) {\r
95       LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));\r
96       pbuf_free(p);\r
97       ICMP_STATS_INC(icmp.chkerr);\r
98       snmp_inc_icmpinerrors();\r
99       return;\r
100     }\r
101     tmpaddr.addr = iphdr->src.addr;\r
102     iphdr->src.addr = iphdr->dest.addr;\r
103     iphdr->dest.addr = tmpaddr.addr;\r
104     ICMPH_TYPE_SET(iecho, ICMP_ER);\r
105     /* adjust the checksum */\r
106     if (iecho->chksum >= htons(0xffff - (ICMP_ECHO << 8))) {\r
107       iecho->chksum += htons(ICMP_ECHO << 8) + 1;\r
108     } else {\r
109       iecho->chksum += htons(ICMP_ECHO << 8);\r
110     }\r
111     ICMP_STATS_INC(icmp.xmit);\r
112     /* increase number of messages attempted to send */\r
113     snmp_inc_icmpoutmsgs();\r
114     /* increase number of echo replies attempted to send */\r
115     snmp_inc_icmpoutechoreps();\r
116 \r
117     pbuf_header(p, hlen);\r
118     ip_output_if(p, &(iphdr->src), IP_HDRINCL,\r
119                  IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp);\r
120     break;\r
121   default:\r
122   LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %d code %d not supported.\n", (int)type, (int)code));\r
123     ICMP_STATS_INC(icmp.proterr);\r
124     ICMP_STATS_INC(icmp.drop);\r
125   }\r
126   pbuf_free(p);\r
127 }\r
128 \r
129 void\r
130 icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)\r
131 {\r
132   struct pbuf *q;\r
133   struct ip_hdr *iphdr;\r
134   struct icmp_dur_hdr *idur;\r
135 \r
136   q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);\r
137   /* ICMP header + IP header + 8 bytes of data */\r
138 \r
139   iphdr = p->payload;\r
140 \r
141   idur = q->payload;\r
142   ICMPH_TYPE_SET(idur, ICMP_DUR);\r
143   ICMPH_CODE_SET(idur, t);\r
144 \r
145   memcpy((char *)q->payload + 8, p->payload, IP_HLEN + 8);\r
146 \r
147   /* calculate checksum */\r
148   idur->chksum = 0;\r
149   idur->chksum = inet_chksum(idur, q->len);\r
150   ICMP_STATS_INC(icmp.xmit);\r
151   /* increase number of messages attempted to send */\r
152   snmp_inc_icmpoutmsgs();\r
153   /* increase number of destination unreachable messages attempted to send */\r
154   snmp_inc_icmpoutdestunreachs();\r
155 \r
156   ip_output(q, NULL, &(iphdr->src),\r
157             ICMP_TTL, 0, IP_PROTO_ICMP);\r
158   pbuf_free(q);\r
159 }\r
160 \r
161 #if IP_FORWARD\r
162 void\r
163 icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)\r
164 {\r
165   struct pbuf *q;\r
166   struct ip_hdr *iphdr;\r
167   struct icmp_te_hdr *tehdr;\r
168 \r
169   q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);\r
170 \r
171   iphdr = p->payload;\r
172   LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));\r
173   ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));\r
174   LWIP_DEBUGF(ICMP_DEBUG, (" to "));\r
175   ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));\r
176   LWIP_DEBUGF(ICMP_DEBUG, ("\n"));\r
177 \r
178   tehdr = q->payload;\r
179   ICMPH_TYPE_SET(tehdr, ICMP_TE);\r
180   ICMPH_CODE_SET(tehdr, t);\r
181 \r
182   /* copy fields from original packet */\r
183   memcpy((char *)q->payload + 8, (char *)p->payload, IP_HLEN + 8);\r
184 \r
185   /* calculate checksum */\r
186   tehdr->chksum = 0;\r
187   tehdr->chksum = inet_chksum(tehdr, q->len);\r
188   ICMP_STATS_INC(icmp.xmit);\r
189   /* increase number of messages attempted to send */\r
190   snmp_inc_icmpoutmsgs();\r
191   /* increase number of destination unreachable messages attempted to send */\r
192   snmp_inc_icmpouttimeexcds();\r
193   ip_output(q, NULL, &(iphdr->src),\r
194             ICMP_TTL, 0, IP_PROTO_ICMP);\r
195   pbuf_free(q);\r
196 }\r
197 \r
198 #endif /* IP_FORWARD */\r
199 \r
200 \r
201 \r
202 \r
203 \r
204 \r
205 \r