seq# of RST in tcp_dropwithreset
Andre Oppermann
andre at freebsd.org
Wed Jun 13 13:30:39 UTC 2012
On 07.06.2012 22:28, George Neville-Neil wrote:
>
> On Mar 27, 2012, at 18:13 , Navdeep Parhar wrote:
>
>> When the kernel decides to respond with a RST to an incoming TCP
>> segment, it uses its ack# (if valid) as the seq# of the RST. See this
>> in tcp_dropwithreset:
>>
>> if (th->th_flags& TH_ACK) {
>> tcp_respond(tp, mtod(m, void *), th, m, (tcp_seq)0,
>> th->th_ack, TH_RST);
>> } else {
>> if (th->th_flags& TH_SYN)
>> tlen++;
>> tcp_respond(tp, mtod(m, void *), th, m, th->th_seq+tlen,
>> (tcp_seq)0, TH_RST|TH_ACK);
>> }
>>
>> This can have some unexpected results. I observed this on a link with
>> a very high delay (B is FreeBSD, A could be anything).
>>
>> 1. There is a segment in flight from A to B. The ack# is X (all tx
>> from B to A is up to date and acknowledged).
>> 2. socket is closed on B. B sends a FIN with seq# X.
>> 3. The segment from A arrives and elicits a RST from B. The seq# of
>> this RST will again be X. A receives the FIN and then the RST with
>> identical sequence numbers. The situation resolves itself eventually,
>> when A retransmits and the retransmitted segment ACKs the FIN too and
>> so the next time around B sends a RST with the "correct" seq# (one
>> after the FIN).
>>
>> If there is a local tcpcb for the connection with state>=
>> ESTABLISHED, wouldn't it be more accurate to use its snd_max as the
>> seq# of the RST?
>>
>
> Hi Navdeep,
>
> Sorry I missed this so many months ago, but jhb@ was kind enough to point this
> query out to me. My understanding of correct operation in this case, is that we
> do not want to move the sequence number until we have received the ACK of our
> FIN, as any other value would indicate to the TCP on A that we have received their
> ACK of our FIN, which, in this case, we have not. The fact that there isn't a better
> way to indicate the error is a tad annoying, but, and others can correct me if they think
> I'm wrong, this is the correct way for the stacks to come to eventual agreement
> on the closing of the connection.
In this case Navdeep is correct. As long as a tcpcb is around no RST
should be generated in step 3 if we are in FIN_WAIT_1, FIN_WAIT_2, CLOSING
or TIME_WAIT.
What is the code path leading to tcp_dropwithreset()? Normally this should
only be reached if no tcpcb is found.
--
Andre
More information about the freebsd-net
mailing list