44#if LWIP_IPV4 && LWIP_ICMP
54#ifdef LWIP_HOOK_FILENAME
55#include LWIP_HOOK_FILENAME
61#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
62#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1
66#define ICMP_DEST_UNREACH_DATASIZE 8
68static void icmp_send_response(
struct pbuf *p, u8_t type, u8_t code);
80icmp_input(
struct pbuf *p,
struct netif *inp)
87 const struct ip_hdr *iphdr_in;
91 ICMP_STATS_INC(icmp.recv);
92 MIB2_STATS_INC(mib2.icmpinmsgs);
94 iphdr_in = ip4_current_header();
95 hlen = IPH_HL_BYTES(iphdr_in);
97 LWIP_DEBUGF(
ICMP_DEBUG, (
"icmp_input: short IP header (%"S16_F
" bytes) received\n", hlen));
100 if (p->len <
sizeof(u16_t) * 2) {
101 LWIP_DEBUGF(
ICMP_DEBUG, (
"icmp_input: short ICMP (%"U16_F
" bytes) received\n", p->tot_len));
105 type = *((u8_t *)p->payload);
107 code = *(((u8_t *)p->payload) + 1);
115 MIB2_STATS_INC(mib2.icmpinechoreps);
118 MIB2_STATS_INC(mib2.icmpinechos);
119 src = ip4_current_dest_addr();
121 if (ip4_addr_ismulticast(ip4_current_dest_addr())) {
122#if LWIP_MULTICAST_PING
124 src = netif_ip4_addr(inp);
126 LWIP_DEBUGF(
ICMP_DEBUG, (
"icmp_input: Not echoing to multicast pings\n"));
132#if LWIP_BROADCAST_PING
134 src = netif_ip4_addr(inp);
136 LWIP_DEBUGF(
ICMP_DEBUG, (
"icmp_input: Not echoing to broadcast pings\n"));
140 LWIP_DEBUGF(
ICMP_DEBUG, (
"icmp_input: ping\n"));
142 LWIP_DEBUGF(
ICMP_DEBUG, (
"icmp_input: bad ICMP echo received\n"));
145#if CHECKSUM_CHECK_ICMP
146 IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP) {
148 LWIP_DEBUGF(
ICMP_DEBUG, (
"icmp_input: checksum failed for received ICMP echo\n"));
150 ICMP_STATS_INC(icmp.chkerr);
151 MIB2_STATS_INC(mib2.icmpinerrors);
156#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
162 u16_t alloc_len = (u16_t)(p->tot_len + hlen);
164 LWIP_DEBUGF(
ICMP_DEBUG, (
"icmp_input: allocating new pbuf failed (tot_len overflow)\n"));
170 LWIP_DEBUGF(
ICMP_DEBUG, (
"icmp_input: allocating new pbuf failed\n"));
182 LWIP_ASSERT(
"icmp_input: moving r->payload to icmp header failed", 0);
199 LWIP_ASSERT(
"icmp_input: restoring original p->payload failed", 0);
215 ICMPH_TYPE_SET(iecho, ICMP_ER);
216 p->if_idx = NETIF_NO_INDEX;
218 IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP) {
220 if (iecho->chksum > PP_HTONS(0xffffU - (ICMP_ECHO << 8))) {
221 iecho->chksum = (u16_t)(iecho->chksum + PP_HTONS((u16_t)(ICMP_ECHO << 8)) + 1);
223 iecho->chksum = (u16_t)(iecho->chksum + PP_HTONS(ICMP_ECHO << 8));
226#if LWIP_CHECKSUM_CTRL_PER_NETIF
237 IPH_CHKSUM_SET(iphdr, 0);
239 IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_IP) {
240 IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, hlen));
244 ICMP_STATS_INC(icmp.xmit);
246 MIB2_STATS_INC(mib2.icmpoutmsgs);
248 MIB2_STATS_INC(mib2.icmpoutechoreps);
251 ret = ip4_output_if(p, src, LWIP_IP_HDRINCL,
254 LWIP_DEBUGF(
ICMP_DEBUG, (
"icmp_input: ip_output_if returned an error: %s\n", lwip_strerr(ret)));
259 if (type == ICMP_DUR) {
260 MIB2_STATS_INC(mib2.icmpindestunreachs);
261 }
else if (type == ICMP_TE) {
262 MIB2_STATS_INC(mib2.icmpintimeexcds);
263 }
else if (type == ICMP_PP) {
264 MIB2_STATS_INC(mib2.icmpinparmprobs);
265 }
else if (type == ICMP_SQ) {
266 MIB2_STATS_INC(mib2.icmpinsrcquenchs);
267 }
else if (type == ICMP_RD) {
268 MIB2_STATS_INC(mib2.icmpinredirects);
269 }
else if (type == ICMP_TS) {
270 MIB2_STATS_INC(mib2.icmpintimestamps);
271 }
else if (type == ICMP_TSR) {
272 MIB2_STATS_INC(mib2.icmpintimestampreps);
273 }
else if (type == ICMP_AM) {
274 MIB2_STATS_INC(mib2.icmpinaddrmasks);
275 }
else if (type == ICMP_AMR) {
276 MIB2_STATS_INC(mib2.icmpinaddrmaskreps);
278 LWIP_DEBUGF(
ICMP_DEBUG, (
"icmp_input: ICMP type %"S16_F
" code %"S16_F
" not supported.\n",
279 (s16_t)type, (s16_t)code));
280 ICMP_STATS_INC(icmp.proterr);
281 ICMP_STATS_INC(icmp.drop);
287 ICMP_STATS_INC(icmp.lenerr);
288 MIB2_STATS_INC(mib2.icmpinerrors);
290#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN || !LWIP_MULTICAST_PING || !LWIP_BROADCAST_PING
293 ICMP_STATS_INC(icmp.err);
294 MIB2_STATS_INC(mib2.icmpinerrors);
311 MIB2_STATS_INC(mib2.icmpoutdestunreachs);
312 icmp_send_response(p, ICMP_DUR, t);
315#if IP_FORWARD || IP_REASSEMBLY
326 MIB2_STATS_INC(mib2.icmpouttimeexcds);
327 icmp_send_response(p, ICMP_TE, t);
341icmp_send_response(
struct pbuf *p, u8_t type, u8_t code)
348 u16_t response_pkt_len;
351 MIB2_STATS_INC(mib2.icmpoutmsgs);
354 response_pkt_len = IP_HLEN + ICMP_DEST_UNREACH_DATASIZE;
355 if (p->tot_len < response_pkt_len) {
356 response_pkt_len = p->tot_len;
362 LWIP_DEBUGF(
ICMP_DEBUG, (
"icmp_send_response: failed to allocate pbuf for ICMP packet.\n"));
363 MIB2_STATS_INC(mib2.icmpouterrors);
366 LWIP_ASSERT(
"check that first pbuf can hold icmp message",
367 (q->len >= (
sizeof(
struct icmp_hdr) + response_pkt_len)));
369 iphdr = (
struct ip_hdr *)p->payload;
370 LWIP_DEBUGF(
ICMP_DEBUG, (
"icmp_send_response: Sending ICMP type %02X for packet from ", type));
371 ip4_addr_debug_print_val(
ICMP_DEBUG, iphdr->src);
373 ip4_addr_debug_print_val(
ICMP_DEBUG, iphdr->dest);
376 icmphdr = (
struct icmp_hdr *)q->payload;
377 icmphdr->type = type;
378 icmphdr->code = code;
385#ifdef LWIP_HOOK_IP4_ROUTE_SRC
389 netif = ip4_route_src(&iphdr_dst, &iphdr_src);
392 netif = ip4_route(&iphdr_src);
398 IF__NETIF_CHECKSUM_ENABLED(
netif, NETIF_CHECKSUM_GEN_ICMP) {
399 icmphdr->chksum = inet_chksum(icmphdr, q->len);
402 ICMP_STATS_INC(icmp.xmit);
403 ip4_output_if(q, NULL, &iphdr_src,
ICMP_TTL, 0, IP_PROTO_ICMP,
netif);
#define ip4_addr_copy(dest, src)
#define LWIP_UNUSED_ARG(x)
#define LWIP_DBG_LEVEL_SERIOUS
#define MEMCPY(dst, src, len)
#define PBUF_LINK_ENCAPSULATION_HLEN
u8 pbuf_free(struct pbuf *p)
err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
err_t pbuf_copy_partial_pbuf(struct pbuf *p_to, const struct pbuf *p_from, u16_t copy_len, u16_t offset)
u16_t inet_chksum_pbuf(struct pbuf *p)
#define ip_current_netif()
u8_t pbuf_add_header(struct pbuf *p, size_t header_size_increment)
u8_t pbuf_remove_header(struct pbuf *p, size_t header_size)
struct ip4_addr ip4_addr_t