Subject: syn received on half open connection

From: Roland Geier <[email-masked]>
Date: Thu, 27 Jul 2000 16:01:37 +0200

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  ---------------

The scenario does not differentiate between the following cases when the
SYN arrives at line 3:

(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 won't be set when coming
along [Code A].

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, at least
accoding to Rich Stevens and the FreeBSD implementation. If I did not
miss the point that would violate the spec, wouldn't it? 

Any comments on that would be highly appreciated,

Roland.

-- 
Roland Geier             Philosys Software GmbH
[email-masked]        Edisonstr. 6
tel: +49 89 321407 56    D-85716 Unterschleissheim
fax: +49 89 321407 12    http://www.philosys.de

---

From: venkat venkatsubra <[email-masked]>
Date: Thu, 27 Jul 2000 10:46:56 -0500

> Any comments on that would be highly appreciated,
Roland, 
     The rfc does differentiate case (a) and (b). In page 70 of rfc793 it
     says this:
 
--------------------------------------------
    fourth, check the SYN bit,
 
      SYN-RECEIVED
      ESTABLISHED STATE
      FIN-WAIT STATE-1
      FIN-WAIT STATE-2
      CLOSE-WAIT STATE
      CLOSING STATE
      LAST-ACK STATE
      TIME-WAIT STATE
 
        If the SYN is in the window it is an error, send a reset, any
        outstanding RECEIVEs and SEND should receive "reset" responses,
        all segment queues should be flushed, the user should also
        receive an unsolicited general "connection reset" signal, enter
        the CLOSED state, delete the TCB, and return.
 
        If the SYN is not in the window this step would not be reached
        and an ack would have been sent in the first step (sequence
        number check).
---------------------------------------------

     And the code fragment [C] is according to the next line in the spec
     (page 71): 
 
-------------------------------------------
    fifth check the ACK field,
 
      if the ACK bit is off drop the segment and return
------------------------------------------

Venkat