]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
stream: improve handling of 3whs packet loss 1173/head
authorVictor Julien <victor@inliniac.net>
Thu, 16 Oct 2014 12:59:38 +0000 (14:59 +0200)
committerVictor Julien <victor@inliniac.net>
Wed, 22 Oct 2014 14:46:06 +0000 (16:46 +0200)
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.

src/stream-tcp.c

index 787b774d36fac5116c1d47b9dd34be89fcb5fef7..86f995ccd9bc44d7ba0f846dd767cebe10f950e1 100644 (file)
@@ -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);