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 90 #ifdef PACK_STRUCT_USE_INCLUDES 94 struct ip_reass_helper {
100 #ifdef PACK_STRUCT_USE_INCLUDES 104 #define IP_ADDRESSES_AND_ID_MATCH(iphdrA, iphdrB) \ 105 (ip4_addr_cmp(&(iphdrA)->src, &(iphdrB)->src) && \ 106 ip4_addr_cmp(&(iphdrA)->dest, &(iphdrB)->dest) && \ 107 IPH_ID(iphdrA) == IPH_ID(iphdrB)) ? 1 : 0 110 static struct ip_reassdata *reassdatagrams;
111 static u16_t ip_reass_pbufcount;
114 static void ip_reass_dequeue_datagram(
struct ip_reassdata *ipr,
struct ip_reassdata *prev);
115 static int ip_reass_free_complete_datagram(
struct ip_reassdata *ipr,
struct ip_reassdata *prev);
126 struct ip_reassdata *r, *prev =
NULL;
139 struct ip_reassdata *tmp;
145 ip_reass_free_complete_datagram(tmp, prev);
160 ip_reass_free_complete_datagram(
struct ip_reassdata *ipr,
struct ip_reassdata *prev)
162 u16_t pbufs_freed = 0;
165 struct ip_reass_helper *iprh;
169 LWIP_ASSERT(
"prev->next == ipr", prev->next == ipr);
174 iprh = (
struct ip_reass_helper *)ipr->p->payload;
175 if (iprh->start == 0) {
179 ipr->p = iprh->next_pbuf;
184 LWIP_ASSERT(
"pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
195 iprh = (
struct ip_reass_helper *)p->
payload;
200 LWIP_ASSERT(
"pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff);
205 ip_reass_dequeue_datagram(ipr, prev);
206 LWIP_ASSERT(
"ip_reass_pbufcount >= clen", ip_reass_pbufcount >= pbufs_freed);
207 ip_reass_pbufcount -= pbufs_freed;
212 #if IP_REASS_FREE_OLDEST 223 ip_reass_remove_oldest_datagram(
struct ip_hdr *fraghdr,
int pbufs_needed)
228 struct ip_reassdata *r, *oldest, *prev, *oldest_prev;
229 int pbufs_freed = 0, pbufs_freed_current;
241 if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) {
244 if (oldest ==
NULL) {
247 }
else if (r->timer <= oldest->timer) {
253 if (r->next !=
NULL) {
258 if (oldest !=
NULL) {
259 pbufs_freed_current = ip_reass_free_complete_datagram(oldest, oldest_prev);
260 pbufs_freed += pbufs_freed_current;
262 }
while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1));
273 static struct ip_reassdata*
274 ip_reass_enqueue_new_datagram(
struct ip_hdr *fraghdr,
int clen)
276 struct ip_reassdata* ipr;
277 #if ! IP_REASS_FREE_OLDEST 282 ipr = (
struct ip_reassdata *)
memp_malloc(MEMP_REASSDATA);
284 #if IP_REASS_FREE_OLDEST 285 if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) {
286 ipr = (
struct ip_reassdata *)
memp_malloc(MEMP_REASSDATA);
296 memset(ipr, 0,
sizeof(
struct ip_reassdata));
300 ipr->next = reassdatagrams;
301 reassdatagrams = ipr;
304 SMEMCPY(&(ipr->iphdr), fraghdr, IP_HLEN);
313 ip_reass_dequeue_datagram(
struct ip_reassdata *ipr,
struct ip_reassdata *prev)
316 if (reassdatagrams == ipr) {
318 reassdatagrams = ipr->next;
322 prev->next = ipr->next;
339 ip_reass_chain_frag_into_datagram_and_validate(
struct ip_reassdata *ipr,
struct pbuf *new_p)
341 struct ip_reass_helper *iprh, *iprh_tmp, *iprh_prev=
NULL;
344 struct ip_hdr *fraghdr;
348 fraghdr = (
struct ip_hdr*)new_p->
payload;
349 len =
ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
350 offset = (
ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8;
355 LWIP_ASSERT(
"sizeof(struct ip_reass_helper) <= IP_HLEN",
356 sizeof(
struct ip_reass_helper) <= IP_HLEN);
357 iprh = (
struct ip_reass_helper*)new_p->
payload;
358 iprh->next_pbuf =
NULL;
359 iprh->start = offset;
360 iprh->end = offset + len;
364 for (q = ipr->p; q !=
NULL;) {
365 iprh_tmp = (
struct ip_reass_helper*)q->
payload;
366 if (iprh->start < iprh_tmp->start) {
369 if (iprh_prev !=
NULL) {
371 #if IP_REASS_CHECK_OVERLAP 372 if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) {
377 iprh_prev->next_pbuf = new_p;
383 }
else if (iprh->start == iprh_tmp->start) {
386 #if IP_REASS_CHECK_OVERLAP 387 }
else if (iprh->start < iprh_tmp->end) {
393 if (iprh_prev !=
NULL) {
394 if (iprh_prev->end != iprh_tmp->start) {
401 q = iprh_tmp->next_pbuf;
402 iprh_prev = iprh_tmp;
407 if (iprh_prev !=
NULL) {
410 #if IP_REASS_CHECK_OVERLAP 411 LWIP_ASSERT(
"check fragments don't overlap", iprh_prev->end <= iprh->start);
413 iprh_prev->next_pbuf = new_p;
414 if (iprh_prev->end != iprh->start) {
418 #if IP_REASS_CHECK_OVERLAP 419 LWIP_ASSERT(
"no previous fragment, this must be the first fragment!",
429 if ((ipr->flags & IP_REASS_FLAG_LASTFRAG) != 0) {
434 if ((ipr->p ==
NULL) || (((
struct ip_reass_helper*)ipr->p->payload)->start != 0)) {
441 iprh = (
struct ip_reass_helper*)q->
payload;
442 if (iprh_prev->end != iprh->start) {
454 ((
struct ip_reass_helper*)ipr->p->payload) != iprh);
456 iprh->next_pbuf ==
NULL);
457 LWIP_ASSERT(
"validate_datagram:datagram end!=datagram len",
458 iprh->end == ipr->datagram_len);
469 #if IP_REASS_CHECK_OVERLAP 484 ip4_reass(
struct pbuf *p)
487 struct ip_hdr *fraghdr;
488 struct ip_reassdata *ipr;
489 struct ip_reass_helper *iprh;
496 fraghdr = (
struct ip_hdr*)p->
payload;
498 if ((IPH_HL(fraghdr) * 4) != IP_HLEN) {
504 offset = (
ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8;
505 len =
ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4;
510 #if IP_REASS_FREE_OLDEST 511 if (!ip_reass_remove_oldest_datagram(fraghdr, clen) ||
527 for (ipr = reassdatagrams; ipr !=
NULL; ipr = ipr->next) {
531 if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) {
533 ntohs(IPH_ID(fraghdr))));
541 ipr = ip_reass_enqueue_new_datagram(fraghdr, clen);
547 if (((
ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) &&
548 ((
ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) {
553 SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN);
558 ip_reass_pbufcount += clen;
564 if ((IPH_OFFSET(fraghdr) &
PP_NTOHS(IP_MF)) == 0) {
565 ipr->flags |= IP_REASS_FLAG_LASTFRAG;
566 ipr->datagram_len = offset + len;
568 (
"ip4_reass: last fragment seen, total len %"S16_F"\n",
573 if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) {
574 struct ip_reassdata *ipr_prev;
577 ipr->datagram_len += IP_HLEN;
580 r = ((
struct ip_reass_helper*)ipr->p->payload)->next_pbuf;
583 fraghdr = (
struct ip_hdr*)(ipr->p->payload);
584 SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN);
585 IPH_LEN_SET(fraghdr,
htons(ipr->datagram_len));
586 IPH_OFFSET_SET(fraghdr, 0);
587 IPH_CHKSUM_SET(fraghdr, 0);
591 IPH_CHKSUM_SET(fraghdr,
inet_chksum(fraghdr, IP_HLEN));
599 iprh = (
struct ip_reass_helper*)r->
payload;
608 if (ipr == reassdatagrams) {
611 for (ipr_prev = reassdatagrams; ipr_prev !=
NULL; ipr_prev = ipr_prev->next) {
612 if (ipr_prev->next == ipr) {
619 ip_reass_dequeue_datagram(ipr, ipr_prev);
642 #if IP_FRAG_USES_STATIC_BUF 646 #if !LWIP_NETIF_TX_SINGLE_PBUF 648 static struct pbuf_custom_ref*
649 ip_frag_alloc_pbuf_custom_ref(
void)
651 return (
struct pbuf_custom_ref*)
memp_malloc(MEMP_FRAG_PBUF);
656 ip_frag_free_pbuf_custom_ref(
struct pbuf_custom_ref* p)
665 ipfrag_free_pbuf_custom(
struct pbuf *p)
667 struct pbuf_custom_ref *pcr = (
struct pbuf_custom_ref*)p;
670 if (pcr->original !=
NULL) {
673 ip_frag_free_pbuf_custom_ref(pcr);
692 ip4_frag(
struct pbuf *p,
struct netif *
netif,
const ip4_addr_t *dest)
695 #if IP_FRAG_USES_STATIC_BUF 698 #if !LWIP_NETIF_TX_SINGLE_PBUF 699 struct pbuf *newpbuf;
701 struct ip_hdr *original_iphdr;
703 struct ip_hdr *iphdr;
709 u16_t poff = IP_HLEN;
711 #if !IP_FRAG_USES_STATIC_BUF && !LWIP_NETIF_TX_SINGLE_PBUF 712 u16_t newpbuflen = 0;
717 #if IP_FRAG_USES_STATIC_BUF 723 if (rambuf ==
NULL) {
731 iphdr = (
struct ip_hdr *)rambuf->
payload;
734 original_iphdr = (
struct ip_hdr *)p->
payload;
735 iphdr = original_iphdr;
739 tmp =
ntohs(IPH_OFFSET(iphdr));
740 ofo = tmp & IP_OFFMASK;
745 nfb = (mtu - IP_HLEN) / 8;
748 last = (left <= mtu - IP_HLEN);
751 tmp = omf | (IP_OFFMASK & (ofo));
757 cop = last ? left : nfb * 8;
759 #if IP_FRAG_USES_STATIC_BUF 762 #if LWIP_NETIF_TX_SINGLE_PBUF 764 if (rambuf ==
NULL) {
777 iphdr = (
struct ip_hdr*)rambuf->
payload;
785 if (rambuf ==
NULL) {
789 (p->
len >= (IP_HLEN)));
791 iphdr = (
struct ip_hdr *)rambuf->
payload;
798 while (left_to_copy) {
799 struct pbuf_custom_ref *pcr;
800 newpbuflen = (left_to_copy < p->
len) ? left_to_copy : p->
len;
806 pcr = ip_frag_alloc_pbuf_custom_ref();
813 if (newpbuf ==
NULL) {
814 ip_frag_free_pbuf_custom_ref(pcr);
820 pcr->pc.custom_free_function = ipfrag_free_pbuf_custom;
826 left_to_copy -= newpbuflen;
836 IPH_OFFSET_SET(iphdr,
htons(tmp));
837 IPH_LEN_SET(iphdr,
htons(cop + IP_HLEN));
838 IPH_CHKSUM_SET(iphdr, 0);
841 IPH_CHKSUM_SET(iphdr,
inet_chksum(iphdr, IP_HLEN));
845 #if IP_FRAG_USES_STATIC_BUF 856 if (header !=
NULL) {
858 netif->output(netif, header, dest);
871 netif->output(netif, rambuf, dest);
886 #if IP_FRAG_USES_STATIC_BUF
#define MIB2_STATS_INC(x)
#define PACK_STRUCT_STRUCT
#define ip_current_input_netif()
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
void pbuf_realloc(struct pbuf *p, u16_t new_len)
#define SMEMCPY(dst, src, len)
#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag)
#define PACK_STRUCT_FIELD(x)
void memp_free(memp_t type, void *mem)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
u16_t inet_chksum(const void *dataptr, u16_t len)
#define IP_REASS_MAX_PBUFS
u8_t pbuf_free(struct pbuf *p)
void pbuf_chain(struct pbuf *h, struct pbuf *t)
#define LWIP_ASSERT(message, assertion)
void pbuf_ref(struct pbuf *p)
#define PACK_STRUCT_BEGIN
u16_t pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
u8_t pbuf_clen(struct pbuf *p)
void pbuf_cat(struct pbuf *h, struct pbuf *t)
#define LWIP_MEM_ALIGN(addr)
#define IPFRAG_STATS_INC(x)
#define LWIP_MEM_ALIGN_SIZE(size)
void * memp_malloc(memp_t type)
#define LWIP_DEBUGF(debug, message)
#define LWIP_UNUSED_ARG(x)