From 92863f005f15f2c4d362bcef8beb884ab6faf13e Mon Sep 17 00:00:00 2001
From: Gurvinder Singh <gurvindersinghdahiya@gmail.com>
Date: Wed, 6 Jan 2010 09:32:04 +0530
Subject: [PATCH] bug 41 patch

---
 src/stream-tcp-reassemble.c |   40 ++++++++++++++++------
 src/stream-tcp.c            |   76 +++++++++++++++++++++++++++++++++++++++---
 2 files changed, 99 insertions(+), 17 deletions(-)

diff --git a/src/stream-tcp-reassemble.c b/src/stream-tcp-reassemble.c
index f5872e0..cf47240 100644
--- a/src/stream-tcp-reassemble.c
+++ b/src/stream-tcp-reassemble.c
@@ -580,7 +580,17 @@ static int HandleSegmentStartsBeforeListSegment(TcpStream *stream,
             if (SEQ_GT(list_seg->seq, (list_seg->prev->seq +
                                    list_seg->prev->payload_len)))
             {
-                packet_length = list_seg->payload_len + (list_seg->seq - seg->seq);
+                SCLogDebug("list_seg->prev %p list_seg->prev->seq %"PRIu32" "
+                           "list_seg->prev->payload_len %"PRIu16"",
+                            list_seg->prev, list_seg->prev->seq,
+                            list_seg->prev->payload_len);
+                if (SEQ_LT(list_seg->prev->seq, seg->seq)) {
+                    packet_length = list_seg->payload_len + (list_seg->seq -
+                                                                    seg->seq);
+                } else {
+                    packet_length = list_seg->payload_len + (list_seg->seq -
+                           (list_seg->prev->seq + list_seg->prev->payload_len));
+                }
 
                 TcpSegment *new_seg = StreamTcpGetSegment(packet_length);
                 if (new_seg == NULL) {
@@ -937,6 +947,7 @@ static int HandleSegmentStartsAfterListSegment(TcpStream *stream,
                                                TcpSegment *list_seg,
                                                TcpSegment *seg)
 {
+    SCEnter();
     uint16_t overlap = 0;
     uint16_t packet_length;
     char end_before = FALSE;
@@ -984,7 +995,7 @@ static int HandleSegmentStartsAfterListSegment(TcpStream *stream,
         overlap = (list_seg->seq + list_seg->payload_len) - seg->seq;
         end_after = TRUE;
 
-        SCLogDebug("starts beyond list seq, before list end, ends at list end: "
+        SCLogDebug("starts beyond list seq, ends after list seq end: "
             "seg->seq %" PRIu32 ", seg->payload_len %"PRIu16" (%"PRIu32") "
             "list_seg->seq %" PRIu32 ", list_seg->payload_len %" PRIu32 " "
             "(%"PRIu32") overlap is %" PRIu32 "", seg->seq, seg->payload_len,
@@ -1033,7 +1044,7 @@ static int HandleSegmentStartsAfterListSegment(TcpStream *stream,
                     uint16_t idx = segment_pool_idx[packet_length];
                     SCLogError(SC_ERR_POOL_EMPTY, "segment_pool[%"PRIu16"] is"
                                " empty", idx);
-                    return -1;
+                    SCReturnInt(-1);
                 }
                 new_seg->payload_len = packet_length;
                 new_seg->seq = list_seg->seq + list_seg->payload_len;
@@ -1044,8 +1055,9 @@ static int HandleSegmentStartsAfterListSegment(TcpStream *stream,
                 list_seg->next = new_seg;
 
                 SCLogDebug("new_seg %p, new_seg->next %p, new_seg->prev %p, "
-                           "list_seg->next %p", new_seg, new_seg->next,
-                           new_seg->prev, list_seg->next);
+                           "list_seg->next %p new_seg->seq %"PRIu32"", new_seg,
+                            new_seg->next, new_seg->prev, list_seg->next,
+                            new_seg->seq);
 
                 StreamTcpSegmentDataReplace(new_seg, seg, new_seg->seq,
                                             new_seg->payload_len);
@@ -1089,9 +1101,9 @@ static int HandleSegmentStartsAfterListSegment(TcpStream *stream,
                 break;
         }
         if (end_before == TRUE || end_same == TRUE || handle_beyond == FALSE)
-            return 1;
+            SCReturnInt(1);
     }
-    return 0;
+    SCReturnInt(0);
 }
 
 int StreamTcpReassembleHandleSegmentHandleData(TcpSession *ssn,
@@ -1232,8 +1244,9 @@ int StreamTcpReassembleHandleSegmentUpdateACK (TcpReassemblyThreadCtx *ra_ctx,
          * because we've reassembled up to the ra_base_seq point already,
          * so we won't do anything with segments before it anyway. */
         SCLogDebug("checking for pre ra_base_seq %"PRIu32" seg %p seq %"PRIu32""
-                   " len %"PRIu16", combined %"PRIu32"", stream->ra_base_seq,
-                   seg, seg->seq, seg->payload_len, seg->seq+seg->payload_len);
+                   " len %"PRIu16", combined %"PRIu32" and stream->last_ack "
+                   "%"PRIu32"", stream->ra_base_seq, seg, seg->seq,
+                    seg->payload_len, seg->seq+seg->payload_len, stream->last_ack);
 
         /** \todo we should probably not even insert them into the seglist */
         if (SEQ_LEQ((seg->seq + seg->payload_len), (stream->ra_base_seq+1))) {
@@ -1339,7 +1352,9 @@ int StreamTcpReassembleHandleSegmentUpdateACK (TcpReassemblyThreadCtx *ra_ctx,
                     payload_len = seg->payload_len;
                 }
             }
-
+            SCLogDebug("payload_offset is %"PRIu16", payload_len is %"PRIu16""
+                       " and stream->last_ack is %"PRIu32"", payload_offset,
+                        payload_len, stream->last_ack);
             /* copy the data into the smsg */
             uint16_t copy_size = sizeof (smsg->data.data) - smsg_offset;
             if (copy_size > payload_len) {
@@ -1348,7 +1363,7 @@ int StreamTcpReassembleHandleSegmentUpdateACK (TcpReassemblyThreadCtx *ra_ctx,
             if (SCLogDebugEnabled()) {
                 BUG_ON(copy_size > sizeof(smsg->data.data));
             }
-
+            SCLogDebug("copy_size is %"PRIu16"", copy_size);
             memcpy(smsg->data.data + smsg_offset, seg->payload + payload_offset,
                     copy_size);
             smsg_offset += copy_size;
@@ -1370,6 +1385,9 @@ int StreamTcpReassembleHandleSegmentUpdateACK (TcpReassemblyThreadCtx *ra_ctx,
 
                 payload_offset += copy_size;
                 payload_len -= copy_size;
+                SCLogDebug("payload_offset is %"PRIu16", seg->payload_len is "
+                           "%"PRIu16" and stream->last_ack is %"PRIu32"",
+                            payload_offset, seg->payload_len, stream->last_ack);
                 if (SCLogDebugEnabled()) {
                     BUG_ON(payload_offset > seg->payload_len);
                 }
diff --git a/src/stream-tcp.c b/src/stream-tcp.c
index fe6b56b..fb0b573 100644
--- a/src/stream-tcp.c
+++ b/src/stream-tcp.c
@@ -2044,8 +2044,18 @@ static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *p,
 static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
                                          StreamTcpThread *stt, TcpSession *ssn)
 {
+    SCEnter();
     if (ssn == NULL)
-        return -1;
+        SCReturnInt(-1);
+    if (PKT_IS_TOCLIENT(p)) {
+                SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
+                           "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
+                            TCP_GET_SEQ(p), TCP_GET_ACK(p));
+    } else {
+         SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
+                           "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
+                            TCP_GET_SEQ(p), TCP_GET_ACK(p));
+    }
 
     switch(p->tcph->th_flags) {
         case TH_FIN:
@@ -2053,7 +2063,7 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
 
             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
                 if (!ValidTimestamp(ssn, p))
-                    return -1;
+                    SCReturnInt(-1);
             }
 
             if (PKT_IS_TOCLIENT(p)) {
@@ -2068,7 +2078,7 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
                     SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
                                " != %" PRIu32 " from stream", ssn,
                                 TCP_GET_SEQ(p), ssn->server.next_seq);
-                    return -1;
+                    SCReturnInt(-1);
                 }
 
                 StreamTcpPacketSetState(p, ssn, TCP_LAST_ACK);
@@ -2084,12 +2094,40 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
                 SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
                            "%" PRIu32 "", ssn, ssn->server.next_seq,
                            ssn->client.last_ack);
+            } else {
+                SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
+                           "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
+                            TCP_GET_SEQ(p), TCP_GET_ACK(p));
+
+                if (SEQ_LT(TCP_GET_SEQ(p), ssn->client.next_seq) ||
+                        SEQ_GT(TCP_GET_SEQ(p), (ssn->client.last_ack +
+                                                         ssn->client.window)))
+                {
+                    SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
+                               " != %" PRIu32 " from stream", ssn,
+                                TCP_GET_SEQ(p), ssn->client.next_seq);
+                    SCReturnInt(-1);
+                }
+
+                StreamTcpPacketSetState(p, ssn, TCP_LAST_ACK);
+                SCLogDebug("ssn %p: state changed to TCP_LAST_ACK", ssn);
+                ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
+
+                if (SEQ_GT(TCP_GET_ACK(p),ssn->server.last_ack))
+                    ssn->server.last_ack = TCP_GET_ACK(p);
+
+                if (!(ssn->flags & STREAMTCP_FLAG_NOSERVER_REASSEMBLY))
+                    StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn,
+                                                          &ssn->client, p);
+                SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
+                           "%" PRIu32 "", ssn, ssn->client.next_seq,
+                           ssn->server.last_ack);
             }
             break;
         case TH_ACK:
             if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
                 if (!ValidTimestamp(ssn, p))
