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>