]> git.sur5r.net Git - freertos/blob - Demo/lwIP_MCF5235_GCC/lwip/src/core/ipv4/icmp.c
Start to re-arrange files to include FreeRTOS+ in main download.
[freertos] / Demo / lwIP_MCF5235_GCC / lwip / 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 <string.h>\r
37 \r
38 #include "lwip/opt.h"\r
39 #include "lwip/icmp.h"\r
40 #include "lwip/inet.h"\r
41 #include "lwip/ip.h"\r
42 #include "lwip/def.h"\r
43 #include "lwip/stats.h"\r
44 #include "lwip/snmp.h"\r
45 \r
46 void\r
47 icmp_input(struct pbuf *p, struct netif *inp)\r
48 {\r
49   u8_t type;\r
50   u8_t code;\r
51   struct icmp_echo_hdr *iecho;\r
52   struct ip_hdr *iphdr;\r
53   struct ip_addr tmpaddr;\r
54   u16_t hlen;\r
55 \r
56   ICMP_STATS_INC(icmp.recv);\r
57   snmp_inc_icmpinmsgs();\r
58 \r
59 \r
60   iphdr = p->payload;\r
61   hlen = IPH_HL(iphdr) * 4;\r
62   if (pbuf_header(p, -((s16_t)hlen)) || (p->tot_len < sizeof(u16_t)*2)) {\r
63     LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: short ICMP (%"U16_F" bytes) received\n", p->tot_len));\r
64     pbuf_free(p);\r
65     ICMP_STATS_INC(icmp.lenerr);\r
66     snmp_inc_icmpinerrors();\r
67     return;\r
68   }\r
69 \r
70   type = *((u8_t *)p->payload);\r
71   code = *(((u8_t *)p->payload)+1);\r
72   switch (type) {\r
73   case ICMP_ECHO:\r
74     /* broadcast or multicast destination address? */\r
75     if (ip_addr_isbroadcast(&iphdr->dest, inp) || ip_addr_ismulticast(&iphdr->dest)) {\r
76       LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: Not echoing to multicast or broadcast pings\n"));\r
77       ICMP_STATS_INC(icmp.err);\r
78       pbuf_free(p);\r
79       return;\r
80     }\r
81     LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ping\n"));\r
82     if (p->tot_len < sizeof(struct icmp_echo_hdr)) {\r
83       LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: bad ICMP echo received\n"));\r
84       pbuf_free(p);\r
85       ICMP_STATS_INC(icmp.lenerr);\r
86       snmp_inc_icmpinerrors();\r
87 \r
88       return;\r
89     }\r
90     iecho = p->payload;\r
91     if (inet_chksum_pbuf(p) != 0) {\r
92       LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));\r
93       pbuf_free(p);\r
94       ICMP_STATS_INC(icmp.chkerr);\r
95       snmp_inc_icmpinerrors();\r
96       return;\r
97     }\r
98     tmpaddr.addr = iphdr->src.addr;\r
99     iphdr->src.addr = iphdr->dest.addr;\r
100     iphdr->dest.addr = tmpaddr.addr;\r
101     ICMPH_TYPE_SET(iecho, ICMP_ER);\r
102     /* adjust the checksum */\r
103     if (iecho->chksum >= htons(0xffff - (ICMP_ECHO << 8))) {\r
104       iecho->chksum += htons(ICMP_ECHO << 8) + 1;\r
105     } else {\r
106       iecho->chksum += htons(ICMP_ECHO << 8);\r
107     }\r
108     ICMP_STATS_INC(icmp.xmit);\r
109     /* increase number of messages attempted to send */\r
110     snmp_inc_icmpoutmsgs();\r
111     /* increase number of echo replies attempted to send */\r
112     snmp_inc_icmpoutechoreps();\r
113 \r
114     pbuf_header(p, hlen);\r
115     ip_output_if(p, &(iphdr->src), IP_HDRINCL,\r
116                  IPH_TTL(iphdr), 0, IP_PROTO_ICMP, inp);\r
117     break;\r
118   default:\r
119   LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: ICMP type %"S16_F" code %"S16_F" not supported.\n", (s16_t)type, (s16_t)code));\r
120     ICMP_STATS_INC(icmp.proterr);\r
121     ICMP_STATS_INC(icmp.drop);\r
122   }\r
123   pbuf_free(p);\r
124 }\r
125 \r
126 void\r
127 icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)\r
128 {\r
129   struct pbuf *q;\r
130   struct ip_hdr *iphdr;\r
131   struct icmp_dur_hdr *idur;\r
132 \r
133   q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);\r
134   /* ICMP header + IP header + 8 bytes of data */\r
135 \r
136   iphdr = p->payload;\r
137 \r
138   idur = q->payload;\r
139   ICMPH_TYPE_SET(idur, ICMP_DUR);\r
140   ICMPH_CODE_SET(idur, t);\r
141 \r
142   memcpy((u8_t *)q->payload + 8, p->payload, IP_HLEN + 8);\r
143 \r
144   /* calculate checksum */\r
145   idur->chksum = 0;\r
146   idur->chksum = inet_chksum(idur, q->len);\r
147   ICMP_STATS_INC(icmp.xmit);\r
148   /* increase number of messages attempted to send */\r
149   snmp_inc_icmpoutmsgs();\r
150   /* increase number of destination unreachable messages attempted to send */\r
151   snmp_inc_icmpoutdestunreachs();\r
152 \r
153   ip_output(q, NULL, &(iphdr->src),\r
154             ICMP_TTL, 0, IP_PROTO_ICMP);\r
155   pbuf_free(q);\r
156 }\r
157 \r
158 #if IP_FORWARD\r
159 void\r
160 icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)\r
161 {\r
162   struct pbuf *q;\r
163   struct ip_hdr *iphdr;\r
164   struct icmp_te_hdr *tehdr;\r
165 \r
166   q = pbuf_alloc(PBUF_IP, 8 + IP_HLEN + 8, PBUF_RAM);\r
167 \r
168   iphdr = p->payload;\r
169   LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));\r
170   ip_addr_debug_print(ICMP_DEBUG, &(iphdr->src));\r
171   LWIP_DEBUGF(ICMP_DEBUG, (" to "));\r
172   ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));\r
173   LWIP_DEBUGF(ICMP_DEBUG, ("\n"));\r
174 \r
175   tehdr = q->payload;\r
176   ICMPH_TYPE_SET(tehdr, ICMP_TE);\r
177   ICMPH_CODE_SET(tehdr, t);\r
178 \r
179   /* copy fields from original packet */\r
180   memcpy((u8_t *)q->payload + 8, (u8_t *)p->payload, IP_HLEN + 8);\r
181 \r
182   /* calculate checksum */\r
183   tehdr->chksum = 0;\r
184   tehdr->chksum = inet_chksum(tehdr, q->len);\r
185   ICMP_STATS_INC(icmp.xmit);\r
186   /* increase number of messages attempted to send */\r
187   snmp_inc_icmpoutmsgs();\r
188   /* increase number of destination unreachable messages attempted to send */\r
189   snmp_inc_icmpouttimeexcds();\r
190   ip_output(q, NULL, &(iphdr->src),\r
191             ICMP_TTL, 0, IP_PROTO_ICMP);\r
192   pbuf_free(q);\r
193 }\r
194 \r
195 #endif /* IP_FORWARD */\r
196 \r
197 \r
198 \r
199 \r
200 \r
201 \r
202 \r