mirror of
https://github.com/lwip-tcpip/lwip.git
synced 2025-02-06 18:41:30 +00:00
BUG28241: improve oos sequence processing with patches from Oleg Tyshev.
This commit is contained in:
parent
feca27d69e
commit
6b6c82aaee
@ -46,6 +46,10 @@ HISTORY
|
|||||||
|
|
||||||
++ Bugfixes:
|
++ Bugfixes:
|
||||||
|
|
||||||
|
2009-12-24: Kieran Mansley
|
||||||
|
* tcp_in.c Apply patches from Oleg Tyshev to improve OOS processing
|
||||||
|
(BUG#28241)
|
||||||
|
|
||||||
2009-12-06: Simon Goldschmidt
|
2009-12-06: Simon Goldschmidt
|
||||||
* ppp.h/.c: Fixed bug #27079 (Yet another leak in PPP): outpacket_buf can
|
* ppp.h/.c: Fixed bug #27079 (Yet another leak in PPP): outpacket_buf can
|
||||||
be statically allocated (like in ucip)
|
be statically allocated (like in ucip)
|
||||||
|
@ -743,17 +743,24 @@ tcp_process(struct tcp_pcb *pcb)
|
|||||||
static void
|
static void
|
||||||
tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next)
|
tcp_oos_insert_segment(struct tcp_seg *cseg, struct tcp_seg *next)
|
||||||
{
|
{
|
||||||
|
struct tcp_seg *old_seg;
|
||||||
|
|
||||||
if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
|
if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
|
||||||
/* received segment overlaps all following segments */
|
/* received segment overlaps all following segments */
|
||||||
tcp_segs_free(next);
|
tcp_segs_free(next);
|
||||||
next = NULL;
|
next = NULL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* delete some following segments */
|
/* delete some following segments
|
||||||
|
oos queue may have segments with FIN flag */
|
||||||
while (next &&
|
while (next &&
|
||||||
TCP_SEQ_GT((seqno + cseg->len),
|
TCP_SEQ_GEQ((seqno + cseg->len),
|
||||||
(next->tcphdr->seqno + next->len))) {
|
(next->tcphdr->seqno + next->len))) {
|
||||||
struct tcp_seg *old_seg = next;
|
/* cseg with FIN already processed */
|
||||||
|
if (TCPH_FLAGS(next->tcphdr) & TCP_FIN) {
|
||||||
|
TCPH_FLAGS_SET(cseg->tcphdr, TCPH_FLAGS(cseg->tcphdr) | TCP_FIN);
|
||||||
|
}
|
||||||
|
old_seg = next;
|
||||||
next = next->next;
|
next = next->next;
|
||||||
tcp_seg_free(old_seg);
|
tcp_seg_free(old_seg);
|
||||||
}
|
}
|
||||||
@ -1160,17 +1167,45 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
("tcp_receive: received in-order FIN, binning ooseq queue\n"));
|
("tcp_receive: received in-order FIN, binning ooseq queue\n"));
|
||||||
/* Received in-order FIN means anything that was received
|
/* Received in-order FIN means anything that was received
|
||||||
* out of order must now have been received in-order, so
|
* out of order must now have been received in-order, so
|
||||||
* bin the ooseq queue */
|
* bin the ooseq queue
|
||||||
|
* rcv_nxt
|
||||||
|
* . |--ooseq--|
|
||||||
|
* .==seg============|FIN
|
||||||
|
*/
|
||||||
while (pcb->ooseq != NULL) {
|
while (pcb->ooseq != NULL) {
|
||||||
struct tcp_seg *old_ooseq = pcb->ooseq;
|
struct tcp_seg *old_ooseq = pcb->ooseq;
|
||||||
pcb->ooseq = pcb->ooseq->next;
|
pcb->ooseq = pcb->ooseq->next;
|
||||||
tcp_seg_free(old_ooseq);
|
tcp_seg_free(old_ooseq);
|
||||||
}
|
}
|
||||||
} else if (TCP_SEQ_LEQ(pcb->ooseq->tcphdr->seqno, seqno + tcplen)) {
|
}
|
||||||
if (pcb->ooseq->len > 0) {
|
else {
|
||||||
/* We have to trim the second edge of the incoming segment. */
|
struct tcp_seg* next = pcb->ooseq;
|
||||||
LWIP_ASSERT("tcp_receive: trimmed segment would have zero length\n",
|
struct tcp_seg *old_seg;
|
||||||
TCP_SEQ_GT(pcb->ooseq->tcphdr->seqno, seqno));
|
/* rcv_nxt
|
||||||
|
* . |--ooseq--|
|
||||||
|
* .==seg============|
|
||||||
|
*/
|
||||||
|
while (next &&
|
||||||
|
TCP_SEQ_GEQ(seqno + tcplen,
|
||||||
|
next->tcphdr->seqno + next->len)) {
|
||||||
|
/* inseg doesn't have FIN (already processed) */
|
||||||
|
if (TCPH_FLAGS(next->tcphdr) & TCP_FIN &&
|
||||||
|
(TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
|
||||||
|
TCPH_FLAGS_SET(inseg.tcphdr,
|
||||||
|
TCPH_FLAGS(inseg.tcphdr) | TCP_FIN);
|
||||||
|
tcplen = TCP_TCPLEN(&inseg);
|
||||||
|
}
|
||||||
|
old_seg = next;
|
||||||
|
next = next->next;
|
||||||
|
tcp_seg_free(old_seg);
|
||||||
|
}
|
||||||
|
/* rcv_nxt
|
||||||
|
* . |--ooseq--|
|
||||||
|
* .==seg============|
|
||||||
|
*/
|
||||||
|
if (next &&
|
||||||
|
TCP_SEQ_GT(seqno + tcplen,
|
||||||
|
next->tcphdr->seqno)) {
|
||||||
/* FIN in inseg already handled by dropping whole ooseq queue */
|
/* FIN in inseg already handled by dropping whole ooseq queue */
|
||||||
inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno);
|
inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno);
|
||||||
if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
|
if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
|
||||||
@ -1180,15 +1215,8 @@ tcp_receive(struct tcp_pcb *pcb)
|
|||||||
tcplen = TCP_TCPLEN(&inseg);
|
tcplen = TCP_TCPLEN(&inseg);
|
||||||
LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
|
LWIP_ASSERT("tcp_receive: segment not trimmed correctly to ooseq queue\n",
|
||||||
(seqno + tcplen) == pcb->ooseq->tcphdr->seqno);
|
(seqno + tcplen) == pcb->ooseq->tcphdr->seqno);
|
||||||
} else {
|
|
||||||
/* does the ooseq segment contain only flags that are in inseg also? */
|
|
||||||
if ((TCPH_FLAGS(inseg.tcphdr) & (TCP_FIN|TCP_SYN)) ==
|
|
||||||
(TCPH_FLAGS(pcb->ooseq->tcphdr) & (TCP_FIN|TCP_SYN))) {
|
|
||||||
struct tcp_seg *old_ooseq = pcb->ooseq;
|
|
||||||
pcb->ooseq = pcb->ooseq->next;
|
|
||||||
tcp_seg_free(old_ooseq);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
pcb->ooseq = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* TCP_QUEUE_OOSEQ */
|
#endif /* TCP_QUEUE_OOSEQ */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user