From fde948f488013f4a8911b10eb924f71848ae3f9a Mon Sep 17 00:00:00 2001 From: Gurvinder Singh 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 f5872e07c5..cf472400c7 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 fe6b56bc85..fb0b573d97 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); } /**