|
57 | 57 |
|
58 | 58 | #include <string.h>
|
59 | 59 |
|
60 |
| -#if LWIP_ICMP6_DATASIZE == 0 |
| 60 | +#if !LWIP_ICMP6_DATASIZE || (LWIP_ICMP6_DATASIZE > (IP6_MIN_MTU_LENGTH - IP6_HLEN - ICMP6_HLEN)) |
61 | 61 | #undef LWIP_ICMP6_DATASIZE
|
62 |
| -#define LWIP_ICMP6_DATASIZE 8 |
| 62 | +#define LWIP_ICMP6_DATASIZE (IP6_MIN_MTU_LENGTH - IP6_HLEN - ICMP6_HLEN) |
63 | 63 | #endif
|
64 | 64 |
|
65 | 65 | /* Forward declarations */
|
@@ -387,26 +387,35 @@ icmp6_send_response_with_addrs_and_netif(struct pbuf *p, u8_t code, u32_t data,
|
387 | 387 | {
|
388 | 388 | struct pbuf *q;
|
389 | 389 | struct icmp6_hdr *icmp6hdr;
|
| 390 | + u16_t datalen = LWIP_MIN(p->tot_len, LWIP_ICMP6_DATASIZE); |
| 391 | + u16_t offset; |
390 | 392 |
|
391 |
| - /* ICMPv6 header + IPv6 header + data */ |
392 |
| - q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, |
| 393 | + /* ICMPv6 header + datalen (as much of the offending packet as possible) */ |
| 394 | + q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + datalen, |
393 | 395 | PBUF_RAM);
|
394 | 396 | if (q == NULL) {
|
395 | 397 | LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n"));
|
396 | 398 | ICMP6_STATS_INC(icmp6.memerr);
|
397 | 399 | return;
|
398 | 400 | }
|
399 |
| - LWIP_ASSERT("check that first pbuf can hold icmp 6message", |
400 |
| - (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); |
| 401 | + LWIP_ASSERT("check that first pbuf can hold icmp6 header", |
| 402 | + (q->len >= (sizeof(struct icmp6_hdr)))); |
401 | 403 |
|
402 | 404 | icmp6hdr = (struct icmp6_hdr *)q->payload;
|
403 | 405 | icmp6hdr->type = type;
|
404 | 406 | icmp6hdr->code = code;
|
405 | 407 | icmp6hdr->data = lwip_htonl(data);
|
406 | 408 |
|
407 |
| - /* copy fields from original packet */ |
408 |
| - SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload, |
409 |
| - IP6_HLEN + LWIP_ICMP6_DATASIZE); |
| 409 | + /* copy fields from original packet (which may be a chain of pbufs) */ |
| 410 | + offset = sizeof(struct icmp6_hdr); |
| 411 | + while (p && datalen) { |
| 412 | + u16_t len = LWIP_MIN(datalen, p->len); |
| 413 | + err_t res = pbuf_take_at(q, p->payload, len, offset); |
| 414 | + if (res != ERR_OK) break; |
| 415 | + datalen -= len; |
| 416 | + offset += len; |
| 417 | + p = p->next; |
| 418 | + } |
410 | 419 |
|
411 | 420 | /* calculate checksum */
|
412 | 421 | icmp6hdr->chksum = 0;
|
|
0 commit comments