From db2dbaaf40a911200849b235d8408788fa379276 Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Tue, 29 Dec 2020 20:36:26 +0100 Subject: [PATCH] stream/midstream: handle packet loss after SYN/ACK --- src/stream-tcp.c | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/src/stream-tcp.c b/src/stream-tcp.c index 94a60184c2..ac0341f089 100644 --- a/src/stream-tcp.c +++ b/src/stream-tcp.c @@ -2045,12 +2045,38 @@ 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 */ + /* SYN/ACK followed by more TOCLIENT suggesting packet loss */ + } else if (PKT_IS_TOCLIENT(p) && !StreamTcpInlineMode() && + SEQ_GT(TCP_GET_SEQ(p), ssn->client.next_seq) && + SEQ_GT(TCP_GET_ACK(p), ssn->client.last_ack)) { + SCLogDebug("ssn %p: ACK for missing data", ssn); + + if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) { + StreamTcpHandleTimestamp(ssn, p); + } + + StreamTcpUpdateLastAck(ssn, &ssn->client, TCP_GET_ACK(p)); + + ssn->server.next_seq = TCP_GET_SEQ(p) + p->payload_len; + SCLogDebug("ssn %p: ACK for missing data: ssn->server.next_seq %u", ssn, + ssn->server.next_seq); + ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale; + + ssn->client.next_win = ssn->client.last_ack + ssn->client.window; + + ssn->client.window = TCP_GET_WINDOW(p); + ssn->server.next_win = ssn->server.last_ack + ssn->server.window; + + StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED); + SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn); + + StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->server, p, pq); + + /* 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)) - { + 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) { @@ -2084,10 +2110,9 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p, /* toclient packet: after having missed the 3whs's final ACK */ } else if ((ack_indicates_missed_3whs_ack_packet || - (ssn->flags & STREAMTCP_FLAG_TCP_FAST_OPEN)) && - SEQ_EQ(TCP_GET_ACK(p), ssn->client.last_ack) && - SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq)) - { + (ssn->flags & STREAMTCP_FLAG_TCP_FAST_OPEN)) && + SEQ_EQ(TCP_GET_ACK(p), ssn->client.last_ack) && + SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq)) { if (ack_indicates_missed_3whs_ack_packet) { SCLogDebug("ssn %p: packet fits perfectly after a missed 3whs-ACK", ssn); } else { -- 2.47.2