diff options
Diffstat (limited to 'framework/src/suricata/src/stream-tcp.c')
-rw-r--r-- | framework/src/suricata/src/stream-tcp.c | 110 |
1 files changed, 79 insertions, 31 deletions
diff --git a/framework/src/suricata/src/stream-tcp.c b/framework/src/suricata/src/stream-tcp.c index 6cde8651..9dce7070 100644 --- a/framework/src/suricata/src/stream-tcp.c +++ b/framework/src/suricata/src/stream-tcp.c @@ -764,8 +764,13 @@ uint32_t StreamTcpGetStreamSize(TcpStream *stream) #define StreamTcpUpdateLastAck(ssn, stream, ack) { \ if (SEQ_GT((ack), (stream)->last_ack)) \ { \ + SCLogDebug("ssn %p: last_ack set to %"PRIu32", moved %u forward", (ssn), (ack), (ack) - (stream)->last_ack); \ + if ((SEQ_LEQ((stream)->last_ack, (stream)->next_seq) && SEQ_GT((ack),(stream)->next_seq))) { \ + SCLogDebug("last_ack just passed next_seq: %u (was %u) > %u", (ack), (stream)->last_ack, (stream)->next_seq); \ + } else { \ + SCLogDebug("next_seq (%u) <> last_ack now %d", (stream)->next_seq, (int)(stream)->next_seq - (ack)); \ + }\ (stream)->last_ack = (ack); \ - SCLogDebug("ssn %p: last_ack set to %"PRIu32, (ssn), (stream)->last_ack); \ StreamTcpSackPruneList((stream)); \ } else { \ SCLogDebug("ssn %p: no update: ack %u, last_ack %"PRIu32", next_seq %u (state %u)", \ @@ -793,6 +798,13 @@ static int StreamTcpPacketIsRetransmission(TcpStream *stream, Packet *p) if (p->payload_len == 0) SCReturnInt(0); + /* retransmission of already partially ack'd data */ + if (SEQ_LT(TCP_GET_SEQ(p), stream->last_ack) && SEQ_GT((TCP_GET_SEQ(p) + p->payload_len), stream->last_ack)) + { + StreamTcpSetEvent(p, STREAM_PKT_RETRANSMISSION); + SCReturnInt(1); + } + /* retransmission of already ack'd data */ if (SEQ_LEQ((TCP_GET_SEQ(p) + p->payload_len), stream->last_ack)) { StreamTcpSetEvent(p, STREAM_PKT_RETRANSMISSION); @@ -805,8 +817,8 @@ static int StreamTcpPacketIsRetransmission(TcpStream *stream, Packet *p) SCReturnInt(2); } - SCLogDebug("seq %u payload_len %u => %u, last_ack %u", TCP_GET_SEQ(p), - p->payload_len, (TCP_GET_SEQ(p) + p->payload_len), stream->last_ack); + SCLogDebug("seq %u payload_len %u => %u, last_ack %u, next_seq %u", TCP_GET_SEQ(p), + p->payload_len, (TCP_GET_SEQ(p) + p->payload_len), stream->last_ack, stream->next_seq); SCReturnInt(0); } @@ -2040,6 +2052,17 @@ static int HandleEstablishedPacketToServer(ThreadVars *tv, TcpSession *ssn, Pack SCLogDebug("ssn %p: ssn->client.next_seq %"PRIu32 " (started before next_seq, ended after)", ssn, ssn->client.next_seq); + /* if next_seq has fallen behind last_ack, we got some catching up to do */ + } else if (SEQ_LT(ssn->client.next_seq, ssn->client.last_ack)) { + ssn->client.next_seq = TCP_GET_SEQ(p) + p->payload_len; + SCLogDebug("ssn %p: ssn->client.next_seq %"PRIu32 + " (next_seq had fallen behind last_ack)", + ssn, ssn->client.next_seq); + } else { + SCLogDebug("ssn %p: no update to ssn->client.next_seq %"PRIu32 + " SEQ %u SEQ+ %u last_ack %u", + ssn, ssn->client.next_seq, + TCP_GET_SEQ(p), TCP_GET_SEQ(p)+p->payload_len, ssn->client.last_ack); } /* in window check */ @@ -2185,6 +2208,17 @@ static int HandleEstablishedPacketToClient(ThreadVars *tv, TcpSession *ssn, Pack SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 " (started before next_seq, ended after)", ssn, ssn->server.next_seq); + /* if next_seq has fallen behind last_ack, we got some catching up to do */ + } else if (SEQ_LT(ssn->server.next_seq, ssn->server.last_ack)) { + ssn->server.next_seq = TCP_GET_SEQ(p) + p->payload_len; + SCLogDebug("ssn %p: ssn->server.next_seq %"PRIu32 + " (next_seq had fallen behind last_ack)", + ssn, ssn->server.next_seq); + } else { + SCLogDebug("ssn %p: no update to ssn->server.next_seq %"PRIu32 + " SEQ %u SEQ+ %u last_ack %u", + ssn, ssn->server.next_seq, + TCP_GET_SEQ(p), TCP_GET_SEQ(p)+p->payload_len, ssn->server.last_ack); } if (zerowindowprobe) { @@ -2284,8 +2318,9 @@ static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p, ssn->server.next_seq); ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale; - StreamTcpUpdateLastAck(ssn, &ssn->server, - StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p))); + if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0) + StreamTcpUpdateLastAck(ssn, &ssn->server, + StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p))); StreamTcpUpdateLastAck(ssn, &ssn->client, StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p))); @@ -2315,8 +2350,9 @@ static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p, ssn->server.next_seq); ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale; - StreamTcpUpdateLastAck(ssn, &ssn->client, - StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p))); + if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0) + StreamTcpUpdateLastAck(ssn, &ssn->client, + StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p))); StreamTcpUpdateLastAck(ssn, &ssn->server, StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p))); @@ -2609,8 +2645,9 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, ssn); if (PKT_IS_TOSERVER(p)) { - StreamTcpUpdateLastAck(ssn, &ssn->server, - StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p))); + if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0) + StreamTcpUpdateLastAck(ssn, &ssn->server, + StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p))); StreamTcpUpdateLastAck(ssn, &ssn->client, StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p))); @@ -2622,8 +2659,9 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p, pq); } else { - StreamTcpUpdateLastAck(ssn, &ssn->client, - StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p))); + if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0) + StreamTcpUpdateLastAck(ssn, &ssn->client, + StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p))); StreamTcpUpdateLastAck(ssn, &ssn->server, StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p))); @@ -3063,8 +3101,9 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p, ssn); if (PKT_IS_TOSERVER(p)) { - StreamTcpUpdateLastAck(ssn, &ssn->server, - StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p))); + if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0) + StreamTcpUpdateLastAck(ssn, &ssn->server, + StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p))); StreamTcpUpdateLastAck(ssn, &ssn->client, StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p))); @@ -3076,8 +3115,9 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p, StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p, pq); } else { - StreamTcpUpdateLastAck(ssn, &ssn->client, - StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p))); + if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0) + StreamTcpUpdateLastAck(ssn, &ssn->client, + StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p))); StreamTcpUpdateLastAck(ssn, &ssn->server, StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p))); @@ -3369,8 +3409,9 @@ static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *p, ssn); if (PKT_IS_TOSERVER(p)) { - StreamTcpUpdateLastAck(ssn, &ssn->server, - StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p))); + if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0) + StreamTcpUpdateLastAck(ssn, &ssn->server, + StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p))); StreamTcpUpdateLastAck(ssn, &ssn->client, StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p))); @@ -3382,8 +3423,9 @@ static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *p, StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p, pq); } else { - StreamTcpUpdateLastAck(ssn, &ssn->client, - StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p))); + if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0) + StreamTcpUpdateLastAck(ssn, &ssn->client, + StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p))); StreamTcpUpdateLastAck(ssn, &ssn->server, StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p))); @@ -3549,8 +3591,9 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p, ssn); if (PKT_IS_TOSERVER(p)) { - StreamTcpUpdateLastAck(ssn, &ssn->server, - StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p))); + if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0) + StreamTcpUpdateLastAck(ssn, &ssn->server, + StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p))); StreamTcpUpdateLastAck(ssn, &ssn->client, StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p))); @@ -3562,8 +3605,9 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p, StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p, pq); } else { - StreamTcpUpdateLastAck(ssn, &ssn->client, - StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p))); + if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0) + StreamTcpUpdateLastAck(ssn, &ssn->client, + StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p))); StreamTcpUpdateLastAck(ssn, &ssn->server, StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p))); @@ -3840,8 +3884,9 @@ static int StreamTcpPacketStateLastAck(ThreadVars *tv, Packet *p, ssn); if (PKT_IS_TOSERVER(p)) { - StreamTcpUpdateLastAck(ssn, &ssn->server, - StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p))); + if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0) + StreamTcpUpdateLastAck(ssn, &ssn->server, + StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p))); StreamTcpUpdateLastAck(ssn, &ssn->client, StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p))); @@ -3853,8 +3898,9 @@ static int StreamTcpPacketStateLastAck(ThreadVars *tv, Packet *p, StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p, pq); } else { - StreamTcpUpdateLastAck(ssn, &ssn->client, - StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p))); + if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0) + StreamTcpUpdateLastAck(ssn, &ssn->client, + StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p))); StreamTcpUpdateLastAck(ssn, &ssn->server, StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p))); @@ -3965,8 +4011,9 @@ static int StreamTcpPacketStateTimeWait(ThreadVars *tv, Packet *p, ssn); if (PKT_IS_TOSERVER(p)) { - StreamTcpUpdateLastAck(ssn, &ssn->server, - StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p))); + if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->server, p) == 0) + StreamTcpUpdateLastAck(ssn, &ssn->server, + StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_ACK(p))); StreamTcpUpdateLastAck(ssn, &ssn->client, StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_SEQ(p))); @@ -3978,8 +4025,9 @@ static int StreamTcpPacketStateTimeWait(ThreadVars *tv, Packet *p, StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn, &ssn->client, p, pq); } else { - StreamTcpUpdateLastAck(ssn, &ssn->client, - StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p))); + if ((p->tcph->th_flags & TH_ACK) && StreamTcpValidateAck(ssn, &ssn->client, p) == 0) + StreamTcpUpdateLastAck(ssn, &ssn->client, + StreamTcpResetGetMaxAck(&ssn->client, TCP_GET_ACK(p))); StreamTcpUpdateLastAck(ssn, &ssn->server, StreamTcpResetGetMaxAck(&ssn->server, TCP_GET_SEQ(p))); |