[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lwip-users] out-of-sequence FIN segment bug
From: |
Oleg Tychev |
Subject: |
[lwip-users] out-of-sequence FIN segment bug |
Date: |
Thu, 06 Apr 2006 13:13:42 +0200 |
User-agent: |
Thunderbird 1.5 (Windows/20051201) |
Hello All,
I think I have found bug (Thanks to a slow hub:) ).
If TCP segment with FIN flag is received out-of-sequence,
it is processed as in-sequence fragment.
Modifications:
tcp_receive
forced passive close for FIN, that in-sequence after processing
current fragment
returns 1 if fragment in-sequence
tcp_process
case CLOSE_WAIT:
case ESTABLISHED:
move to CLOSE_WAIT only if FIN fragment in-sequence
Oleg Tychev
Here is patch against version lwip-1.1.1
--- lwip-1.1.1/src/core/1/tcp_in.c 2006-03-01 16:53:42.000000000 +0100
+++ lwip-1.1.1/src/core/2/tcp_in.c 2006-04-06 11:08:37.359375000 +0200
@@ -74,7 +74,7 @@
/* Forward declarations. */
static err_t tcp_process(struct tcp_pcb *pcb);
-static void tcp_receive(struct tcp_pcb *pcb);
+static u8_t tcp_receive(struct tcp_pcb *pcb);
static void tcp_parseopt(struct tcp_pcb *pcb);
static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
@@ -436,6 +436,7 @@
struct tcp_seg *rseg;
u8_t acceptable = 0;
err_t err;
+ u8_t accepted_inseq;
err = ERR_OK;
@@ -545,8 +546,8 @@
case CLOSE_WAIT:
/* FALLTHROUGH */
case ESTABLISHED:
- tcp_receive(pcb);
- if (flags & TCP_FIN) {
+ accepted_inseq = tcp_receive(pcb);
+ if ((flags & TCP_FIN) && accepted_inseq) { /* passive close */
tcp_ack_now(pcb);
pcb->state = CLOSE_WAIT;
}
@@ -618,7 +619,7 @@
* estimation, the RTT is estimated here as well.
*/
-static void
+static u8_t
tcp_receive(struct tcp_pcb *pcb)
{
struct tcp_seg *next;
@@ -630,6 +631,7 @@
s16_t m;
u32_t right_wnd_edge;
u16_t new_tot_len;
+ u8_t accepted_inseq = 0;
if (flags & TCP_ACK) {
@@ -922,6 +924,7 @@
TCP_SEQ_LT(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
if(TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd
- 1)){
if (pcb->rcv_nxt == seqno) {
+ accepted_inseq = 1;
/* The incoming segment is the next in sequence. We check if
we have to trim the end of the segment and update rcv_nxt
and pass the data to the application. */
@@ -1000,6 +1003,9 @@
if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
recv_flags = TF_GOT_FIN;
+ if (pcb->state == ESTABLISHED) { /* force passive close or
we can move to active close */
+ pcb->state = CLOSE_WAIT;
+ }
}
@@ -1144,6 +1150,7 @@
tcp_ack_now(pcb);
}
}
+ return accepted_inseq;
}
/*
--- lwip-1.1.1/src/core/1/tcp_in.c 2006-03-01 16:53:42.000000000 +0100
+++ lwip-1.1.1/src/core/2/tcp_in.c 2006-04-06 11:08:37.359375000 +0200
@@ -74,7 +74,7 @@
/* Forward declarations. */
static err_t tcp_process(struct tcp_pcb *pcb);
-static void tcp_receive(struct tcp_pcb *pcb);
+static u8_t tcp_receive(struct tcp_pcb *pcb);
static void tcp_parseopt(struct tcp_pcb *pcb);
static err_t tcp_listen_input(struct tcp_pcb_listen *pcb);
@@ -436,6 +436,7 @@
struct tcp_seg *rseg;
u8_t acceptable = 0;
err_t err;
+ u8_t accepted_inseq;
err = ERR_OK;
@@ -545,8 +546,8 @@
case CLOSE_WAIT:
/* FALLTHROUGH */
case ESTABLISHED:
- tcp_receive(pcb);
- if (flags & TCP_FIN) {
+ accepted_inseq = tcp_receive(pcb);
+ if ((flags & TCP_FIN) && accepted_inseq) { /* passive close */
tcp_ack_now(pcb);
pcb->state = CLOSE_WAIT;
}
@@ -618,7 +619,7 @@
* estimation, the RTT is estimated here as well.
*/
-static void
+static u8_t
tcp_receive(struct tcp_pcb *pcb)
{
struct tcp_seg *next;
@@ -630,6 +631,7 @@
s16_t m;
u32_t right_wnd_edge;
u16_t new_tot_len;
+ u8_t accepted_inseq = 0;
if (flags & TCP_ACK) {
@@ -922,6 +924,7 @@
TCP_SEQ_LT(seqno, pcb->rcv_nxt + pcb->rcv_wnd)) {*/
if(TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd - 1)){
if (pcb->rcv_nxt == seqno) {
+ accepted_inseq = 1;
/* The incoming segment is the next in sequence. We check if
we have to trim the end of the segment and update rcv_nxt
and pass the data to the application. */
@@ -1000,6 +1003,9 @@
if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
recv_flags = TF_GOT_FIN;
+ if (pcb->state == ESTABLISHED) { /* force passive close or we can
move to active close */
+ pcb->state = CLOSE_WAIT;
+ }
}
@@ -1144,6 +1150,7 @@
tcp_ack_now(pcb);
}
}
+ return accepted_inseq;
}
/*
- [lwip-users] out-of-sequence FIN segment bug,
Oleg Tychev <=