-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IP stack: TCP FIN handling is incorrect for both local close and peer close #1945
Comments
by Paul Sokolovsky:
Crude fix for this is:
|
by Paul Sokolovsky: Perhaps less crude hack is:
It apparently depends on the fact that each FIN is ORed with ACK. But likely there's even better place to increment sequence number one by one. |
by Paul Sokolovsky: Ok, so here's capture from echo_server w/o any patches like above:
So, Zephyr doesn't acknowledge peer's FIN, instead rushes to send its FIN, peer acknowledges it, but Zephyr doesn't understand it, and aborts with RST instead. |
by Paul Sokolovsky: Ok, so the whole intrigue was how http_server sample runs. Well... It pretends to support HTTP 1.1, while being not compliant with HTTP at all: it doesn't accept any headers after the request line (so I can't even tell it "Connection: close", HTTP1.1, ahem). So, I'd love to be wrong, but looks like a proper, baseline TCP server - which accepts a connection, receives a request, sends a reply and closes connection - was never implemented for Zephyr, or the original issue with which this ticket starts, was spotted. And let me adjust the title - FIN handling is incorrect not in some, but in all cases. In some cases only Wireshark can see that though. |
by Paul Sokolovsky: From https://tools.ietf.org/html/rfc793
The most straightforward interpretation of that is: it's a violation of TCP protocol to send any packet without ACK flag, beyond the initial SYN. |
by Jukka Rissanen: I noticed while implementing HTTP server library, that we do not properly handle the case if we receive ACK | RST packet while being in ESTABLISHED state. The RST flag is just ignored and we do not close the receive context properly which leads to context leak. I have a fix for this case and will send it shortly. |
by Paul Sokolovsky: |
Reported by Paul Sokolovsky:
"Some cases" for me are: MicroPython BSD Sockets prototype (which of course just calls thru to native API), HTTP server sample, net_context received via accept_cb, first HTTP request is recv'ed from it, then HTTP response is sent thru it, then context_put is called. In Wireshark:
So, lone FIN is being sent, which is suspicious on its own (it's known that modern IP stacks prefer to see ACKs on all packets). Drilling into packet:
This packet gets dropped by Linux, so telnet I use to connect just continues to hang after receiving the response, doesn't terminate.
So, my first idea was to see if Linux could actually digest FIN without ACK, so I tried to make sure that ack number is set to 0:
{code:java}
@@ -433,7 +434,12 @@ int net_tcp_prepare_segment(struct net_tcp *tcp, u8_t flags,
segment.src_addr = (struct sockaddr_ptr *)local;
segment.dst_addr = remote;
segment.seq = tcp->send_seq;
+printf("no ack\n");
{code}
Unfortunately, that didn't work - "no ack" was printed, but something else set .ack to non-zero later still.
Ok, making sure that FIN always has ACK:
{code:java}
@@ -416,6 +416,7 @@ int net_tcp_prepare_segment(struct net_tcp *tcp, u8_t flags,
{code}
That worked better, telnet properly terminated. But Linux still worried:
So, in packet 26, Zephyr tries to send ACK to Linux' FIN/ACK, but instead comes out what Wireshark recognizes as TCP keep-alive. Apparently, Linux agrees as it keeps retransmitting its FIN/ACK.
(Imported from Jira ZEP-2104)
The text was updated successfully, but these errors were encountered: