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

Michael Tuexen <[email protected]>
Newsgroups gmane.os.freebsd.devel.net
Message-ID <[email protected]>
> On 18. Sep 2025, at 10:50, 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.
I agree that FreeBSD is inconsistent here. It reacts different if data is
received after the reading end is closed or before.
I don't know why it is that way, but it is there for a long time...
I plan to fix this.
> 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
> 
> 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
I am not sure which scenario are you considering. Could you provide SEG.SEQ
for the this TCP segment?
> 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?
I overall intention is to be RFC compliant...

Best regards
Michael
> 
> Thanks.
>
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.