2 * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
27 * This file is part of the lwIP TCP/IP stack.
29 * Author: Adam Dunkels <adam@sics.se>
33 /* Some ICMP messages should be passed to the transport protocols. This
34 is not implemented. */
38 #include "lwip/icmp.h"
39 #include "lwip/inet.h"
43 #include "lwip/stats.h"
45 #include "lwip/snmp.h"
52 icmp_input(struct pbuf
*p
, struct netif
*inp
)
56 struct icmp_echo_hdr
*iecho
;
58 struct ip_addr tmpaddr
;
61 ICMP_STATS_INC(icmp
.recv
);
62 snmp_inc_icmpinmsgs();
66 hlen
= IPH_HL(iphdr
) * 4;
67 if (pbuf_header(p
, -((s16_t
)hlen
)) || (p
->tot_len
< sizeof(u16_t
)*2)) {
68 LWIP_DEBUGF(ICMP_DEBUG
, ("icmp_input: short ICMP (%u bytes) received\n", p
->tot_len
));
70 ICMP_STATS_INC(icmp
.lenerr
);
71 snmp_inc_icmpinerrors();
75 type
= *((u8_t
*)p
->payload
);
76 code
= *(((u8_t
*)p
->payload
)+1);
79 if (ip_addr_isbroadcast(&iphdr
->dest
, &inp
->netmask
) ||
80 ip_addr_ismulticast(&iphdr
->dest
)) {
81 LWIP_DEBUGF(ICMP_DEBUG
, ("Smurf.\n"));
82 ICMP_STATS_INC(icmp
.err
);
86 LWIP_DEBUGF(ICMP_DEBUG
, ("icmp_input: ping\n"));
87 if (p
->tot_len
< sizeof(struct icmp_echo_hdr
)) {
88 LWIP_DEBUGF(ICMP_DEBUG
, ("icmp_input: bad ICMP echo received\n"));
90 ICMP_STATS_INC(icmp
.lenerr
);
91 snmp_inc_icmpinerrors();
96 if (inet_chksum_pbuf(p
) != 0) {
97 LWIP_DEBUGF(ICMP_DEBUG
, ("icmp_input: checksum failed for received ICMP echo\n"));
99 ICMP_STATS_INC(icmp
.chkerr
);
100 snmp_inc_icmpinerrors();
103 tmpaddr
.addr
= iphdr
->src
.addr
;
104 iphdr
->src
.addr
= iphdr
->dest
.addr
;
105 iphdr
->dest
.addr
= tmpaddr
.addr
;
106 ICMPH_TYPE_SET(iecho
, ICMP_ER
);
107 /* adjust the checksum */
108 if (iecho
->chksum
>= htons(0xffff - (ICMP_ECHO
<< 8))) {
109 iecho
->chksum
+= htons(ICMP_ECHO
<< 8) + 1;
111 iecho
->chksum
+= htons(ICMP_ECHO
<< 8);
113 ICMP_STATS_INC(icmp
.xmit
);
114 /* increase number of messages attempted to send */
115 snmp_inc_icmpoutmsgs();
116 /* increase number of echo replies attempted to send */
117 snmp_inc_icmpoutechoreps();
119 pbuf_header(p
, hlen
);
120 ip_output_if(p
, &(iphdr
->src
), IP_HDRINCL
,
121 IPH_TTL(iphdr
), 0, IP_PROTO_ICMP
, inp
);
124 LWIP_DEBUGF(ICMP_DEBUG
, ("icmp_input: ICMP type %d code %d not supported.\n", (int)type
, (int)code
));
125 ICMP_STATS_INC(icmp
.proterr
);
126 ICMP_STATS_INC(icmp
.drop
);
132 icmp_dest_unreach(struct pbuf
*p
, enum icmp_dur_type t
)
135 struct ip_hdr
*iphdr
;
136 struct icmp_dur_hdr
*idur
;
138 q
= pbuf_alloc(PBUF_IP
, 8 + IP_HLEN
+ 8, PBUF_RAM
);
139 /* ICMP header + IP header + 8 bytes of data */
144 ICMPH_TYPE_SET(idur
, ICMP_DUR
);
145 ICMPH_CODE_SET(idur
, t
);
147 mips_memcpy((char *)q
->payload
+ 8, p
->payload
, IP_HLEN
+ 8);
149 /* calculate checksum */
151 idur
->chksum
= inet_chksum(idur
, q
->len
);
152 ICMP_STATS_INC(icmp
.xmit
);
153 /* increase number of messages attempted to send */
154 snmp_inc_icmpoutmsgs();
155 /* increase number of destination unreachable messages attempted to send */
156 snmp_inc_icmpoutdestunreachs();
158 ip_output(q
, NULL
, &(iphdr
->src
),
159 ICMP_TTL
, 0, IP_PROTO_ICMP
);
165 icmp_time_exceeded(struct pbuf
*p
, enum icmp_te_type t
)
168 struct ip_hdr
*iphdr
;
169 struct icmp_te_hdr
*tehdr
;
171 q
= pbuf_alloc(PBUF_IP
, 8 + IP_HLEN
+ 8, PBUF_RAM
);
174 LWIP_DEBUGF(ICMP_DEBUG
, ("icmp_time_exceeded from "));
175 ip_addr_debug_print(ICMP_DEBUG
, &(iphdr
->src
));
176 LWIP_DEBUGF(ICMP_DEBUG
, (" to "));
177 ip_addr_debug_print(ICMP_DEBUG
, &(iphdr
->dest
));
178 LWIP_DEBUGF(ICMP_DEBUG
, ("\n"));
181 ICMPH_TYPE_SET(tehdr
, ICMP_TE
);
182 ICMPH_CODE_SET(tehdr
, t
);
184 /* copy fields from original packet */
185 mips_memcpy((char *)q
->payload
+ 8, (char *)p
->payload
, IP_HLEN
+ 8);
187 /* calculate checksum */
189 tehdr
->chksum
= inet_chksum(tehdr
, q
->len
);
190 ICMP_STATS_INC(icmp
.xmit
);
191 /* increase number of messages attempted to send */
192 snmp_inc_icmpoutmsgs();
193 /* increase number of destination unreachable messages attempted to send */
194 snmp_inc_icmpouttimeexcds();
195 ip_output(q
, NULL
, &(iphdr
->src
),
196 ICMP_TTL
, 0, IP_PROTO_ICMP
);
200 #endif /* IP_FORWARD */