mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2025-01-30 12:32:37 +00:00
Shrinked ICMP code, added option to NOT check icoming ECHO pbuf for size (just use it): LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
This commit is contained in:
parent
c752e5731c
commit
105d72a3c2
@ -19,6 +19,10 @@ HISTORY
|
|||||||
|
|
||||||
++ New features:
|
++ New features:
|
||||||
|
|
||||||
|
2009-05-09 Simon Goldschmidt
|
||||||
|
* icmp.h, icmp.c: Shrinked ICMP code, added option to NOT check icoming
|
||||||
|
ECHO pbuf for size (just use it): LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
||||||
|
|
||||||
2009-05-05 Simon Goldschmidt, Jakob Stoklund Olesen
|
2009-05-05 Simon Goldschmidt, Jakob Stoklund Olesen
|
||||||
* ip.h, ip.c: Added ip_current_netif() & ip_current_header() to receive
|
* ip.h, ip.c: Added ip_current_netif() & ip_current_header() to receive
|
||||||
extended info about the currently received packet.
|
extended info about the currently received packet.
|
||||||
|
@ -53,9 +53,18 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
/** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be
|
||||||
|
* used to modify and send a response packet (and to 1 if this is not the case,
|
||||||
|
* e.g. when link header is stripped of when receiving) */
|
||||||
|
#ifndef LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
||||||
|
#define LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN 1
|
||||||
|
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
|
||||||
|
|
||||||
/* The amount of data from the original packet to return in a dest-unreachable */
|
/* The amount of data from the original packet to return in a dest-unreachable */
|
||||||
#define ICMP_DEST_UNREACH_DATASIZE 8
|
#define ICMP_DEST_UNREACH_DATASIZE 8
|
||||||
|
|
||||||
|
static void icmp_send_response(struct pbuf *p, u8_t type, u8_t code);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processes ICMP input packets, called from ip_input().
|
* Processes ICMP input packets, called from ip_input().
|
||||||
*
|
*
|
||||||
@ -130,6 +139,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
snmp_inc_icmpinerrors();
|
snmp_inc_icmpinerrors();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
||||||
if (pbuf_header(p, (PBUF_IP_HLEN + PBUF_LINK_HLEN))) {
|
if (pbuf_header(p, (PBUF_IP_HLEN + PBUF_LINK_HLEN))) {
|
||||||
/* p is not big enough to contain link headers
|
/* p is not big enough to contain link headers
|
||||||
* allocate a new one and copy p into it
|
* allocate a new one and copy p into it
|
||||||
@ -170,6 +180,7 @@ icmp_input(struct pbuf *p, struct netif *inp)
|
|||||||
goto memerr;
|
goto memerr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
|
||||||
/* At this point, all checks are OK. */
|
/* At this point, all checks are OK. */
|
||||||
/* We generate an answer by switching the dest and src ip addresses,
|
/* We generate an answer by switching the dest and src ip addresses,
|
||||||
* setting the icmp type to ECHO_RESPONSE and updating the checksum. */
|
* setting the icmp type to ECHO_RESPONSE and updating the checksum. */
|
||||||
@ -222,11 +233,13 @@ lenerr:
|
|||||||
ICMP_STATS_INC(icmp.lenerr);
|
ICMP_STATS_INC(icmp.lenerr);
|
||||||
snmp_inc_icmpinerrors();
|
snmp_inc_icmpinerrors();
|
||||||
return;
|
return;
|
||||||
|
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
|
||||||
memerr:
|
memerr:
|
||||||
pbuf_free(p);
|
pbuf_free(p);
|
||||||
ICMP_STATS_INC(icmp.err);
|
ICMP_STATS_INC(icmp.err);
|
||||||
snmp_inc_icmpinerrors();
|
snmp_inc_icmpinerrors();
|
||||||
return;
|
return;
|
||||||
|
#endif /* LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -241,40 +254,7 @@ memerr:
|
|||||||
void
|
void
|
||||||
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
||||||
{
|
{
|
||||||
struct pbuf *q;
|
icmp_send_response(p, ICMP_DUR, t);
|
||||||
struct ip_hdr *iphdr;
|
|
||||||
struct icmp_dur_hdr *idur;
|
|
||||||
|
|
||||||
/* ICMP header + IP header + 8 bytes of data */
|
|
||||||
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_dur_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
|
|
||||||
PBUF_RAM);
|
|
||||||
if (q == NULL) {
|
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_dest_unreach: failed to allocate pbuf for ICMP packet.\n"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LWIP_ASSERT("check that first pbuf can hold icmp message",
|
|
||||||
(q->len >= (sizeof(struct icmp_dur_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
|
|
||||||
|
|
||||||
iphdr = p->payload;
|
|
||||||
|
|
||||||
idur = q->payload;
|
|
||||||
ICMPH_TYPE_SET(idur, ICMP_DUR);
|
|
||||||
ICMPH_CODE_SET(idur, t);
|
|
||||||
|
|
||||||
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_dur_hdr), p->payload,
|
|
||||||
IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);
|
|
||||||
|
|
||||||
/* calculate checksum */
|
|
||||||
idur->chksum = 0;
|
|
||||||
idur->chksum = inet_chksum(idur, q->len);
|
|
||||||
ICMP_STATS_INC(icmp.xmit);
|
|
||||||
/* increase number of messages attempted to send */
|
|
||||||
snmp_inc_icmpoutmsgs();
|
|
||||||
/* increase number of destination unreachable messages attempted to send */
|
|
||||||
snmp_inc_icmpoutdestunreachs();
|
|
||||||
|
|
||||||
ip_output(q, NULL, &(iphdr->src), ICMP_TTL, 0, IP_PROTO_ICMP);
|
|
||||||
pbuf_free(q);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if IP_FORWARD || IP_REASSEMBLY
|
#if IP_FORWARD || IP_REASSEMBLY
|
||||||
@ -287,20 +267,37 @@ icmp_dest_unreach(struct pbuf *p, enum icmp_dur_type t)
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
||||||
|
{
|
||||||
|
icmp_send_response(p, ICMP_TE, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* IP_FORWARD || IP_REASSEMBLY */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an icmp packet in response to an incoming packet.
|
||||||
|
*
|
||||||
|
* @param p the input packet for which the 'unreachable' should be sent,
|
||||||
|
* p->payload pointing to the IP header
|
||||||
|
* @param type Type of the ICMP header
|
||||||
|
* @param code Code of the ICMP header
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
|
||||||
{
|
{
|
||||||
struct pbuf *q;
|
struct pbuf *q;
|
||||||
struct ip_hdr *iphdr;
|
struct ip_hdr *iphdr;
|
||||||
struct icmp_te_hdr *tehdr;
|
/* we can use the echo header here */
|
||||||
|
struct icmp_echo_hdr *icmphdr;
|
||||||
|
|
||||||
/* ICMP header + IP header + 8 bytes of data */
|
/* ICMP header + IP header + 8 bytes of data */
|
||||||
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_dur_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
|
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
|
||||||
PBUF_RAM);
|
PBUF_RAM);
|
||||||
if (q == NULL) {
|
if (q == NULL) {
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n"));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMP packet.\n"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LWIP_ASSERT("check that first pbuf can hold icmp message",
|
LWIP_ASSERT("check that first pbuf can hold icmp message",
|
||||||
(q->len >= (sizeof(struct icmp_dur_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
|
(q->len >= (sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE)));
|
||||||
|
|
||||||
iphdr = p->payload;
|
iphdr = p->payload;
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
|
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded from "));
|
||||||
@ -309,17 +306,19 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
|||||||
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
|
ip_addr_debug_print(ICMP_DEBUG, &(iphdr->dest));
|
||||||
LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
|
LWIP_DEBUGF(ICMP_DEBUG, ("\n"));
|
||||||
|
|
||||||
tehdr = q->payload;
|
icmphdr = q->payload;
|
||||||
ICMPH_TYPE_SET(tehdr, ICMP_TE);
|
icmphdr->type = type;
|
||||||
ICMPH_CODE_SET(tehdr, t);
|
icmphdr->code = code;
|
||||||
|
icmphdr->id = 0;
|
||||||
|
icmphdr->seqno = 0;
|
||||||
|
|
||||||
/* copy fields from original packet */
|
/* copy fields from original packet */
|
||||||
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_dur_hdr), (u8_t *)p->payload,
|
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload,
|
||||||
IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);
|
IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);
|
||||||
|
|
||||||
/* calculate checksum */
|
/* calculate checksum */
|
||||||
tehdr->chksum = 0;
|
icmphdr->chksum = 0;
|
||||||
tehdr->chksum = inet_chksum(tehdr, q->len);
|
icmphdr->chksum = inet_chksum(icmphdr, q->len);
|
||||||
ICMP_STATS_INC(icmp.xmit);
|
ICMP_STATS_INC(icmp.xmit);
|
||||||
/* increase number of messages attempted to send */
|
/* increase number of messages attempted to send */
|
||||||
snmp_inc_icmpoutmsgs();
|
snmp_inc_icmpoutmsgs();
|
||||||
@ -329,6 +328,4 @@ icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t)
|
|||||||
pbuf_free(q);
|
pbuf_free(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* IP_FORWARD */
|
|
||||||
|
|
||||||
#endif /* LWIP_ICMP */
|
#endif /* LWIP_ICMP */
|
||||||
|
@ -78,39 +78,30 @@ void icmp_time_exceeded(struct pbuf *p, enum icmp_te_type t);
|
|||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
# include "arch/bpstruct.h"
|
# include "arch/bpstruct.h"
|
||||||
#endif
|
#endif
|
||||||
|
/** This is the standard ICMP header only that the u32_t data
|
||||||
|
* is splitted to two u16_t like ICMP echo needs it.
|
||||||
|
* This header is also used for other ICMP types that do not
|
||||||
|
* use the data part.
|
||||||
|
*/
|
||||||
PACK_STRUCT_BEGIN
|
PACK_STRUCT_BEGIN
|
||||||
struct icmp_echo_hdr {
|
struct icmp_echo_hdr {
|
||||||
PACK_STRUCT_FIELD(u16_t _type_code);
|
PACK_STRUCT_FIELD(u8_t type);
|
||||||
|
PACK_STRUCT_FIELD(u8_t code);
|
||||||
PACK_STRUCT_FIELD(u16_t chksum);
|
PACK_STRUCT_FIELD(u16_t chksum);
|
||||||
PACK_STRUCT_FIELD(u16_t id);
|
PACK_STRUCT_FIELD(u16_t id);
|
||||||
PACK_STRUCT_FIELD(u16_t seqno);
|
PACK_STRUCT_FIELD(u16_t seqno);
|
||||||
} PACK_STRUCT_STRUCT;
|
} PACK_STRUCT_STRUCT;
|
||||||
PACK_STRUCT_END
|
PACK_STRUCT_END
|
||||||
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct icmp_dur_hdr {
|
|
||||||
PACK_STRUCT_FIELD(u16_t _type_code);
|
|
||||||
PACK_STRUCT_FIELD(u16_t chksum);
|
|
||||||
PACK_STRUCT_FIELD(u32_t unused);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
|
|
||||||
PACK_STRUCT_BEGIN
|
|
||||||
struct icmp_te_hdr {
|
|
||||||
PACK_STRUCT_FIELD(u16_t _type_code);
|
|
||||||
PACK_STRUCT_FIELD(u16_t chksum);
|
|
||||||
PACK_STRUCT_FIELD(u32_t unused);
|
|
||||||
} PACK_STRUCT_STRUCT;
|
|
||||||
PACK_STRUCT_END
|
|
||||||
#ifdef PACK_STRUCT_USE_INCLUDES
|
#ifdef PACK_STRUCT_USE_INCLUDES
|
||||||
# include "arch/epstruct.h"
|
# include "arch/epstruct.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ICMPH_TYPE(hdr) (ntohs((hdr)->_type_code) >> 8)
|
#define ICMPH_TYPE(hdr) ((hdr)->type)
|
||||||
#define ICMPH_CODE(hdr) (ntohs((hdr)->_type_code) & 0xff)
|
#define ICMPH_CODE(hdr) ((hdr)->code)
|
||||||
|
|
||||||
#define ICMPH_TYPE_SET(hdr, type) ((hdr)->_type_code = htons(ICMPH_CODE(hdr) | ((type) << 8)))
|
/** Combines type and code to an u16_t */
|
||||||
#define ICMPH_CODE_SET(hdr, code) ((hdr)->_type_code = htons((code) | (ICMPH_TYPE(hdr) << 8)))
|
#define ICMPH_TYPE_SET(hdr, t) ((hdr)->type = (t))
|
||||||
|
#define ICMPH_CODE_SET(hdr, c) ((hdr)->code = (c))
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user