1
0
mirror of https://github.com/elua/elua.git synced 2025-01-25 01:02:54 +08:00

Lost SYNACK causes connection reset

==================
From: Raimondas Sasnauskas <raimondas.sasnauskas@cs.rwth-aachen.de>
Date: Sun, Sep 20, 2009 at 1:29 PM
Subject: Re: RE: Re: RE: Re: Re: RE: Bug (?) in uip TCP/IP stack: lost SYNACK causes connection reset

OK, here I'm proposing the following patch (see git diff attached).

Again the problem we face here is the subsequent SYN arriving in
UIP_SYN_RCVD state after the SYNACK packet was lost.  First, to avoid
other issues,  suggest to reset any _active_ connection where a SYN
arrives in a state != UIP_SYN_RCVD.

==================

This is a combination of the patch submitted by Raimondas Sasnauskas and
the patch applied by Oliver Schmidt to Contiki

===================
Original bug report
===================

 From: Raimondas Sasnauskas
       <raimondas.sasnauskas@cs.rwth-aachen.de>
 Subject: Bug (?) in uip TCP/IP stack: lost SYNACK causes
          connection reset
 Date: 2009-09-02 19:07:51 GMT

 Hi all,

 I've found the following issue in the TCP (UIP_ACTIVE_OPEN)
 connection establishment phase leading to connection failure.
 This happens whe the SYNACK packet gets lost during the TCP
 3-way handshake.

 Client: SYN
 Server: SYNACK (this packet gets lost)
 Client: SYN (retransmission)
 Server: ACK (<-- server thinks it's data?)
 Client: RESET (correct, no SYNACK received yet)
 Server: ABORT (got reset, aborting connection)

 I do not have a patch/workaround yet, but I think that
 correctly handling incoming TCP_SYN packets in UIP_SYN_RCVD
 state would fix this issue.

 http://article.gmane.org/gmane.network.uip.user/1506
This commit is contained in:
Raimondas Sasnauskas 2011-10-04 21:02:16 -05:00 committed by James Snyder
parent c388c3f3b3
commit eeab1025e2

View File

@ -1271,6 +1271,10 @@ uip_process(u8_t flag)
BUF->destport == uip_connr->lport && BUF->destport == uip_connr->lport &&
BUF->srcport == uip_connr->rport && BUF->srcport == uip_connr->rport &&
uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) { uip_ipaddr_cmp(BUF->srcipaddr, uip_connr->ripaddr)) {
if ((uip_connr->tcpstateflags != UIP_SYN_RCVD) &&
(BUF->flags & TCP_CTL) == TCP_SYN) {
goto reset;
}
goto found; goto found;
} }
} }
@ -1482,9 +1486,13 @@ uip_process(u8_t flag)
/* First, check if the sequence number of the incoming packet is /* First, check if the sequence number of the incoming packet is
what we're expecting next. If not, we send out an ACK with the what we're expecting next. If not, we send out an ACK with the
correct numbers in. */ correct numbers in, unless we are in the SYN_RCVD state and
if(!(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) && receive a SYN, in which case we should retransmit our SYNACK
((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)))) { (which is done futher down). */
if(!((((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_SENT) &&
((BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK))) ||
(((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_SYN_RCVD) &&
((BUF->flags & TCP_CTL) == TCP_SYN)))) {
if((uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) && if((uip_len > 0 || ((BUF->flags & (TCP_SYN | TCP_FIN)) != 0)) &&
(BUF->seqno[0] != uip_connr->rcv_nxt[0] || (BUF->seqno[0] != uip_connr->rcv_nxt[0] ||
BUF->seqno[1] != uip_connr->rcv_nxt[1] || BUF->seqno[1] != uip_connr->rcv_nxt[1] ||
@ -1561,6 +1569,10 @@ uip_process(u8_t flag)
UIP_APPCALL(); UIP_APPCALL();
goto appsend; goto appsend;
} }
/* We need to retransmit the SYNACK */
if((BUF->flags & TCP_CTL) == TCP_SYN) {
goto tcp_send_synack;
}
goto drop; goto drop;
#if UIP_ACTIVE_OPEN #if UIP_ACTIVE_OPEN
case UIP_SYN_SENT: case UIP_SYN_SENT: