Re: Two different places between TCP socket behavior and RFC documents

Vadim Goncharov <[email protected]>
Newsgroups gmane.os.freebsd.devel.net
Message-ID <[email protected]>
On Thu, 18 Sep 2025 16:50:46 +0800
Tilnel <[email protected]> wrote:

> Hi,
> 
> I found two behaviors different with RFC recommendations in FreeBSD 14.3 TCP
> socket.
> 
> 1. Failure to RST on close with data pending
> According to RFC2525 section 2.17, RST should be sent when close() on socket
> with pending data to read in receive buffer.
> According to RFC1122: A host MAY implement a "half-duplex" TCP close
> sequence, ... cannot continue to read data ... If such a host issues a CLOSE
>           call while received data is still pending in TCP, or if new data is
>           received after CLOSE is called, its TCP SHOULD send a RST to show
> that data was lost.
> It's not the case with FreeBSD TCP socket. Here is TCPDUMP output,
> showing close()
> on socket with pending data emit FIN instead of RST.
>   A > B: Flags [S], seq 2636678338, win 65535, length 0
>   B > A: Flags [S.], seq 1969223298, ack 2636678339, win 65535, length 0
>   A > B: Flags [.], ack 1, win 1277, length 0
>   A > B: Flags [P.], seq 1:6, ack 1, win 1277, length 5
>   B > A: Flags [.], ack 6, win 1277, length 0
>   B > A: Flags [F.], seq 1, ack 6, win 1277, length 0
>   A > B: Flags [.], ack 2, win 1277, length 0
> All close()/shutdown(SHUT_RDWR)/shutdown(SHUT_RD) and both SO_LINGER on or
> off give the same trace. While on Linux the same execution gives this:
>   A > B: Flags [S], seq 2879877684, win 65495, length 0
>   B > A: Flags [S.], seq 1538598692, ack 2879877685, win 65483, length 0
>   A > B: Flags [.], ack 1, win 512, length 0
>   A > B: Flags [P.], seq 1:6, ack 1, win 512, length 5
>   B > A: Flags [.], ack 6, win 512, length 0
>   B > A: Flags [R.], seq 1, ack 6, win 512, length 0

Is the situation from RFC 2525 section 2/17 still applicable to our TCP stack?
I.e. does the connection still hold indefinitely for A after B's close() ?

> 2. Sending RST to segment with old sequence SYN-RECEIVED instead of
> acknowledgement
> According to RFC793 page 69: If an incoming segment is not acceptable, an
> acknowledgement should be sent in reply. (here `should` is not capitalized).
> This should be applied to all states including and after SYN-RECEIVED. But
> it's not the case with FreeBSD TCP socket. I found this with manually
> constructed TCP segment:
>   A > B: Flags [S], seq 1, win 8192, length 0
>   B > A: Flags [S.], seq 4054810353, ack 2, win 65535, length 0
>   A > B: Flags [.], ack 1, win 8192, length 0
>   B > A: Flags [R], seq 4054810354, win 0, length 0
> Expected behavior is to send an empty ack:
>   A > B: Flags [S], seq 1, win 8192, length 0
>   B > A: Flags [S.], seq 3620804602, ack 2, win 65495, length 0
>   A > B: Flags [.], ack 1, win 8192, length 0
>   B > A: Flags [.], ack 1, win 65495, length 0
> Which is the case with Linux.
> 
> Does anyone know why these two violations exist? Did FreeBSD choose not to
> comply with the RFC for a specific reason, or is it simply an implementation
> error?

RFC 9293 still does not capitalize "should" here, therefore it is not a
normative requirement. In fact, I vaguely recall that some anti-DDoS systems
check the liveness of host (not being spoofed SYN) by sending out-of-window
packet and expecting RST while main connection is unaffected.

-- 
WBR, @nuclight
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.