summaryrefslogtreecommitdiffstats
path: root/lwip/src/core/ipv6/icmp6.c
diff options
context:
space:
mode:
Diffstat (limited to 'lwip/src/core/ipv6/icmp6.c')
-rw-r--r--lwip/src/core/ipv6/icmp6.c27
1 files changed, 18 insertions, 9 deletions
diff --git a/lwip/src/core/ipv6/icmp6.c b/lwip/src/core/ipv6/icmp6.c
index 167738a..4fd1021 100644
--- a/lwip/src/core/ipv6/icmp6.c
+++ b/lwip/src/core/ipv6/icmp6.c
@@ -57,9 +57,9 @@
#include <string.h>
-#if LWIP_ICMP6_DATASIZE == 0
+#if !LWIP_ICMP6_DATASIZE || (LWIP_ICMP6_DATASIZE > (IP6_MIN_MTU_LENGTH - IP6_HLEN - ICMP6_HLEN))
#undef LWIP_ICMP6_DATASIZE
-#define LWIP_ICMP6_DATASIZE 8
+#define LWIP_ICMP6_DATASIZE (IP6_MIN_MTU_LENGTH - IP6_HLEN - ICMP6_HLEN)
#endif
/* Forward declarations */
@@ -387,26 +387,35 @@ icmp6_send_response_with_addrs_and_netif(struct pbuf *p, u8_t code, u32_t data,
{
struct pbuf *q;
struct icmp6_hdr *icmp6hdr;
+ u16_t datalen = LWIP_MIN(p->tot_len, LWIP_ICMP6_DATASIZE);
+ u16_t offset;
- /* ICMPv6 header + IPv6 header + data */
- q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE,
+ /* ICMPv6 header + datalen (as much of the offending packet as possible) */
+ q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + datalen,
PBUF_RAM);
if (q == NULL) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n"));
ICMP6_STATS_INC(icmp6.memerr);
return;
}
- LWIP_ASSERT("check that first pbuf can hold icmp 6message",
- (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE)));
+ LWIP_ASSERT("check that first pbuf can hold icmp6 header",
+ (q->len >= (sizeof(struct icmp6_hdr))));
icmp6hdr = (struct icmp6_hdr *)q->payload;
icmp6hdr->type = type;
icmp6hdr->code = code;
icmp6hdr->data = lwip_htonl(data);
- /* copy fields from original packet */
- SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload,
- IP6_HLEN + LWIP_ICMP6_DATASIZE);
+ /* copy fields from original packet (which may be a chain of pbufs) */
+ offset = sizeof(struct icmp6_hdr);
+ while (p && datalen) {
+ u16_t len = LWIP_MIN(datalen, p->len);
+ err_t res = pbuf_take_at(q, p->payload, len, offset);
+ if (res != ERR_OK) break;
+ datalen -= len;
+ offset += len;
+ p = p->next;
+ }
/* calculate checksum */
icmp6hdr->chksum = 0;