> On 18. Sep 2025, at 10:50, Tilnel <deng1991...@gmail.com> 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.
> 


Reply via email to