mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2024-11-16 23:15:37 +00:00
ip4_reass: fixed bug #51595 (ip_reass_pbufcount may be updated incorectly)
(cherry picked from commit f1072fee8a
)
# Conflicts:
# src/core/ipv4/ip4_frag.c
This commit is contained in:
parent
82e5a18b50
commit
737ed228c9
@ -79,6 +79,10 @@
|
|||||||
|
|
||||||
#define IP_REASS_FLAG_LASTFRAG 0x01
|
#define IP_REASS_FLAG_LASTFRAG 0x01
|
||||||
|
|
||||||
|
#define IP_REASS_VALIDATE_TELEGRAM_FINISHED 1
|
||||||
|
#define IP_REASS_VALIDATE_PBUF_QUEUED 0
|
||||||
|
#define IP_REASS_VALIDATE_PBUF_DROPPED -1
|
||||||
|
|
||||||
/** This is a helper struct which holds the starting
|
/** This is a helper struct which holds the starting
|
||||||
* offset and the ending offset of this fragment to
|
* offset and the ending offset of this fragment to
|
||||||
* easily chain the fragments.
|
* easily chain the fragments.
|
||||||
@ -333,7 +337,7 @@ ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev)
|
|||||||
* fragment was received at least once).
|
* fragment was received at least once).
|
||||||
* @param ipr points to the reassembly state
|
* @param ipr points to the reassembly state
|
||||||
* @param new_p points to the pbuf for the current fragment
|
* @param new_p points to the pbuf for the current fragment
|
||||||
* @return 0 if invalid, >0 otherwise
|
* @return see IP_REASS_VALIDATE_* defines
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p)
|
ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct pbuf *new_p)
|
||||||
@ -462,15 +466,15 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct
|
|||||||
/* If valid is 0 here, there are some fragments missing in the middle
|
/* If valid is 0 here, there are some fragments missing in the middle
|
||||||
* (since MF == 0 has already arrived). Such datagrams simply time out if
|
* (since MF == 0 has already arrived). Such datagrams simply time out if
|
||||||
* no more fragments are received... */
|
* no more fragments are received... */
|
||||||
return valid;
|
return valid ? IP_REASS_VALIDATE_TELEGRAM_FINISHED : IP_REASS_VALIDATE_PBUF_QUEUED;
|
||||||
}
|
}
|
||||||
/* If we come here, not all fragments were received, yet! */
|
/* If we come here, not all fragments were received, yet! */
|
||||||
return 0; /* not yet valid! */
|
return IP_REASS_VALIDATE_PBUF_QUEUED; /* not yet valid! */
|
||||||
#if IP_REASS_CHECK_OVERLAP
|
#if IP_REASS_CHECK_OVERLAP
|
||||||
freepbuf:
|
freepbuf:
|
||||||
ip_reass_pbufcount -= pbuf_clen(new_p);
|
ip_reass_pbufcount -= pbuf_clen(new_p);
|
||||||
pbuf_free(new_p);
|
pbuf_free(new_p);
|
||||||
return 0;
|
return IP_REASS_VALIDATE_PBUF_DROPPED;
|
||||||
#endif /* IP_REASS_CHECK_OVERLAP */
|
#endif /* IP_REASS_CHECK_OVERLAP */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,6 +492,7 @@ ip4_reass(struct pbuf *p)
|
|||||||
struct ip_reassdata *ipr;
|
struct ip_reassdata *ipr;
|
||||||
struct ip_reass_helper *iprh;
|
struct ip_reass_helper *iprh;
|
||||||
u16_t offset, len, clen;
|
u16_t offset, len, clen;
|
||||||
|
int valid;
|
||||||
|
|
||||||
IPFRAG_STATS_INC(ip_frag.recv);
|
IPFRAG_STATS_INC(ip_frag.recv);
|
||||||
MIB2_STATS_INC(mib2.ipreasmreqds);
|
MIB2_STATS_INC(mib2.ipreasmreqds);
|
||||||
@ -552,9 +557,6 @@ ip4_reass(struct pbuf *p)
|
|||||||
SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN);
|
SMEMCPY(&ipr->iphdr, fraghdr, IP_HLEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Track the current number of pbufs current 'in-flight', in order to limit
|
|
||||||
the number of fragments that may be enqueued at any one time */
|
|
||||||
ip_reass_pbufcount += clen;
|
|
||||||
|
|
||||||
/* At this point, we have either created a new entry or pointing
|
/* At this point, we have either created a new entry or pointing
|
||||||
* to an existing one */
|
* to an existing one */
|
||||||
@ -569,7 +571,18 @@ ip4_reass(struct pbuf *p)
|
|||||||
}
|
}
|
||||||
/* find the right place to insert this pbuf */
|
/* find the right place to insert this pbuf */
|
||||||
/* @todo: trim pbufs if fragments are overlapping */
|
/* @todo: trim pbufs if fragments are overlapping */
|
||||||
if (ip_reass_chain_frag_into_datagram_and_validate(ipr, p)) {
|
valid = ip_reass_chain_frag_into_datagram_and_validate(ipr, p);
|
||||||
|
if (valid == IP_REASS_VALIDATE_PBUF_DROPPED) {
|
||||||
|
goto nullreturn;
|
||||||
|
}
|
||||||
|
/* if we come here, the pbuf has been enqueued */
|
||||||
|
|
||||||
|
/* Track the current number of pbufs current 'in-flight', in order to limit
|
||||||
|
the number of fragments that may be enqueued at any one time
|
||||||
|
(overflow checked by testing against IP_REASS_MAX_PBUFS) */
|
||||||
|
ip_reass_pbufcount = (u16_t)(ip_reass_pbufcount + clen);
|
||||||
|
|
||||||
|
if (valid == IP_REASS_VALIDATE_TELEGRAM_FINISHED) {
|
||||||
struct ip_reassdata *ipr_prev;
|
struct ip_reassdata *ipr_prev;
|
||||||
/* the totally last fragment (flag more fragments = 0) was received at least
|
/* the totally last fragment (flag more fragments = 0) was received at least
|
||||||
* once AND all fragments are received */
|
* once AND all fragments are received */
|
||||||
|
Loading…
Reference in New Issue
Block a user