Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 10 Aug 2000 13:19:55 +0200
From:      Roland Geier <Roland.Geier@philosys.de>
To:        freebsd-net@freebsd.org
Subject:   syn received on half open connection
Message-ID:  <39928FDB.28E687B9@philosys.de>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------F97D64E3D6AEC89A5AB8798B
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hello,

I've got a question concerning the fits-to-specs-behaviour of BSD
derived tcp implementations when a syn is received on half open
connections. Therefore, please assume the scenario that is pointed out
in rfc793, section 'Half-Open Connections and Other Anomalies':

--------------- excerpt from rfc793  ---------------

Assume that two user processes A and B are communicating with one
another when a crash occurs causing loss of memory to A's TCP. Depending
on the operating system supporting A's TCP, it is likely that some error
recovery mechanism exists.  When the TCP is up again, A is likely to
start again from the beginning or from a recovery point.  As a result, A
will probably try to OPEN the connection again or try to SEND on the
connection it believes open.  In the latter case, it receives the error
message "connection not open" from the local (A's) TCP.  In an attempt
to establish the connection, A's TCP will send a segment containing
SYN.  This scenario leads to the example shown in figure 10.  After TCP
A crashes, the user attempts to re-open the connection.  TCP B, in the
meantime, thinks the connection is open.

   TCP A                                         TCP B

1. (CRASH)                            (send 300,receive 100)
2. CLOSED                                        ESTABLISHED
3. SYN-SENT --> <SEQ=400><CTL=SYN>           --> (??)
4. (!!)     <-- <SEQ=300><ACK=100><CTL=ACK>  <-- ESTABLISHED
5. SYN-SENT --> <SEQ=100><CTL=RST>           --> (Abort!!)
6. SYN-SENT                                      CLOSED
7. SYN-SENT --> <SEQ=400><CTL=SYN>           -->

When the SYN arrives at line 3, TCP B, being in a synchronized state,
and the incoming segment outside the window, responds with an
acknowledgment indicating what sequence it next expects to hear (ACK
100).  TCP A sees that this segment does not acknowledge anything it
sent and, being unsynchronized, sends a reset (RST) because it has
detected a half-open connection.  TCP B aborts at line 5. TCP A will
continue to try to establish the connection; the problem is now reduced
to the basic 3-way handshake.

---------------  end of excerpt  ---------------

I assume two different cases when the SYN arrives on a half open
connection:

(a) the SYN packet's ISS is *within* the receive window of TCP B 
(b) the SYN packet's ISS is *not* within the receive window of TCP B

AS shown in [Code A] (see TCP/IP Illustrated Vol. II, Fig. 28.37), case
(a) is considered to be an error and BSD implementations will send a RST
and drop the connection:

        ----- [Code A] -----

        /*
         * If a SYN is in the window, then this is an
         * error and we send an RST and drop the connection.
         */
        if (tiflags & TH_SYN) {
                tp = tcp_drop(tp, ECONNRESET);
                goto dropwithreset;
        }

Let's now assume case (b), i.e. the syn is *not* in the  window. In this
case the SYN-Flag is explicitly switched off (see [Code B], taken from
Fig. 28.24):

        ----- [Code B] -----

        todrop = tp->rcv_nxt - ti->ti_seq;
        if (todrop > 0) {
                if (tiflags & TH_SYN) {
                        tiflags &= ~TH_SYN;
                        ti->ti_seq++;
                        :
        }

As [Code B] is located before [Code A], BSD won't send a reset if the
syn is *not* within the window as the SYN bit was explicitly reset. 

Furthermore, [Code C] (see Fig. 28.37 again), directly following [Code
A], states:

        ----- [Code C] -----

        /*
         * If the ACK bit is off we drop the segment and return.
         */
         if ((tiflags & TH_ACK) == 0)
           goto drop;

As in an initial SYN request the ACK bit isn't set, a SYN request that
does not fall into the window will be silently dropped in BSD instead of
sending an ACK before dropping the packet. If I did not miss the point,
this behaviour violates the spec. 

A colleague of mine found out that the original implementation did not
trigger this bug (see. Fig 28.25) as the 'goto dropafterack' in line 671
forced an ACK to be sent. The correction suggested in Fig. 28.30 doesn't
do that.

Suggested fix:

Use the 'TF_ACKNOW'-marker set in Fig. 28.30 to trigger the ACK later
on. Attached you'll find a patch for tcp_input.c (Version 1.118). I'd
like to open this patch for discussion.

Roland
--------------F97D64E3D6AEC89A5AB8798B
Content-Type: text/plain; charset=us-ascii;
 name="synpatch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="synpatch"

*** tcp_input.c-1.118	Thu Aug 10 11:45:05 2000
--- tcp_input.c	Thu Aug 10 11:52:06 2000
***************
*** 1678,1686 ****
  		if (tp->t_state == TCPS_SYN_RECEIVED ||
  		    (tp->t_flags & TF_NEEDSYN))
  			goto step6;
! 		else
! 			goto drop;
! 	}
  
  	/*
  	 * Ack processing.
--- 1678,1694 ----
  		if (tp->t_state == TCPS_SYN_RECEIVED ||
  		    (tp->t_flags & TF_NEEDSYN))
  			goto step6;
!                 /*
!                  * if we want resynchronization ack's to be generated,
!                  * here is the place to do it: the marker set above now
!                  * can be evaluated and jumping to dropafterack will then
!                  * generate the resynchronization ack.
!                  */
!                 else if (tp->t_flags & TF_ACKNOW)
!                         goto dropafterack;
!                 else
!                         goto drop;
!         }
  
  	/*
  	 * Ack processing.

--------------F97D64E3D6AEC89A5AB8798B--



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?39928FDB.28E687B9>