Another fix for bug #28241 (ooseq processing) and adapted corresponding unit test

This commit is contained in:
goldsimon 2009-12-27 11:31:19 +00:00
parent dc8639bc06
commit bf261f4f13
3 changed files with 22 additions and 33 deletions

View File

@ -22,6 +22,10 @@ HISTORY
++ Bugfixes: ++ Bugfixes:
2009-12-27: Simon Goldschmidt
* tcp_in.c: Another fix for bug #28241 (ooseq processing) and adapted
unit test
(STABLE-1.3.2) (STABLE-1.3.2)

View File

@ -1167,11 +1167,7 @@ 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;
@ -1179,42 +1175,37 @@ tcp_receive(struct tcp_pcb *pcb)
} }
} }
else { else {
struct tcp_seg* next = pcb->ooseq; next = pcb->ooseq;
struct tcp_seg *old_seg; /* Remove all segments on ooseq that are covered by inseg already.
/* rcv_nxt * FIN is copied from ooseq to inseg if present. */
* . |--ooseq--|
* .==seg============|
*/
while (next && while (next &&
TCP_SEQ_GEQ(seqno + tcplen, TCP_SEQ_GEQ(seqno + tcplen,
next->tcphdr->seqno + next->len)) { next->tcphdr->seqno + next->len)) {
/* inseg doesn't have FIN (already processed) */ /* inseg cannot have FIN here (already processed above) */
if (TCPH_FLAGS(next->tcphdr) & TCP_FIN && if (TCPH_FLAGS(next->tcphdr) & TCP_FIN &&
(TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) { (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) == 0) {
TCPH_FLAGS_SET(inseg.tcphdr, TCPH_FLAGS_SET(inseg.tcphdr,
TCPH_FLAGS(inseg.tcphdr) | TCP_FIN); TCPH_FLAGS(inseg.tcphdr) | TCP_FIN);
tcplen = TCP_TCPLEN(&inseg); tcplen = TCP_TCPLEN(&inseg);
} }
old_seg = next; prev = next;
next = next->next; next = next->next;
tcp_seg_free(old_seg); tcp_seg_free(prev);
} }
/* rcv_nxt /* Now trim right side of inseg if it overlaps with the first
* . |--ooseq--| * segment on ooseq */
* .==seg============|
*/
if (next && if (next &&
TCP_SEQ_GT(seqno + tcplen, TCP_SEQ_GT(seqno + tcplen,
next->tcphdr->seqno)) { next->tcphdr->seqno)) {
/* FIN in inseg already handled by dropping whole ooseq queue */ /* inseg cannot have FIN here (already processed above) */
inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno); inseg.len = (u16_t)(next->tcphdr->seqno - seqno);
if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) { if (TCPH_FLAGS(inseg.tcphdr) & TCP_SYN) {
inseg.len -= 1; inseg.len -= 1;
} }
pbuf_realloc(inseg.p, inseg.len); pbuf_realloc(inseg.p, inseg.len);
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) == next->tcphdr->seqno);
} }
pcb->ooseq = next; pcb->ooseq = next;
} }

View File

@ -208,11 +208,9 @@ START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ)
EXPECT(counters.recved_bytes == 0); EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0); EXPECT(counters.err_calls == 0);
/* check ooseq queue */ /* check ooseq queue */
EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2); EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 6); EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
/* pass the segment to tcp_input */ /* pass the segment to tcp_input */
tcp_input(p_fin, &netif); tcp_input(p_fin, &netif);
@ -222,11 +220,9 @@ START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ)
EXPECT(counters.recved_bytes == 0); EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0); EXPECT(counters.err_calls == 0);
/* ooseq queue: unchanged */ /* ooseq queue: unchanged */
EXPECT_OOSEQ(tcp_oos_count(pcb) == 2); EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2); EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 6); EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
/* pass the segment to tcp_input */ /* pass the segment to tcp_input */
tcp_input(pinseq, &netif); tcp_input(pinseq, &netif);
@ -363,13 +359,11 @@ START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
EXPECT(counters.recved_bytes == 0); EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0); EXPECT(counters.err_calls == 0);
/* check ooseq queue */ /* check ooseq queue */
EXPECT_OOSEQ(tcp_oos_count(pcb) == 3); EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1); EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1); EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 2); EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 2);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 1); EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 12);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 2) == 3);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 2) == 11);
/* pass the segment to tcp_input */ /* pass the segment to tcp_input */
tcp_input(pinseq, &netif); tcp_input(pinseq, &netif);