TCP bug?

Hartmut Brandt hartmut.brandt at dlr.de
Fri Jun 19 20:04:52 UTC 2009


Hi,

On Fri, 19 Jun 2009, Karim Fodil-Lemelin wrote:

KF>Looking at Steven's book TCP/IP Volume 2 (1995 edition) page 988 (Processing
KF>and Received Data) they call TCP_REASS(tp, ti, m, so, tiflags) where tiflags
KF>is thflags and inside the TCP_REASS macro (page 908), this code is used
KF>(where ti is the tcpiphdr pointer):
KF>
KF>flags = (ti)->ti_flags & TH_FIN; \
KF>
KF>Same problem there as well ...
KF>
KF>Also, looking at tcp_reass(), the same approach of using the header version
KF>is used there:
KF>
KF>flags = q->tqe_th->th_flags & TH_FIN;
KF>
KF>This seems to work since the data was kept inside the reassembly queue and
KF>not dropped
KF>
KF>If this problem is confirmed you've probably found an original implementation
KF>bug. Can you describe better the test condition to reproduce this problem?

Sure. I've a test environment for TCP which does for this test the 
following:

- open a TCP socket, set the socket send buffer to 32768 byte

- call connect() and expect

   SYN seq=<iss> win=32768
 
- tester responds with

   SYN, FIN, ACK=<iss+1> data=(41000 bytes) seq=<irs>

- expect

   ACK=<irs+32769> seq=<iss+1>

- check that TCP is in EsTABLISHED state

Everything is fine except that TCP ends up in CLOSE_WAIT.

harti

KF>Harti Brandt wrote:
KF>> 
KF>> Hi all,
KF>> 
KF>> one of my TCP test cases breaks in what one could call an edge case:
KF>> 
KF>> When the TCP is in SYN-SENT state (the user has called connect()) and the
KF>> peer answers with an almost-lamp test packet which has SYN, FIN, ACK and
KF>> data larger than the window, TCP ACKs a window full of data, drops the
KF>> rest, but processes the FIN - it goes into CLOSE_WAIT. This looks wrong to
KF>> me. When dropping the data that is outside the window, it should also drop
KF>> the FIN.
KF>> 
KF>> The problem seems to be very old - I found it alread in rev. 1.1
KF>> of tcp_input.c. In -CURRENT it is on line 2590: when the sequence number
KF>> of the incoming segment is the next expected one, the reassembly queue is
KF>> empty and we are in an established state, the segment data is added to the
KF>> socket buffer and all TCP header flags are cleared except for TH_FIN.
KF>> Unfortunately here the original header flags are taken instead of the
KF>> cached version in thflags. Earlier in the processing the out-of-window
KF>> data and the FIN in thflags were chopped off and now TH_FIN reappears.
KF>> 
KF>> The fix should be easy: instead of using the original flag byte to get the
KF>> FIN use the cached copy.
KF>> 
KF>> Index: tcp_input.c
KF>> ===================================================================
KF>> --- tcp_input.c    (revision 194499)
KF>> +++ tcp_input.c    (working copy)
KF>> @@ -2587,7 +2587,7 @@
KF>>                 else
KF>>                     tp->t_flags |= TF_ACKNOW;
KF>>                 tp->rcv_nxt += tlen;
KF>> -            thflags = th->th_flags & TH_FIN;
KF>> +            thflags &= TH_FIN;
KF>>                 TCPSTAT_INC(tcps_rcvpack);
KF>>                 TCPSTAT_ADD(tcps_rcvbyte, tlen);
KF>>                 ND6_HINT(tp);
KF>> 
KF>> I wonder, though, why the code is as it is, i.e. why it takes the original
KF>> FIN flag. Any idea?
KF>> 
KF>> harti
KF>> 
KF>> _______________________________________________
KF>> freebsd-net at freebsd.org mailing list
KF>> http://lists.freebsd.org/mailman/listinfo/freebsd-net
KF>> To unsubscribe, send any mail to "freebsd-net-unsubscribe at freebsd.org"
KF>
KF>


More information about the freebsd-net mailing list