Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 18 Sep 2025 12:24:58 +0200
From:      Michael Tuexen <michael.tuexen@lurchi.franken.de>
To:        Tilnel <deng1991816@gmail.com>
Cc:        freebsd-net@freebsd.org
Subject:   Re: Two different places between TCP socket behavior and RFC documents
Message-ID:  <38DCEDDE-7BAB-4A1D-ACB4-6B2E8FCEB6CE@lurchi.franken.de>
In-Reply-To: <CADvKEf-vkJ-eKpwe_-x-z0pUTyx2sZRE3v7%2BZRV7cP_pq7h__w@mail.gmail.com>
References:  <CADvKEf-vkJ-eKpwe_-x-z0pUTyx2sZRE3v7%2BZRV7cP_pq7h__w@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
> On 18. Sep 2025, at 10:50, Tilnel <deng1991816@gmail.com> wrote:
>=20
> Hi,
>=20
> I found two behaviors different with RFC recommendations in FreeBSD =
14.3 TCP
> socket.
>=20
> 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
>=20
> 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.
>=20
> 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
>=20
> Thanks.
>=20




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?38DCEDDE-7BAB-4A1D-ACB4-6B2E8FCEB6CE>