lwip-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lwip-devel] TCP/IP - Connection attempt refused for TIME_WAIT pcbs even


From: Benjamin Kalytta
Subject: [lwip-devel] TCP/IP - Connection attempt refused for TIME_WAIT pcbs even if seqno is valid?
Date: Mon, 12 Jul 2021 13:03:14 +0000

Hello LwIp users,

I've a strange problem regarding TCP/IP connections. I don't know if it is a 
bug or it is intended (if so why).

We are running a simple webserver on an STM32F7 system. We have encountered 
problems with certain web browsers (especially Chrome) when retrieving content. 
It seems to be the case whenever the local TCP/IP port is reused too quickly 
(several 10th of ms) by the browser/operating system connection is 
refused/reset since the PCB is still in TIME_WAIT state on the server side (in 
LWIP stack) which is fine and understandable.

However, according to the specification, TIME_WAIT should be left as soon as 
the new sequence number is greater than the last one used.

See https://www.freesoft.org/CIE/RFC/1122/99.htm 4.2.2.13 Closing a Connection: 
RFC-793 Section 3.5:

"However, it MAY accept a new SYN from the remote TCP to reopen the connection 
directly from TIME-WAIT state, if it:
- assigns its initial sequence number for the new connection to be larger than 
the largest sequence number it used on the previous connection incarnation[...]"

I'm not 100% sure, but I think I found the code snippet responsible dealing 
with SYN while in TIME_WAIT:
[Version LWIP 2.1.2]

738 static void
739 tcp_timewait_input(struct tcp_pcb *pcb)
{
  /* RFC 1337: in TIME_WAIT, ignore RST and ACK FINs + any 'acceptable' 
segments */
  /* RFC 793 3.9 Event Processing - Segment Arrives:
   * - first check sequence number - we skip that one in TIME_WAIT (always
   *   acceptable since we only send ACKs)
   * - second check the RST bit (... return) */
  if (flags & TCP_RST) {
    return;
  }

  LWIP_ASSERT("tcp_timewait_input: invalid pcb", pcb != NULL);

  /* - fourth, check the SYN bit, */
  if (flags & TCP_SYN) {
    /* If an incoming segment is not acceptable, an acknowledgment
       should be sent in reply */
756    if (TCP_SEQ_BETWEEN(seqno, pcb->rcv_nxt, pcb->rcv_nxt + pcb->rcv_wnd)) {
      /* If the SYN is in the window it is an error, send a reset */
      tcp_rst(pcb, ackno, seqno + tcplen, ip_current_dest_addr(),
              ip_current_src_addr(), tcphdr->dest, tcphdr->src);
      return;
761    }
  } else if (flags & TCP_FIN) {
    /* - eighth, check the FIN bit: Remain in the TIME-WAIT state.
         Restart the 2 MSL time-wait timeout.*/
    pcb->tmr = tcp_ticks;
  }

  if ((tcplen > 0)) {
    /* Acknowledge data, FIN or out-of-window SYN */
770    tcp_ack_now(pcb);
    tcp_output(pcb);
  }
return;
774 }

Here (line 758) only a RST is sent if sequence is not valid, otherwise ACK is 
sent (line 770). I either case tcp_input processing is aborted which means 
connection is never accepted as per RFC 793 chapter 4.2.2.13. Am I wrong here? 
Are there any fixes for that issue or any other solutions?

With Kind Regards,
Benjamin Kalytta




reply via email to

[Prev in Thread] Current Thread [Next in Thread]