-                    return -1;
+                    SCReturnInt(-1);
             }
 
             if (PKT_IS_TOCLIENT(p)) {
@@ -2104,7 +2142,7 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
                     SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
                                " != %" PRIu32 " from stream", ssn,
                                 TCP_GET_SEQ(p), ssn->server.next_seq);
-                    return -1;
+                    SCReturnInt(-1);
                 }
                 ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
 
@@ -2117,12 +2155,38 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
                 SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
                            "%" PRIu32 "", ssn, ssn->server.next_seq,
                            ssn->client.last_ack);
+            } else {
+                SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
+                           "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
+                            TCP_GET_SEQ(p), TCP_GET_ACK(p));
+
+                if (SEQ_LT(TCP_GET_SEQ(p), ssn->client.next_seq) ||
+                        SEQ_GT(TCP_GET_SEQ(p), (ssn->client.last_ack +
+                                                         ssn->client.window)))
+                {
+                    SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
+                               " != %" PRIu32 " from stream", ssn,
+                                TCP_GET_SEQ(p), ssn->client.next_seq);
+                    SCReturnInt(-1);
+                }
+                ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
+
+                if (SEQ_GT(TCP_GET_ACK(p),ssn->server.last_ack))
+                    ssn->server.last_ack = TCP_GET_ACK(p);
+
+                if (!(ssn->flags & STREAMTCP_FLAG_NOSERVER_REASSEMBLY))
+                    StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn,
+                                                          &ssn->client, p);
+                SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK "
+                           "%" PRIu32 "", ssn, ssn->client.next_seq,
+                           ssn->server.last_ack);
             }
+            break;
         default:
             SCLogDebug("ssn %p: default case", ssn);
             break;
     }
-    return 0;
+    SCReturnInt(0);
 }
 
 /**
-- 
1.6.0.4

