Date: Fri, 19 Sep 2025 00:26:47 +0300 From: Vadim Goncharov <vadimnuclight@gmail.com> To: Tilnel <deng1991816@gmail.com> Cc: freebsd-net@freebsd.org Subject: Re: Two different places between TCP socket behavior and RFC documents Message-ID: <20250919002647.367809e7@nuclight.lan> 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 Thu, 18 Sep 2025 16:50:46 +0800 Tilnel <deng1991816@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. > 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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20250919002647.367809e7>