From: Victor Julien Date: Thu, 16 Oct 2014 12:59:38 +0000 (+0200) Subject: stream: improve handling of 3whs packet loss X-Git-Tag: suricata-2.1beta2~60 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F1173%2Fhead;p=thirdparty%2Fsuricata.git stream: improve handling of 3whs packet loss If the 3whs ACK and some data after this is lost, we would get stuck in the 'SYN_RECV' state, where from there each packet might be considered invalid. This patch improves the handling of this case. --- diff --git a/src/stream-tcp.c b/src/stream-tcp.c index 787b774d36..86f995ccd9 100644 --- a/src/stream-tcp.c +++ b/src/stream-tcp.c @@ -1829,6 +1829,42 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p, StreamTcpSetEvent(p, STREAM_3WHS_RIGHT_SEQ_WRONG_ACK_EVASION); return -1; + + /* if we get a packet with a proper ack, but a seq that is beyond + * next_seq but in-window, we probably missed some packets */ + } else if (SEQ_GT(TCP_GET_SEQ(p), ssn->client.next_seq) && + SEQ_LEQ(TCP_GET_SEQ(p),ssn->client.next_win) && + SEQ_EQ(TCP_GET_ACK(p), ssn->server.next_seq)) + { + SCLogDebug("ssn %p: ACK for missing data", ssn); + + if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) { + StreamTcpHandleTimestamp(ssn, p); + } + + StreamTcpUpdateLastAck(ssn, &ssn->server, TCP_GET_ACK(p)); + + ssn->client.next_seq = TCP_GET_SEQ(p) + p->payload_len; + ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale; + + ssn->server.next_win = ssn->server.last_ack + ssn->server.window; + + if (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) { + ssn->client.window = TCP_GET_WINDOW(p); + ssn->server.next_win = ssn->server.last_ack + + ssn->server.window; + /* window scaling for midstream pickups, we can't do much + * other than assume that it's set to the max value: 14 */ + ssn->server.wscale = TCP_WSCALE_MAX; + ssn->client.wscale = TCP_WSCALE_MAX; + ssn->flags |= STREAMTCP_FLAG_SACKOK; + } + + StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED); + SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn); + + StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, + &ssn->client, p, pq); } else { SCLogDebug("ssn %p: wrong seq nr on packet", ssn);