Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 1 Oct 1997 04:19:03 -0700
From:      Don Lewis <Don.Lewis@tsc.tdk.com>
To:        Richard Jones <richard@a42.deep-thought.org>, dg@root.com
Cc:        hackers@FreeBSD.ORG, bugs@FreeBSD.ORG
Subject:   Re: FreeBSD TCP stack and RST processing [subj changed]
Message-ID:  <199710011119.EAA14305@salsa.gv.tsc.tdk.com>
In-Reply-To: Richard Jones <richard@a42.deep-thought.org> "Re: FreeBSD TCP stack and RST processing [subj changed]" (Oct  1,  7:48pm)

next in thread | previous in thread | raw e-mail | index | archive | help
On Oct 1,  7:48pm, Richard Jones wrote:
} Subject: Re: FreeBSD TCP stack and RST processing [subj changed]
} 
} Ok the other system tested was 2-2 Stable.  implode.root.com exhibits the
} same behaviour as does 204.216.27.21 (the real freefall as pointed out by
} you in a later mail).  The main reason I didn't provide version info
} was that I thought it was an easy enough situation to replicate if it was 
} indeed replicatable.  Unfortunately I know of no systems that are running
} CURRENT to test upon.

I think this bug exists in all versions including -current ...

Fortunately, I have my copy of TCP/IP Illustrated Volume 2 here in the
office :-)

The initial faked SYN will put is in the SYN_RECEIVED state.  This is the
code from tcp_input() in -current that is supposed handle this situation,
and it appears to be the same in 2.1 and 2.2:

        /*
         * If the RST bit is set examine the state:
         *    SYN_RECEIVED STATE:
         *      If passive open, return to LISTEN state.
         *      If active open, inform user that connection was refused.
         *    ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES:
         *      Inform user that connection was reset, and close tcb.
         *    CLOSING, LAST_ACK, TIME_WAIT STATES
         *      Close the tcb.
         */ 
        if (tiflags&TH_RST) switch (tp->t_state) {
                
        case TCPS_SYN_RECEIVED:
                so->so_error = ECONNREFUSED;
                goto close;


This code appears to be correct, and agrees with what's in the book.

However ... there is some code *earlier* in tcp_input() that looks like it
botches this situation:

        /*
         * If the state is SYN_RECEIVED:
         *      do just the ack and RST checks from SYN_SENT state.
         * If the state is SYN_SENT:
         *      if seg contains an ACK, but not for our SYN, drop the input.
         *      if seg contains a RST, then drop the connection.
         *      if seg does not contain SYN, then drop it.
         * Otherwise this is an acceptable SYN segment
         *      initialize tp->rcv_nxt and tp->irs
         *      if seg contains ack then advance tp->snd_una
         *      if SYN has been acked change to ESTABLISHED else SYN_RCVD state
         *      arrange for segment to be acked (eventually)
         *      continue processing rest of data/controls, beginning with URG
         */
        case TCPS_SYN_RECEIVED:
        case TCPS_SYN_SENT:   
                if ((taop = tcp_gettaocache(inp)) == NULL) {
                        taop = &tao_noncached;
                        bzero(taop, sizeof(*taop));
                }

                if ((tiflags & TH_ACK) &&
                    (SEQ_LEQ(ti->ti_ack, tp->iss) ||
                     SEQ_GT(ti->ti_ack, tp->snd_max))) {
                        /*    
                         * If we have a cached CCsent for the remote host,
                         * hence we haven't just crashed and restarted,
                         * do not send a RST.  This may be a retransmission
                         * from the other side after our earlier ACK was lost.
                         * Our new SYN, when it arrives, will serve as the
                         * needed ACK.
                         */   
                        if (taop->tao_ccsent != 0)
                                goto drop;
                        else   
                                goto dropwithreset;
                }
                if (tiflags & TH_RST) {
                        if (tiflags & TH_ACK)
                                tp = tcp_drop(tp, ECONNREFUSED);
                        goto drop;
                }              
                if (tp->t_state == TCPS_SYN_RECEIVED)
                        break;

It looks like we just drop the packet containing the RST!  The example code
in the book does not execute this code in the SYN_RECEIVED state.  I don't
know the history of this code, so I don't know why it was changed.

copied to freebsd-bugs

			---  Truck



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199710011119.EAA14305>