55#if LWIP_IPV6 && LWIP_IPV6_REASS
61#ifndef IP_REASS_CHECK_OVERLAP
62#define IP_REASS_CHECK_OVERLAP 1
69#ifndef IP_REASS_FREE_OLDEST
70#define IP_REASS_FREE_OLDEST 1
73#if IPV6_FRAG_COPYHEADER
76#define IPV6_FRAG_REQROOM ((s16_t)(sizeof(struct ip6_reass_helper) - IP6_FRAG_HLEN))
79#define IP_REASS_FLAG_LASTFRAG 0x01
88#ifdef PACK_STRUCT_USE_INCLUDES
92struct ip6_reass_helper {
98#ifdef PACK_STRUCT_USE_INCLUDES
103static struct ip6_reassdata *reassdatagrams;
104static u16_t ip6_reass_pbufcount;
107static void ip6_reass_free_complete_datagram(
struct ip6_reassdata *ipr);
108#if IP_REASS_FREE_OLDEST
109static void ip6_reass_remove_oldest_datagram(
struct ip6_reassdata *ipr,
int pbufs_needed);
115 struct ip6_reassdata *
r, *tmp;
117#if !IPV6_FRAG_COPYHEADER
118 LWIP_ASSERT(
"sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1",
135 ip6_reass_free_complete_datagram(tmp);
148ip6_reass_free_complete_datagram(
struct ip6_reassdata *ipr)
150 struct ip6_reassdata *prev;
151 u16_t pbufs_freed = 0;
154 struct ip6_reass_helper *iprh;
157 iprh = (
struct ip6_reass_helper *)ipr->p->payload;
158 if (iprh->start == 0) {
162 ipr->p = iprh->next_pbuf;
165 MEMCPY(
p->payload, ipr->orig_hdr,
sizeof(iprh));
169 LWIP_ASSERT(
"ip6_reass_free: moving p->payload to ip6 header failed", 0);
174 ip6_addr_t src_addr, dest_addr;
175 ip6_addr_copy_from_packed(src_addr, IPV6_FRAG_SRC(ipr));
176 ip6_addr_set_zone(&src_addr, ipr->src_zone);
177 ip6_addr_copy_from_packed(dest_addr, IPV6_FRAG_DEST(ipr));
178 ip6_addr_set_zone(&dest_addr, ipr->dest_zone);
180 icmp6_time_exceeded_with_addrs(
p,
ICMP6_TE_FRAG, &src_addr, &dest_addr);
183 LWIP_ASSERT(
"pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
184 pbufs_freed = (
u16_t)(pbufs_freed + clen);
194 iprh = (
struct ip6_reass_helper *)
p->payload;
199 LWIP_ASSERT(
"pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
200 pbufs_freed = (
u16_t)(pbufs_freed + clen);
205 if (ipr == reassdatagrams) {
206 reassdatagrams = ipr->next;
208 prev = reassdatagrams;
209 while (prev !=
NULL) {
210 if (prev->next == ipr) {
216 prev->next = ipr->next;
222 LWIP_ASSERT(
"ip_reass_pbufcount >= clen", ip6_reass_pbufcount >= pbufs_freed);
223 ip6_reass_pbufcount = (
u16_t)(ip6_reass_pbufcount - pbufs_freed);
226#if IP_REASS_FREE_OLDEST
236ip6_reass_remove_oldest_datagram(
struct ip6_reassdata *ipr,
int pbufs_needed)
238 struct ip6_reassdata *
r, *oldest;
243 r = oldest = reassdatagrams;
246 if (
r->timer <= oldest->timer) {
257 if (oldest !=
NULL) {
258 ip6_reass_free_complete_datagram(oldest);
272ip6_reass(
struct pbuf *
p)
274 struct ip6_reassdata *ipr, *ipr_prev;
275 struct ip6_reass_helper *iprh, *iprh_tmp, *iprh_prev=
NULL;
281 struct pbuf *
q, *next_pbuf;
286 LWIP_ASSERT(
"IPv6 fragment header does not fit in first pbuf",
299 hdrdiff = (
u8_t*)
p->payload - (
const u8_t*)ip6_current_header();
300 LWIP_ASSERT(
"not a valid pbuf (ip6_input check missing?)", hdrdiff <= 0xFFFF);
318 for (ipr = reassdatagrams, ipr_prev =
NULL; ipr !=
NULL; ipr = ipr->
next) {
322 if ((frag_hdr->_identification == ipr->identification) &&
323 ip6_addr_packed_eq(ip6_current_src_addr(), &(IPV6_FRAG_SRC(ipr)), ipr->src_zone) &&
324 ip6_addr_packed_eq(ip6_current_dest_addr(), &(IPV6_FRAG_DEST(ipr)), ipr->dest_zone)) {
333 ipr = (
struct ip6_reassdata *)
memp_malloc(MEMP_IP6_REASSDATA);
335#if IP_REASS_FREE_OLDEST
337 ip6_reass_remove_oldest_datagram(ipr, clen);
338 ipr = (
struct ip6_reassdata *)
memp_malloc(MEMP_IP6_REASSDATA);
341 for (ipr_prev = reassdatagrams; ipr_prev !=
NULL; ipr_prev = ipr_prev->
next) {
342 if (ipr_prev->next == ipr) {
354 memset(ipr, 0,
sizeof(
struct ip6_reassdata));
358 ipr->
next = reassdatagrams;
359 reassdatagrams = ipr;
365 ipr->iphdr =
ip_data.current_ip6_header;
366#if IPV6_FRAG_COPYHEADER
367 MEMCPY(&ipr->src, &ip6_current_header()->
src,
sizeof(ipr->src));
368 MEMCPY(&ipr->dest, &ip6_current_header()->
dest,
sizeof(ipr->dest));
377 ipr->src_zone = ip6_addr_zone(ip6_current_src_addr());
378 ipr->dest_zone = ip6_addr_zone(ip6_current_dest_addr());
381 ipr->identification = frag_hdr->_identification;
384 ipr->nexth = frag_hdr->_nexth;
389#if IP_REASS_FREE_OLDEST
390 ip6_reass_remove_oldest_datagram(ipr, clen);
393 for (ipr_prev = reassdatagrams; ipr_prev !=
NULL; ipr_prev = ipr_prev->
next) {
394 if (ipr_prev->next == ipr) {
409#if IPV6_FRAG_COPYHEADER
410 if (IPV6_FRAG_REQROOM > 0) {
415 LWIP_ASSERT(
"no room for struct ip6_reass_helper", hdrerr == 0);
418 LWIP_ASSERT(
"sizeof(struct ip6_reass_helper) <= IP6_FRAG_HLEN, set IPV6_FRAG_COPYHEADER to 1",
426 iprh = (
struct ip6_reass_helper *)
p->payload;
433 for (
q = ipr->p;
q !=
NULL;) {
434 iprh_tmp = (
struct ip6_reass_helper*)
q->payload;
436#if IP_REASS_CHECK_OVERLAP
437 if (
end > iprh_tmp->start) {
442 if (iprh_prev !=
NULL) {
443 if (start < iprh_prev->
end) {
452 if (iprh_prev !=
NULL) {
454 iprh_prev->next_pbuf =
p;
460 }
else if (
start == iprh_tmp->start) {
463#if IP_REASS_CHECK_OVERLAP
464 }
else if (start < iprh_tmp->
end) {
471 if (iprh_prev !=
NULL) {
472 if (iprh_prev->end != iprh_tmp->start) {
479 q = iprh_tmp->next_pbuf;
480 iprh_prev = iprh_tmp;
485 if (iprh_prev !=
NULL) {
488#if IP_REASS_CHECK_OVERLAP
491 iprh_prev->next_pbuf =
p;
492 if (iprh_prev->end !=
start) {
496#if IP_REASS_CHECK_OVERLAP
497 LWIP_ASSERT(
"no previous fragment, this must be the first fragment!",
507 ip6_reass_pbufcount = (
u16_t)(ip6_reass_pbufcount + clen);
512 ipr->iphdr =
ip_data.current_ip6_header;
515 MEMCPY(ipr->orig_hdr,
p->payload,
sizeof(*iprh));
521 iprh->next_pbuf = next_pbuf;
527 ipr->datagram_len = iprh->end;
531 iprh_tmp = (
struct ip6_reass_helper*)ipr->p->payload;
532 if (iprh_tmp->start != 0) {
535 if (ipr->datagram_len == 0) {
543 iprh = (
struct ip6_reass_helper*)
q->payload;
544 if (iprh_prev->end != iprh->start) {
557 iprh = (
struct ip6_reass_helper*) ipr->p->payload;
559 next_pbuf = iprh->next_pbuf;
560 if (next_pbuf !=
NULL) {
562 iprh_tmp = (
struct ip6_reass_helper*)next_pbuf->
payload;
566#if IPV6_FRAG_COPYHEADER
567 if (IPV6_FRAG_REQROOM > 0) {
571 LWIP_ASSERT(
"no room for struct ip6_reass_helper", hdrerr == 0);
586#if IPV6_FRAG_COPYHEADER
587 if (IPV6_FRAG_REQROOM > 0) {
592 MEMCPY(
p->payload, ipr->orig_hdr, IPV6_FRAG_REQROOM);
596 LWIP_ASSERT(
"no room for struct ip6_reass_helper", hdrerr == 0);
610 (
size_t)((
u8_t*)
p->payload - (
u8_t*)ipr->iphdr));
617 ipr->datagram_len = (
u16_t)(ipr->datagram_len + ((
u8_t*)
p->payload - (
u8_t*)iphdr_ptr)
621 iphdr_ptr->_plen =
lwip_htons(ipr->datagram_len);
628 iphdr_ptr->_nexth = ipr->nexth;
638 if (reassdatagrams == ipr) {
640 reassdatagrams = ipr->next;
644 ipr_prev->next = ipr->next;
650 LWIP_ASSERT(
"ip6_reass_pbufcount >= clen", ip6_reass_pbufcount >= clen);
651 ip6_reass_pbufcount = (
u16_t)(ip6_reass_pbufcount - clen);
655 LWIP_ASSERT(
"ip6_reass: moving p->payload to ip6 header failed", 0);
674#if LWIP_IPV6 && LWIP_IPV6_FRAG
676#if !LWIP_NETIF_TX_SINGLE_PBUF
678static struct pbuf_custom_ref*
679ip6_frag_alloc_pbuf_custom_ref(
void)
681 return (
struct pbuf_custom_ref*)
memp_malloc(MEMP_FRAG_PBUF);
686ip6_frag_free_pbuf_custom_ref(
struct pbuf_custom_ref*
p)
695ip6_frag_free_pbuf_custom(
struct pbuf *
p)
697 struct pbuf_custom_ref *pcr = (
struct pbuf_custom_ref*)
p;
700 if (pcr->original !=
NULL) {
703 ip6_frag_free_pbuf_custom_ref(pcr);
722 struct ip6_hdr *original_ip6hdr;
726#if !LWIP_NETIF_TX_SINGLE_PBUF
727 struct pbuf *newpbuf;
728 u16_t newpbuflen = 0;
731 static u32_t identification;
735 u16_t fragment_offset = 0;
741 original_ip6hdr = (
struct ip6_hdr *)
p->payload;
753#if LWIP_NETIF_TX_SINGLE_PBUF
755 if (rambuf ==
NULL) {
779 if (rambuf ==
NULL) {
790 p->payload = (
u8_t *)
p->payload + poff;
791 p->len = (
u16_t)(
p->len - poff);
792 p->tot_len = (
u16_t)(
p->tot_len - poff);
795 while (left_to_copy) {
796 struct pbuf_custom_ref *pcr;
797 newpbuflen = (left_to_copy <
p->len) ? left_to_copy :
p->len;
803 pcr = ip6_frag_alloc_pbuf_custom_ref();
810 newpbuf = pbuf_alloced_custom(
PBUF_RAW, newpbuflen,
PBUF_REF, &pcr->pc,
p->payload, newpbuflen);
811 if (newpbuf ==
NULL) {
812 ip6_frag_free_pbuf_custom_ref(pcr);
819 pcr->pc.custom_free_function = ip6_frag_free_pbuf_custom;
825 left_to_copy = (
u16_t)(left_to_copy - newpbuflen);
834 frag_hdr->_nexth = original_ip6hdr->_nexth;
835 frag_hdr->reserved = 0;
837 frag_hdr->_identification =
lwip_htonl(identification);
857 fragment_offset = (
u16_t)(fragment_offset + cop);
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
__kernel_ptrdiff_t ptrdiff_t
#define PACK_STRUCT_STRUCT
#define LWIP_ASSERT(message, assertion)
struct ip_globals ip_data
GLdouble GLdouble GLdouble r
GLdouble GLdouble GLdouble GLdouble q
#define LWIP_UNUSED_ARG(x)
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_FIELD(x)
#define IPV6_REASS_MAXAGE
#define MEMMOVE(dst, src, len)
#define SMEMCPY(dst, src, len)
void pbuf_ref(struct pbuf *p)
void pbuf_cat(struct pbuf *h, struct pbuf *t)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
u8_t pbuf_free(struct pbuf *p)
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
#define IP_REASS_MAX_PBUFS
#define MEMCPY(DST, SRC, BYTES)
void * memp_malloc(memp_t type)
void memp_free(memp_t type, void *mem)
u8_t pbuf_add_header(struct pbuf *p, size_t header_size_increment)
u16_t pbuf_clen(const struct pbuf *p)
u8_t pbuf_remove_header(struct pbuf *p, size_t header_size_decrement)
u8_t pbuf_header_force(struct pbuf *p, s16_t header_size_increment)
#define IP6_NEXTH_FRAGMENT
#define IP6H_PLEN_SET(hdr, plen)
#define IP6_FRAG_OFFSET_MASK
#define IP6_FRAG_MORE_FLAG
#define IP6H_NEXTH_SET(hdr, nexth)
#define IP6_FRAG_STATS_INC(x)