aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/suricata/src/stream-tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/suricata/src/stream-tcp.c')
-rw-r--r--framework/src/suricata/src/stream-tcp.c110
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)));