68#ifndef IP_REASS_CHECK_OVERLAP
69#define IP_REASS_CHECK_OVERLAP 1
76#ifndef IP_REASS_FREE_OLDEST
77#define IP_REASS_FREE_OLDEST 1
80#define IP_REASS_FLAG_LASTFRAG 0x01
82#define IP_REASS_VALIDATE_TELEGRAM_FINISHED 1
83#define IP_REASS_VALIDATE_PBUF_QUEUED 0
84#define IP_REASS_VALIDATE_PBUF_DROPPED -1
94#ifdef PACK_STRUCT_USE_INCLUDES
98struct ip_reass_helper {
104#ifdef PACK_STRUCT_USE_INCLUDES
108#define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \
109 (ip4_addr_eq(&(iphdrA)->src, &(iphdrB)->src) && \
110 ip4_addr_eq(&(iphdrA)->dest, &(iphdrB)->dest) && \
111 IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0
114static struct ip_reassdata *reassdatagrams;
115static u16_t ip_reass_pbufcount;
118static void ip_reass_dequeue_datagram(
struct ip_reassdata *ipr,
struct ip_reassdata *prev);
119static int ip_reass_free_complete_datagram(
struct ip_reassdata *ipr,
struct ip_reassdata *prev);
130 struct ip_reassdata *
r, *prev =
NULL;
143 struct ip_reassdata *tmp;
149 ip_reass_free_complete_datagram(tmp, prev);
164ip_reass_free_complete_datagram(
struct ip_reassdata *ipr,
struct ip_reassdata *prev)
166 u16_t pbufs_freed = 0;
169 struct ip_reass_helper *iprh;
173 LWIP_ASSERT(
"prev->next == ipr", prev->next == ipr);
178 iprh = (
struct ip_reass_helper *)ipr->p->payload;
179 if (iprh->start == 0) {
183 ipr->p = iprh->next_pbuf;
188 LWIP_ASSERT(
"pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
189 pbufs_freed = (
u16_t)(pbufs_freed + clen);
199 iprh = (
struct ip_reass_helper *)
p->payload;
204 LWIP_ASSERT(
"pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
205 pbufs_freed = (
u16_t)(pbufs_freed + clen);
209 ip_reass_dequeue_datagram(ipr, prev);
210 LWIP_ASSERT(
"ip_reass_pbufcount >= pbufs_freed", ip_reass_pbufcount >= pbufs_freed);
211 ip_reass_pbufcount = (
u16_t)(ip_reass_pbufcount - pbufs_freed);
216#if IP_REASS_FREE_OLDEST
227ip_reass_remove_oldest_datagram(
struct ip_hdr *fraghdr,
int pbufs_needed)
232 struct ip_reassdata *
r, *oldest, *prev, *oldest_prev;
233 int pbufs_freed = 0, pbufs_freed_current;
245 if (!IP_ADDRESSES_AND_ID_MATCH(&
r->iphdr, fraghdr)) {
248 if (oldest ==
NULL) {
251 }
else if (
r->timer <= oldest->timer) {
257 if (
r->next !=
NULL) {
262 if (oldest !=
NULL) {
263 pbufs_freed_current = ip_reass_free_complete_datagram(oldest, oldest_prev);
264 pbufs_freed += pbufs_freed_current;
266 }
while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1));
277static struct ip_reassdata *
278ip_reass_enqueue_new_datagram(
struct ip_hdr *fraghdr,
int clen)
280 struct ip_reassdata *ipr;
281#if ! IP_REASS_FREE_OLDEST
286 ipr = (
struct ip_reassdata *)
memp_malloc(MEMP_REASSDATA);
288#if IP_REASS_FREE_OLDEST
289 if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) {
290 ipr = (
struct ip_reassdata *)
memp_malloc(MEMP_REASSDATA);
300 memset(ipr, 0,
sizeof(
struct ip_reassdata));
304 ipr->
next = reassdatagrams;
305 reassdatagrams = ipr;
317ip_reass_dequeue_datagram(
struct ip_reassdata *ipr,
struct ip_reassdata *prev)
320 if (reassdatagrams == ipr) {
322 reassdatagrams = ipr->next;
326 prev->next = ipr->next;
344ip_reass_chain_frag_into_datagram_and_validate(
struct ip_reassdata *ipr,
struct pbuf *new_p,
int is_last)
346 struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev =
NULL;
359 return IP_REASS_VALIDATE_PBUF_DROPPED;
367 LWIP_ASSERT(
"sizeof(struct ip_reass_helper) <= IP_HLEN",
368 sizeof(
struct ip_reass_helper) <=
IP_HLEN);
369 iprh = (
struct ip_reass_helper *)new_p->
payload;
370 iprh->next_pbuf =
NULL;
375 return IP_REASS_VALIDATE_PBUF_DROPPED;
380 for (
q = ipr->p;
q !=
NULL;) {
381 iprh_tmp = (
struct ip_reass_helper *)
q->payload;
382 if (iprh->start < iprh_tmp->start) {
385 if (iprh_prev !=
NULL) {
387#if IP_REASS_CHECK_OVERLAP
388 if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) {
390 return IP_REASS_VALIDATE_PBUF_DROPPED;
393 iprh_prev->next_pbuf = new_p;
394 if (iprh_prev->end != iprh->start) {
400#if IP_REASS_CHECK_OVERLAP
401 if (iprh->end > iprh_tmp->start) {
403 return IP_REASS_VALIDATE_PBUF_DROPPED;
410 }
else if (iprh->start == iprh_tmp->start) {
412 return IP_REASS_VALIDATE_PBUF_DROPPED;
413#if IP_REASS_CHECK_OVERLAP
414 }
else if (iprh->start < iprh_tmp->end) {
416 return IP_REASS_VALIDATE_PBUF_DROPPED;
420 if (iprh_prev !=
NULL) {
421 if (iprh_prev->end != iprh_tmp->start) {
428 q = iprh_tmp->next_pbuf;
429 iprh_prev = iprh_tmp;
434 if (iprh_prev !=
NULL) {
437#if IP_REASS_CHECK_OVERLAP
438 LWIP_ASSERT(
"check fragments don't overlap", iprh_prev->end <= iprh->start);
440 iprh_prev->next_pbuf = new_p;
441 if (iprh_prev->end != iprh->start) {
445#if IP_REASS_CHECK_OVERLAP
446 LWIP_ASSERT(
"no previous fragment, this must be the first fragment!",
456 if (is_last || ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0)) {
461 if ((ipr->p ==
NULL) || (((
struct ip_reass_helper *)ipr->p->payload)->start != 0)) {
468 iprh = (
struct ip_reass_helper *)
q->payload;
469 if (iprh_prev->end != iprh->start) {
481 ((
struct ip_reass_helper *)ipr->p->payload) != iprh);
483 iprh->next_pbuf ==
NULL);
490 return valid ? IP_REASS_VALIDATE_TELEGRAM_FINISHED : IP_REASS_VALIDATE_PBUF_QUEUED;
493 return IP_REASS_VALIDATE_PBUF_QUEUED;
503ip4_reass(
struct pbuf *
p)
507 struct ip_reassdata *ipr;
508 struct ip_reass_helper *iprh;
517 fraghdr = (
struct ip_hdr *)
p->payload;
537#if IP_REASS_FREE_OLDEST
538 if (!ip_reass_remove_oldest_datagram(fraghdr, clen) ||
554 for (ipr = reassdatagrams; ipr !=
NULL; ipr = ipr->
next) {
558 if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) {
568 ipr = ip_reass_enqueue_new_datagram(fraghdr, clen);
591 if ((datagram_len <
offset) || (datagram_len > (0xFFFF -
IP_HLEN))) {
598 valid = ip_reass_chain_frag_into_datagram_and_validate(ipr,
p, is_last);
599 if (
valid == IP_REASS_VALIDATE_PBUF_DROPPED) {
607 ip_reass_pbufcount = (
u16_t)(ip_reass_pbufcount + clen);
610 ipr->datagram_len = datagram_len;
611 ipr->flags |= IP_REASS_FLAG_LASTFRAG;
613 (
"ip4_reass: last fragment seen, total len %"S16_F"\n",
617 if (
valid == IP_REASS_VALIDATE_TELEGRAM_FINISHED) {
618 struct ip_reassdata *ipr_prev;
624 r = ((
struct ip_reass_helper *)ipr->p->payload)->next_pbuf;
627 fraghdr = (
struct ip_hdr *)(ipr->p->payload);
643 iprh = (
struct ip_reass_helper *)
r->payload;
652 if (ipr == reassdatagrams) {
655 for (ipr_prev = reassdatagrams; ipr_prev !=
NULL; ipr_prev = ipr_prev->
next) {
656 if (ipr_prev->next == ipr) {
663 ip_reass_dequeue_datagram(ipr, ipr_prev);
667 LWIP_ASSERT(
"ip_reass_pbufcount >= clen", ip_reass_pbufcount >= clen);
668 ip_reass_pbufcount = (
u16_t)(ip_reass_pbufcount - clen);
681 if (ipr->p ==
NULL) {
683 LWIP_ASSERT(
"not firstalthough just enqueued", ipr == reassdatagrams);
684 ip_reass_dequeue_datagram(ipr,
NULL);
696#if !LWIP_NETIF_TX_SINGLE_PBUF
698static struct pbuf_custom_ref *
699ip_frag_alloc_pbuf_custom_ref(
void)
701 return (
struct pbuf_custom_ref *)
memp_malloc(MEMP_FRAG_PBUF);
706ip_frag_free_pbuf_custom_ref(
struct pbuf_custom_ref *
p)
715ipfrag_free_pbuf_custom(
struct pbuf *
p)
717 struct pbuf_custom_ref *pcr = (
struct pbuf_custom_ref *)
p;
720 if (pcr->original !=
NULL) {
723 ip_frag_free_pbuf_custom_ref(pcr);
743#if !LWIP_NETIF_TX_SINGLE_PBUF
744 struct pbuf *newpbuf;
745 u16_t newpbuflen = 0;
748 struct ip_hdr *original_iphdr;
758 original_iphdr = (
struct ip_hdr *)
p->payload;
759 iphdr = original_iphdr;
770 mf_set = tmp &
IP_MF;
778#if LWIP_NETIF_TX_SINGLE_PBUF
780 if (rambuf ==
NULL) {
801 if (rambuf ==
NULL) {
809 left_to_copy = fragsize;
810 while (left_to_copy) {
811 struct pbuf_custom_ref *pcr;
814 newpbuflen =
LWIP_MIN(left_to_copy, plen);
821 pcr = ip_frag_alloc_pbuf_custom_ref();
828 (
u8_t *)
p->payload + poff, newpbuflen);
829 if (newpbuf ==
NULL) {
830 ip_frag_free_pbuf_custom_ref(pcr);
836 pcr->pc.custom_free_function = ipfrag_free_pbuf_custom;
842 left_to_copy = (
u16_t)(left_to_copy - newpbuflen);
848 poff = (
u16_t)(poff + newpbuflen);
856 if (!
last || mf_set) {
884 ofo = (
u16_t)(ofo + nfb);
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
#define PACK_STRUCT_STRUCT
#define LWIP_DEBUGF(debug, message)
#define LWIP_ERROR(message, expression, handler)
#define LWIP_ASSERT(message, assertion)
#define ip_current_input_netif()
GLdouble GLdouble GLdouble r
GLdouble GLdouble GLdouble GLdouble q
#define LWIP_UNUSED_ARG(x)
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_FIELD(x)
#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
u16_t inet_chksum(const void *dataptr, u16_t len)
void * memp_malloc(memp_t type)
void memp_free(memp_t type, void *mem)
#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag)
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)
#define IPH_LEN_SET(hdr, len)
#define IPH_HL_BYTES(hdr)
#define IPH_OFFSET_BYTES(hdr)
#define IPH_OFFSET_SET(hdr, off)
#define IPH_CHKSUM_SET(hdr, chksum)
#define MIB2_STATS_INC(x)
#define IPFRAG_STATS_INC(x)