From d8433c72558ce7772da4e18a9bc9b4cc016b4eb7 Mon Sep 17 00:00:00 2001 From: Gurvinder Singh Date: Wed, 23 Dec 2009 04:27:31 +0530 Subject: [PATCH] fixed-pool-error-and-tcp-state-transition --- src/app-layer-parser.c | 2 +- src/stream-tcp-reassemble.c | 588 ++++++++++++++------- src/stream-tcp.c | 983 ++++++++++++++++++++++++------------ src/stream-tcp.h | 4 +- src/util-error.c | 3 + src/util-error.h | 3 + 6 files changed, 1088 insertions(+), 495 deletions(-) diff --git a/src/app-layer-parser.c b/src/app-layer-parser.c index 488164f101..62783e4675 100644 --- a/src/app-layer-parser.c +++ b/src/app-layer-parser.c @@ -95,7 +95,7 @@ static int AlpStoreField(AppLayerParserResult *output, uint16_t idx, AppLayerParserResultElmt *e = AlpGetResultElmt(); if (e == NULL) { - SCLogError(SC_INVALID_ARGUMENT, " App layer pool returned NULL"); + SCLogError(SC_ERR_POOL_EMPTY, "App layer \"al_result_pool\" is empty"); SCReturnInt(-1); } diff --git a/src/stream-tcp-reassemble.c b/src/stream-tcp-reassemble.c index 8aee4a23f4..34c13a3ade 100644 --- a/src/stream-tcp-reassemble.c +++ b/src/stream-tcp-reassemble.c @@ -43,9 +43,12 @@ static uint64_t segment_pool_memcnt = 0; #endif /* prototypes */ -static int HandleSegmentStartsBeforeListSegment(TcpStream *, TcpSegment *, TcpSegment *, uint8_t); -static int HandleSegmentStartsAtSameListSegment(TcpStream *, TcpSegment *, TcpSegment *, uint8_t); -static int HandleSegmentStartsAfterListSegment(TcpStream *, TcpSegment *, TcpSegment *, uint8_t); +static int HandleSegmentStartsBeforeListSegment(TcpStream *, TcpSegment *, + TcpSegment *, uint8_t); +static int HandleSegmentStartsAtSameListSegment(TcpStream *, TcpSegment *, + TcpSegment *, uint8_t); +static int HandleSegmentStartsAfterListSegment(TcpStream *, TcpSegment *, + TcpSegment *, uint8_t); void StreamTcpSegmentDataReplace(TcpSegment *, TcpSegment *, uint32_t, uint16_t); void StreamTcpSegmentDataCopy(TcpSegment *, TcpSegment *); TcpSegment* StreamTcpGetSegment(uint16_t); @@ -94,8 +97,11 @@ void TcpSegmentPoolFree(void *ptr) { * data segment we receive, which would be a large performance penalty. * The cost is in memory of course. */ #define segment_pool_num 8 -static uint16_t segment_pool_pktsizes[segment_pool_num] = {4, 16, 112, 248, 512, 768, 1448, 0xffff}; -static uint16_t segment_pool_poolsizes[segment_pool_num] = {2048, 3072, 3072, 3072, 3072, 4096, 8192, 512}; +static uint16_t segment_pool_pktsizes[segment_pool_num] = {4, 16, 112, 248, 512, + 768, 1448, 0xffff}; +static uint16_t segment_pool_poolsizes[segment_pool_num] = {2048, 3072, 3072, + 3072, 3072, 8192, + 8192, 512}; static Pool *segment_pool[segment_pool_num]; static SCMutex segment_pool_mutex[segment_pool_num]; #ifdef DEBUG @@ -105,14 +111,20 @@ static uint64_t segment_pool_cnt = 0; /* index to the right pool for all packet sizes. */ static uint16_t segment_pool_idx[65536]; /* O(1) lookups of the pool */ -int StreamTcpReassembleInit(char quiet) { +int StreamTcpReassembleInit(char quiet) +{ StreamMsgQueuesInit(); #ifdef DEBUG SCMutexInit(&segment_pool_memuse_mutex, NULL); #endif uint16_t u16 = 0; - for (u16 = 0; u16 < segment_pool_num; u16++) { - segment_pool[u16] = PoolInit(segment_pool_poolsizes[u16], segment_pool_poolsizes[u16] / 8, TcpSegmentPoolAlloc, (void *) & segment_pool_pktsizes[u16], TcpSegmentPoolFree); + for (u16 = 0; u16 < segment_pool_num; u16++) + { + segment_pool[u16] = PoolInit(segment_pool_poolsizes[u16], + segment_pool_poolsizes[u16] / 8, + TcpSegmentPoolAlloc, (void *) & + segment_pool_pktsizes[u16], + TcpSegmentPoolFree); SCMutexInit(&segment_pool_mutex[u16], NULL); } @@ -136,12 +148,17 @@ int StreamTcpReassembleInit(char quiet) { return 0; } -void StreamTcpReassembleFree(char quiet) { +void StreamTcpReassembleFree(char quiet) +{ uint16_t u16 = 0; for (u16 = 0; u16 < segment_pool_num; u16++) { if (quiet == FALSE) { PoolPrintSaturation(segment_pool[u16]); - SCLogDebug("segment_pool[u16]->empty_list_size %"PRIu32", segment_pool[u16]->alloc_list_size %"PRIu32", alloced %"PRIu32"", segment_pool[u16]->empty_list_size, segment_pool[u16]->alloc_list_size, segment_pool[u16]->allocated); + SCLogDebug("segment_pool[u16]->empty_list_size %"PRIu32", " + "segment_pool[u16]->alloc_list_size %"PRIu32", alloced " + "%"PRIu32"", segment_pool[u16]->empty_list_size, + segment_pool[u16]->alloc_list_size, + segment_pool[u16]->allocated); } PoolFree(segment_pool[u16]); @@ -157,7 +174,8 @@ void StreamTcpReassembleFree(char quiet) { StreamMsgQueuesDeinit(quiet); } -TcpReassemblyThreadCtx *StreamTcpReassembleInitThreadCtx(void) { +TcpReassemblyThreadCtx *StreamTcpReassembleInitThreadCtx(void) +{ TcpReassemblyThreadCtx *ra_ctx = malloc(sizeof(TcpReassemblyThreadCtx)); if (ra_ctx == NULL) { return NULL; @@ -169,7 +187,8 @@ TcpReassemblyThreadCtx *StreamTcpReassembleInitThreadCtx(void) { return ra_ctx; } -void StreamTcpReassembleFreeThreadCtx(TcpReassemblyThreadCtx *ra_ctx) { +void StreamTcpReassembleFreeThreadCtx(TcpReassemblyThreadCtx *ra_ctx) +{ if (ra_ctx->stream_q != NULL) StreamMsgQueueFree(ra_ctx->stream_q); @@ -178,7 +197,8 @@ void StreamTcpReassembleFreeThreadCtx(TcpReassemblyThreadCtx *ra_ctx) { free(ra_ctx); } -void PrintList2(TcpSegment *seg) { +void PrintList2(TcpSegment *seg) +{ TcpSegment *prev_seg = NULL; if (seg == NULL) @@ -188,21 +208,28 @@ void PrintList2(TcpSegment *seg) { while (seg != NULL) { if (SEQ_LT(next_seq,seg->seq)) { - SCLogDebug("missing segment(s) for %" PRIu32 " bytes of data", (seg->seq - next_seq)); + SCLogDebug("missing segment(s) for %" PRIu32 " bytes of data", + (seg->seq - next_seq)); } - SCLogDebug("seg %10"PRIu32" len %" PRIu16 ", seg %p, prev %p, next %p", seg->seq, seg->payload_len, seg, seg->prev, seg->next); + SCLogDebug("seg %10"PRIu32" len %" PRIu16 ", seg %p, prev %p, next %p", + seg->seq, seg->payload_len, seg, seg->prev, seg->next); if (seg->prev != NULL && SEQ_LT(seg->seq,seg->prev->seq)) { - SCLogDebug("inconsistant list: SEQ_LT(seg->seq,seg->prev->seq)) == TRUE, seg->seq %" PRIu32 ", seg->prev->seq %" PRIu32 "", seg->seq, seg->prev->seq); + SCLogDebug("inconsistant list: SEQ_LT(seg->seq,seg->prev->seq)) ==" + " TRUE, seg->seq %" PRIu32 ", seg->prev->seq %" PRIu32 "" + "", seg->seq, seg->prev->seq); } if (SEQ_LT(seg->seq,next_seq)) { - SCLogDebug("inconsistant list: SEQ_LT(seg->seq,next_seq)) == TRUE, seg->seq %" PRIu32 ", next_seq %" PRIu32 "", seg->seq, next_seq); + SCLogDebug("inconsistant list: SEQ_LT(seg->seq,next_seq)) == TRUE, " + "seg->seq %" PRIu32 ", next_seq %" PRIu32 "", seg->seq, + next_seq); } if (prev_seg != seg->prev) { - SCLogDebug("inconsistant list: prev_seg %p != seg->prev %p", prev_seg, seg->prev); + SCLogDebug("inconsistant list: prev_seg %p != seg->prev %p", + prev_seg, seg->prev); } next_seq = seg->seq + seg->payload_len; @@ -212,7 +239,8 @@ void PrintList2(TcpSegment *seg) { } } -void PrintList(TcpSegment *seg) { +void PrintList(TcpSegment *seg) +{ TcpSegment *prev_seg = NULL; TcpSegment *head_seg = seg; @@ -223,25 +251,32 @@ void PrintList(TcpSegment *seg) { while (seg != NULL) { if (SEQ_LT(next_seq,seg->seq)) { - SCLogDebug("missing segment(s) for %" PRIu32 " bytes of data", (seg->seq - next_seq)); + SCLogDebug("missing segment(s) for %" PRIu32 " bytes of data", + (seg->seq - next_seq)); } - SCLogDebug("seg %10"PRIu32" len %" PRIu16 ", seg %p, prev %p, next %p", seg->seq, seg->payload_len, seg, seg->prev, seg->next); + SCLogDebug("seg %10"PRIu32" len %" PRIu16 ", seg %p, prev %p, next %p", + seg->seq, seg->payload_len, seg, seg->prev, seg->next); if (seg->prev != NULL && SEQ_LT(seg->seq,seg->prev->seq)) { - SCLogDebug("inconsistant list: SEQ_LT(seg->seq,seg->prev->seq)) == TRUE, seg->seq %" PRIu32 ", seg->prev->seq %" PRIu32 "", seg->seq, seg->prev->seq); + SCLogDebug("inconsistant list: SEQ_LT(seg->seq,seg->prev->seq)) == " + "TRUE, seg->seq %" PRIu32 ", seg->prev->seq %" PRIu32 "", + seg->seq, seg->prev->seq); PrintList2(head_seg); abort(); } if (SEQ_LT(seg->seq,next_seq)) { - SCLogDebug("inconsistant list: SEQ_LT(seg->seq,next_seq)) == TRUE, seg->seq %" PRIu32 ", next_seq %" PRIu32 "", seg->seq, next_seq); + SCLogDebug("inconsistant list: SEQ_LT(seg->seq,next_seq)) == TRUE, " + "seg->seq %" PRIu32 ", next_seq %" PRIu32 "", seg->seq, + next_seq); PrintList2(head_seg); abort(); } if (prev_seg != seg->prev) { - SCLogDebug("inconsistant list: prev_seg %p != seg->prev %p", prev_seg, seg->prev); + SCLogDebug("inconsistant list: prev_seg %p != seg->prev %p", + prev_seg, seg->prev); PrintList2(head_seg); abort(); } @@ -261,7 +296,8 @@ void PrintList(TcpSegment *seg) { * \param seg Newly arrived segment */ -static int ReassembleInsertSegment(TcpStream *stream, TcpSegment *seg) { +static int ReassembleInsertSegment(TcpStream *stream, TcpSegment *seg) +{ TcpSegment *list_seg = stream->seg_list; uint8_t os_policy = stream->os_policy; @@ -269,8 +305,8 @@ static int ReassembleInsertSegment(TcpStream *stream, TcpSegment *seg) { char return_seg = FALSE; if (list_seg == NULL) { - SCLogDebug("empty list, inserting seg %p seq %" PRIu32 ", len %" PRIu32 "", - seg, seg->seq, seg->payload_len); + SCLogDebug("empty list, inserting seg %p seq %" PRIu32 ", " + "len %" PRIu32 "", seg, seg->seq, seg->payload_len); stream->seg_list = seg; seg->prev = NULL; stream->seg_list_tail = seg; @@ -290,14 +326,18 @@ static int ReassembleInsertSegment(TcpStream *stream, TcpSegment *seg) { } for (; list_seg != NULL; list_seg = list_seg->next) { - SCLogDebug("seg %p, list_seg %p, list_prev %p list_seg->next %p, segment length %" PRIu32 "", - seg, list_seg, list_seg->prev, list_seg->next, seg->payload_len); + SCLogDebug("seg %p, list_seg %p, list_prev %p list_seg->next %p, " + "segment length %" PRIu32 "", seg, list_seg, list_seg->prev, + list_seg->next, seg->payload_len); /* segment starts before list */ if (SEQ_LT(seg->seq, list_seg->seq)) { /* seg is entirely before list_seg */ if (SEQ_LEQ((seg->seq + seg->payload_len), list_seg->seq)) { - SCLogDebug("before list seg: seg->seq %" PRIu32 ", list_seg->seq %" PRIu32 ", list_seg->payload_len %" PRIu32 ", list_seg->prev %p", seg->seq, list_seg->seq, list_seg->payload_len, list_seg->prev); + SCLogDebug("before list seg: seg->seq %" PRIu32 ", list_seg->seq" + " %" PRIu32 ", list_seg->payload_len %" PRIu32 ", " + "list_seg->prev %p", seg->seq, list_seg->seq, + list_seg->payload_len, list_seg->prev); seg->next = list_seg; if (list_seg->prev == NULL) { stream->seg_list = seg; @@ -310,13 +350,15 @@ static int ReassembleInsertSegment(TcpStream *stream, TcpSegment *seg) { goto end; /*seg overlap with nest seg(s)*/ } else { - ret_value = HandleSegmentStartsBeforeListSegment(stream, list_seg, seg, os_policy); + ret_value = HandleSegmentStartsBeforeListSegment(stream, + list_seg, seg, os_policy); if (ret_value == 1) { ret_value = 0; return_seg = TRUE; goto end; } else if (ret_value == -1) { - printf("ERROR: HandleSegmentStartsBeforeListSegment failed\n"); + SCLogError(SC_ERR_REASSEMBLY_FAILED, + "HandleSegmentStartsBeforeListSegment failed"); ret_value = -1; return_seg = TRUE; goto end; @@ -324,23 +366,30 @@ static int ReassembleInsertSegment(TcpStream *stream, TcpSegment *seg) { } /* seg starts at same sequence number as list_seg */ } else if (SEQ_EQ(seg->seq, list_seg->seq)) { - ret_value = HandleSegmentStartsAtSameListSegment(stream, list_seg, seg, os_policy); + ret_value = HandleSegmentStartsAtSameListSegment(stream, list_seg, + seg, os_policy); if (ret_value == 1) { ret_value = 0; return_seg = TRUE; goto end; } else if (ret_value == -1) { - printf("ERROR: HandleSegmentStartsAtSameListSegment failed\n"); + SCLogError(SC_ERR_REASSEMBLY_FAILED, + "HandleSegmentStartsAtSameListSegment failed"); ret_value = -1; return_seg = TRUE; goto end; } /* seg starts at sequence number higher than list_seg */ } else if (SEQ_GT(seg->seq, list_seg->seq)) { - if (((SEQ_GEQ(seg->seq, (list_seg->seq + list_seg->payload_len)))) && - SEQ_GT((seg->seq + seg->payload_len), - (list_seg->seq + list_seg->payload_len))) { - SCLogDebug("starts beyond list end, ends after list end: seg->seq %" PRIu32 ", list_seg->seq %" PRIu32 ", list_seg->payload_len %" PRIu32 " (%" PRIu32 ")", seg->seq, list_seg->seq, list_seg->payload_len, list_seg->seq + list_seg->payload_len); + if (((SEQ_GEQ(seg->seq, (list_seg->seq + list_seg->payload_len)))) + && SEQ_GT((seg->seq + seg->payload_len), + (list_seg->seq + list_seg->payload_len))) + { + SCLogDebug("starts beyond list end, ends after list end: " + "seg->seq %" PRIu32 ", list_seg->seq %" PRIu32 ", " + "list_seg->payload_len %" PRIu32 " (%" PRIu32 ")", + seg->seq, list_seg->seq, list_seg->payload_len, + list_seg->seq + list_seg->payload_len); if (list_seg->next == NULL) { list_seg->next = seg; @@ -348,13 +397,15 @@ static int ReassembleInsertSegment(TcpStream *stream, TcpSegment *seg) { goto end; } } else { - ret_value = HandleSegmentStartsAfterListSegment(stream, list_seg, seg, os_policy); + ret_value = HandleSegmentStartsAfterListSegment(stream, + list_seg, seg, os_policy); if (ret_value == 1) { ret_value = 0; return_seg = TRUE; goto end; } else if (ret_value == -1) { - printf("ERROR: HandleSegmentStartsAfterListSegment failed\n"); + SCLogError(SC_ERR_REASSEMBLY_FAILED, + "HandleSegmentStartsAfterListSegment failed"); ret_value = -1; return_seg = TRUE; goto end; @@ -386,7 +437,11 @@ end: * \param os_policy OS_POLICY of the given stream. */ -static int HandleSegmentStartsBeforeListSegment(TcpStream *stream, TcpSegment *list_seg, TcpSegment *seg, uint8_t os_policy) { +static int HandleSegmentStartsBeforeListSegment(TcpStream *stream, + TcpSegment *list_seg, + TcpSegment *seg, + uint8_t os_policy) +{ uint16_t overlap = 0; uint16_t packet_length = 0; uint32_t overlap_point = 0; @@ -394,12 +449,15 @@ static int HandleSegmentStartsBeforeListSegment(TcpStream *stream, TcpSegment *l char end_after = FALSE; char end_same = FALSE; #ifdef DEBUG - SCLogDebug("seg->seq %" PRIu32 ", seg->payload_len %" PRIu32 "", seg->seq, seg->payload_len); + SCLogDebug("seg->seq %" PRIu32 ", seg->payload_len %" PRIu32 "", seg->seq, + seg->payload_len); PrintList(stream->seg_list); #endif if (SEQ_GT((seg->seq + seg->payload_len), list_seg->seq) && - SEQ_LT((seg->seq + seg->payload_len),(list_seg->seq + list_seg->payload_len))) { + SEQ_LT((seg->seq + seg->payload_len),(list_seg->seq + + list_seg->payload_len))) + { /* seg starts before list seg, ends beyond it but before list end */ end_before = TRUE; @@ -407,35 +465,55 @@ static int HandleSegmentStartsBeforeListSegment(TcpStream *stream, TcpSegment *l * We know seg->seq + seg->payload_len is bigger than list_seg->seq */ overlap = (seg->seq + seg->payload_len) - list_seg->seq; overlap_point = list_seg->seq; - SCLogDebug("starts before list seg, ends before list end: seg->seq %" PRIu32 ", list_seg->seq %" PRIu32 ", list_seg->payload_len %" PRIu16 " overlap is %" PRIu32 ", overlap point %"PRIu32"", seg->seq, list_seg->seq, list_seg->payload_len, overlap, overlap_point); - } else if (SEQ_EQ((seg->seq + seg->payload_len), (list_seg->seq + list_seg->payload_len))) { + SCLogDebug("starts before list seg, ends before list end: seg->seq " + "%" PRIu32 ", list_seg->seq %" PRIu32 ", " + "list_seg->payload_len %" PRIu16 " overlap is %" PRIu32 ", " + "overlap point %"PRIu32"", seg->seq, list_seg->seq, + list_seg->payload_len, overlap, overlap_point); + } else if (SEQ_EQ((seg->seq + seg->payload_len), (list_seg->seq + + list_seg->payload_len))) + { /* seg fully overlaps list_seg, starts before, at end point * [aaa[ababab]] where a = seg, b = list_seg * overlap is [ababab], which is list_seg->payload_len */ overlap = list_seg->payload_len; end_same = TRUE; overlap_point = list_seg->seq; - SCLogDebug("starts before list seg, ends at list end: list prev %p seg->seq %" PRIu32 ", list_seg->seq %" PRIu32 ", list_seg->payload_len %" PRIu32 " overlap is %" PRIu32 "", list_seg->prev, seg->seq, list_seg->seq, list_seg->payload_len, overlap); + SCLogDebug("starts before list seg, ends at list end: list prev %p" + "seg->seq %" PRIu32 ", list_seg->seq %" PRIu32 "," + "list_seg->payload_len %" PRIu32 " overlap is %" PRIu32 "", + list_seg->prev, seg->seq, list_seg->seq, + list_seg->payload_len, overlap); /* seg fully overlaps list_seg, starts before, ends after list endpoint */ - } else if (SEQ_GT((seg->seq + seg->payload_len), (list_seg->seq + list_seg->payload_len))) { + } else if (SEQ_GT((seg->seq + seg->payload_len), (list_seg->seq + + list_seg->payload_len))) + { /* seg fully overlaps list_seg, starts before, ends after list endpoint * [aaa[ababab]aaa] where a = seg, b = list_seg * overlap is [ababab] which is list_seg->payload_len */ overlap = list_seg->payload_len; end_after = TRUE; overlap_point = list_seg->seq; - SCLogDebug("starts before list seg, ends after list end: seg->seq %" PRIu32 ", list_seg->seq %" PRIu32 ", list_seg->payload_len %" PRIu32 " overlap is %" PRIu32 "", seg->seq, list_seg->seq, list_seg->payload_len, overlap); + SCLogDebug("starts before list seg, ends after list end: seg->seq " + "%" PRIu32 ", list_seg->seq %" PRIu32 ", " + "list_seg->payload_len %" PRIu32 " overlap is %" PRIu32 "", + seg->seq, list_seg->seq, list_seg->payload_len, overlap); } if (overlap > 0) { - /* Handling case when the packet starts before the first packet in the list */ + /* Handling case when the packet starts before the first packet in the + * list */ if (list_seg->prev == NULL) { packet_length = seg->payload_len + (list_seg->payload_len - overlap); - SCLogDebug("entered here pkt len %" PRIu32 ", seg %" PRIu32 ", list %" PRIu32 "", - packet_length, seg->payload_len, list_seg->payload_len); + SCLogDebug("entered here pkt len %" PRIu32 ", seg %" PRIu32 ", list" + " %" PRIu32 "", packet_length, seg->payload_len, + list_seg->payload_len); TcpSegment *new_seg = StreamTcpGetSegment(packet_length); if (new_seg == NULL) { + uint16_t idx = segment_pool_idx[packet_length]; + SCLogError(SC_ERR_POOL_EMPTY, "segment_pool[%"PRIu16"] is" + " empty", idx); return -1; } new_seg->payload_len = packet_length; @@ -446,11 +524,18 @@ static int HandleSegmentStartsBeforeListSegment(TcpStream *stream, TcpSegment *l StreamTcpSegmentDataCopy(new_seg, list_seg); /* first the data before the list_seg->seq */ - StreamTcpSegmentDataReplace(new_seg, seg, seg->seq, (uint16_t) (list_seg->seq - seg->seq)); - - /* then, if any, the data after list_seg->seq + list_seg->payload_len */ - if (SEQ_GT((seg->seq + seg->payload_len), (list_seg->seq + list_seg->payload_len))) { - StreamTcpSegmentDataReplace(new_seg, seg, (list_seg->seq + list_seg->payload_len), (uint16_t) (((seg->seq + seg->payload_len) - (list_seg->seq + list_seg->payload_len)))); + StreamTcpSegmentDataReplace(new_seg, seg, seg->seq, + (uint16_t) (list_seg->seq - seg->seq)); + + /* if any, data after list_seg->seq + list_seg->payload_len */ + if (SEQ_GT((seg->seq + seg->payload_len), (list_seg->seq + + list_seg->payload_len))) + { + StreamTcpSegmentDataReplace(new_seg, seg, (list_seg->seq + + list_seg->payload_len), (uint16_t) + (((seg->seq + seg->payload_len) - + (list_seg->seq + + list_seg->payload_len)))); } /*update the stream last_seg in case of removal of list_seg*/ @@ -467,30 +552,48 @@ static int HandleSegmentStartsBeforeListSegment(TcpStream *stream, TcpSegment *l } stream->seg_list = new_seg; - SCLogDebug("list_seg now %p, stream->seg_list now %p", list_seg, stream->seg_list); + SCLogDebug("list_seg now %p, stream->seg_list now %p", list_seg, + stream->seg_list); } else if (end_before == TRUE || end_same == TRUE) { /* Handling overlapping with more than one segment and filling gap */ - if (SEQ_LEQ(seg->seq, (list_seg->prev->seq + list_seg->prev->payload_len))) { - packet_length = list_seg->payload_len + (list_seg->seq - (list_seg->prev->seq + list_seg->prev->payload_len)); + if (SEQ_LEQ(seg->seq, (list_seg->prev->seq + + list_seg->prev->payload_len))) + { + 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) { + uint16_t idx = segment_pool_idx[packet_length]; + SCLogError(SC_ERR_POOL_EMPTY, "segment_pool[%"PRIu16"] is" + " empty", idx); return -1; } new_seg->payload_len = packet_length; - if (SEQ_GT((list_seg->prev->seq + list_seg->prev->payload_len), seg->seq)) - new_seg->seq = (list_seg->prev->seq + list_seg->prev->payload_len); - else + if (SEQ_GT((list_seg->prev->seq + list_seg->prev->payload_len), + seg->seq)) + { + new_seg->seq = (list_seg->prev->seq + + list_seg->prev->payload_len); + } else { new_seg->seq = seg->seq; + } + new_seg->next = list_seg->next; new_seg->prev = list_seg->prev; StreamTcpSegmentDataCopy(new_seg, list_seg); - uint16_t copy_len = (uint16_t) (list_seg->seq - (list_seg->prev->seq + list_seg->prev->payload_len)); - SCLogDebug("copy_len %" PRIu32 " (%" PRIu32 " - %" PRIu32 ")", copy_len, list_seg->seq, (list_seg->prev->seq + list_seg->prev->payload_len)); - StreamTcpSegmentDataReplace(new_seg, seg, (list_seg->prev->seq + list_seg->prev->payload_len), copy_len); + uint16_t copy_len = (uint16_t) (list_seg->seq - + (list_seg->prev->seq + + list_seg->prev->payload_len)); + SCLogDebug("copy_len %" PRIu32 " (%" PRIu32 " - %" PRIu32 ")", + copy_len, list_seg->seq, (list_seg->prev->seq + + list_seg->prev->payload_len)); + StreamTcpSegmentDataReplace(new_seg, seg, (list_seg->prev->seq + + list_seg->prev->payload_len), copy_len); /*update the stream last_seg in case of removal of list_seg*/ if (stream->seg_list_tail == list_seg) @@ -507,23 +610,38 @@ static int HandleSegmentStartsBeforeListSegment(TcpStream *stream, TcpSegment *l } } else if (end_after == TRUE) { if (list_seg->next != NULL) { - if (SEQ_LEQ((seg->seq + seg->payload_len), list_seg->next->seq)) { - if (SEQ_GT(seg->seq, (list_seg->prev->seq + list_seg->prev->payload_len))) - 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)); + if (SEQ_LEQ((seg->seq + seg->payload_len), list_seg->next->seq)) + { + if (SEQ_GT(seg->seq, (list_seg->prev->seq + + list_seg->prev->payload_len))) + { + 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)); + } - packet_length += (seg->seq + seg->payload_len) - (list_seg->seq + list_seg->payload_len); + packet_length += (seg->seq + seg->payload_len) - + (list_seg->seq + list_seg->payload_len); TcpSegment *new_seg = StreamTcpGetSegment(packet_length); if (new_seg == NULL) { + uint16_t idx = segment_pool_idx[packet_length]; + SCLogError(SC_ERR_POOL_EMPTY, "segment_pool[%"PRIu16"] " + "is empty", idx); return -1; } new_seg->payload_len = packet_length; - if (SEQ_GT((list_seg->prev->seq + list_seg->prev->payload_len), seg->seq)) - new_seg->seq = (list_seg->prev->seq + list_seg->prev->payload_len); - else + if (SEQ_GT((list_seg->prev->seq + + list_seg->prev->payload_len), seg->seq)) + { + new_seg->seq = (list_seg->prev->seq + + list_seg->prev->payload_len); + } else { new_seg->seq = seg->seq; + } new_seg->next = list_seg->next; new_seg->prev = list_seg->prev; @@ -532,11 +650,14 @@ static int HandleSegmentStartsBeforeListSegment(TcpStream *stream, TcpSegment *l /* copy the part before list_seg */ uint16_t copy_len = list_seg->seq - new_seg->seq; - StreamTcpSegmentDataReplace(new_seg, seg, new_seg->seq, copy_len); + StreamTcpSegmentDataReplace(new_seg, seg, new_seg->seq, + copy_len); /* copy the part after list_seg */ - copy_len = packet_length - ((list_seg->seq + list_seg->payload_len) - seg->seq); - StreamTcpSegmentDataReplace(new_seg, seg, (list_seg->seq + list_seg->payload_len), copy_len); + copy_len = packet_length - ((list_seg->seq + + list_seg->payload_len) - seg->seq); + StreamTcpSegmentDataReplace(new_seg, seg, (list_seg->seq + + list_seg->payload_len), copy_len); if (new_seg->prev != NULL) { new_seg->prev->next = new_seg; @@ -558,15 +679,22 @@ static int HandleSegmentStartsBeforeListSegment(TcpStream *stream, TcpSegment *l case OS_POLICY_SOLARIS: case OS_POLICY_HPUX11: if (end_after == TRUE || end_same == TRUE) { - StreamTcpSegmentDataReplace(list_seg, seg, overlap_point, overlap); + StreamTcpSegmentDataReplace(list_seg, seg, overlap_point, + overlap); end_after = FALSE; } else { - SCLogDebug("using old data in starts before list case, list_seg->seq %" PRIu32 " policy %" PRIu32 " overlap %" PRIu32 "", list_seg->seq, os_policy, overlap); + SCLogDebug("using old data in starts before list case, " + "list_seg->seq %" PRIu32 " policy %" PRIu32 " " + "overlap %" PRIu32 "", list_seg->seq, os_policy, + overlap); } break; case OS_POLICY_VISTA: case OS_POLICY_FIRST: - SCLogDebug("using old data in starts before list case, list_seg->seq %" PRIu32 " policy %" PRIu32 " overlap %" PRIu32 "", list_seg->seq, os_policy, overlap); + SCLogDebug("using old data in starts before list case, " + "list_seg->seq %" PRIu32 " policy %" PRIu32 " " + "overlap %" PRIu32 "", list_seg->seq, os_policy, + overlap); break; case OS_POLICY_BSD: case OS_POLICY_HPUX10: @@ -578,8 +706,12 @@ static int HandleSegmentStartsBeforeListSegment(TcpStream *stream, TcpSegment *l case OS_POLICY_MACOS: case OS_POLICY_LAST: default: - SCLogDebug("replacing old data in starts before list seg list_seg->seq %" PRIu32 " policy %" PRIu32 " overlap %" PRIu32 "", list_seg->seq, os_policy, overlap); - StreamTcpSegmentDataReplace(list_seg, seg, overlap_point, overlap); + SCLogDebug("replacing old data in starts before list seg " + "list_seg->seq %" PRIu32 " policy %" PRIu32 " " + "overlap %" PRIu32 "", list_seg->seq, os_policy, + overlap); + StreamTcpSegmentDataReplace(list_seg, seg, overlap_point, + overlap); break; } /* To return from for loop as seg is finished with current list_seg @@ -605,7 +737,11 @@ static int HandleSegmentStartsBeforeListSegment(TcpStream *stream, TcpSegment *l * \param os_policy OS_POLICY of the given stream. */ -static int HandleSegmentStartsAtSameListSegment(TcpStream *stream, TcpSegment *list_seg, TcpSegment *seg, uint8_t os_policy) { +static int HandleSegmentStartsAtSameListSegment(TcpStream *stream, + TcpSegment *list_seg, + TcpSegment *seg, + uint8_t os_policy) +{ uint16_t overlap = 0; uint16_t packet_length; char end_before = FALSE; @@ -613,15 +749,22 @@ static int HandleSegmentStartsAtSameListSegment(TcpStream *stream, TcpSegment *l char end_same = FALSE; char handle_beyond = FALSE; - if (SEQ_LT((seg->seq + seg->payload_len), (list_seg->seq + list_seg->payload_len))) { + if (SEQ_LT((seg->seq + seg->payload_len), (list_seg->seq + + list_seg->payload_len))) + { /* seg->seg == list_seg->seq and list_seg->payload_len > seg->payload_len * [[ababab]bbbb] where a = seg, b = list_seg * overlap is the [ababab] part, which equals seg->payload_len. */ overlap = seg->payload_len; end_before = TRUE; - SCLogDebug("starts at list seq, ends before list end: seg->seq %" PRIu32 ", list_seg->seq %" PRIu32 ", list_seg->payload_len %" PRIu32 " overlap is%" PRIu32 "", seg->seq, list_seg->seq, list_seg->payload_len, overlap); - - } else if (SEQ_EQ((seg->seq + seg->payload_len), (list_seg->seq + list_seg->payload_len))) { + SCLogDebug("starts at list seq, ends before list end: seg->seq " + "%" PRIu32 ", list_seg->seq %" PRIu32 ", " + "list_seg->payload_len %" PRIu32 " overlap is%" PRIu32 "", + seg->seq, list_seg->seq, list_seg->payload_len, overlap); + + } else if (SEQ_EQ((seg->seq + seg->payload_len), (list_seg->seq + + list_seg->payload_len))) + { /* seg starts at seq, ends at seq, retransmission. * both segments are the same, so overlap is either * seg->payload_len or list_seg->payload_len */ @@ -629,7 +772,10 @@ static int HandleSegmentStartsAtSameListSegment(TcpStream *stream, TcpSegment *l /* check csum, ack, other differences? */ overlap = seg->payload_len; end_same = TRUE; - SCLogDebug("(retransmission) starts at list seq, ends at list end: seg->seq %" PRIu32 ", list_seg->seq %" PRIu32 ", list_seg->payload_len %" PRIu32 " overlap is %"PRIu32"", seg->seq, list_seg->seq, list_seg->payload_len, overlap); + SCLogDebug("(retransmission) starts at list seq, ends at list end: " + "seg->seq %" PRIu32 ", list_seg->seq %" PRIu32 ", " + "list_seg->payload_len %" PRIu32 " overlap is %"PRIu32"", + seg->seq, list_seg->seq, list_seg->payload_len, overlap); } else if (SEQ_GT((seg->seq + seg->payload_len), (list_seg->seq + list_seg->payload_len))) { @@ -639,7 +785,10 @@ static int HandleSegmentStartsAtSameListSegment(TcpStream *stream, TcpSegment *l * overlap is the [ababab] part, which equals list_seg->payload_len. */ overlap = list_seg->payload_len; end_after = TRUE; - SCLogDebug("starts at list seq, ends beyond list end: seg->seq %" PRIu32 ", list_seg->seq %" PRIu32 ", list_seg->payload_len %" PRIu32 " overlap is %" PRIu32 "", seg->seq, list_seg->seq, list_seg->payload_len, overlap); + SCLogDebug("starts at list seq, ends beyond list end: seg->seq " + "%" PRIu32 ", list_seg->seq %" PRIu32 ", " + "list_seg->payload_len %" PRIu32 " overlap is %" PRIu32 "", + seg->seq, list_seg->seq, list_seg->payload_len, overlap); } if (overlap > 0) { /*Handle the case when newly arrived segment ends after original @@ -650,27 +799,36 @@ static int HandleSegmentStartsAtSameListSegment(TcpStream *stream, TcpSegment *l if (list_seg->next != NULL) { /* first see if we have space left to fill up */ - if (SEQ_LT((list_seg->seq + list_seg->payload_len), list_seg->next->seq)) { + if (SEQ_LT((list_seg->seq + list_seg->payload_len), + list_seg->next->seq)) + { fill_gap = TRUE; } /* then see if we overlap (partly) with the next seg */ - if (SEQ_GT((seg->seq + seg->payload_len), list_seg->next->seq)) { + if (SEQ_GT((seg->seq + seg->payload_len), list_seg->next->seq)) + { handle_beyond = TRUE; } } - SCLogDebug("fill_gap %s, handle_beyond %s", fill_gap?"TRUE":"FALSE", handle_beyond?"TRUE":"FALSE"); + SCLogDebug("fill_gap %s, handle_beyond %s", fill_gap?"TRUE":"FALSE", + handle_beyond?"TRUE":"FALSE"); if (fill_gap == TRUE) { - /* if there is a gap after this list_seg we fill it now with a new seg */ - SCLogDebug("filling gap: list_seg->next->seq %"PRIu32"", list_seg->next?list_seg->next->seq:0); + /* if there is a gap after this list_seg we fill it now with a + * new seg */ + SCLogDebug("filling gap: list_seg->next->seq %"PRIu32"", + list_seg->next?list_seg->next->seq:0); packet_length = seg->payload_len - list_seg->payload_len; SCLogDebug("packet_length %"PRIu16"", packet_length); TcpSegment *new_seg = StreamTcpGetSegment(packet_length); if (new_seg == NULL) { + uint16_t idx = segment_pool_idx[packet_length]; + SCLogError(SC_ERR_POOL_EMPTY, "segment_pool[%"PRIu16"] is" + " empty", idx); return -1; } new_seg->payload_len = packet_length; @@ -680,8 +838,11 @@ static int HandleSegmentStartsAtSameListSegment(TcpStream *stream, TcpSegment *l new_seg->next->prev = new_seg; new_seg->prev = list_seg; 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); - StreamTcpSegmentDataReplace(new_seg, seg, new_seg->seq, new_seg->payload_len); + 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); + StreamTcpSegmentDataReplace(new_seg, seg, new_seg->seq, + new_seg->payload_len); /*update the stream last_seg in case of removal of list_seg*/ if (stream->seg_list_tail == list_seg) @@ -696,7 +857,10 @@ static int HandleSegmentStartsAtSameListSegment(TcpStream *stream, TcpSegment *l StreamTcpSegmentDataReplace(list_seg, seg, seg->seq, overlap); end_after = FALSE; } else { - SCLogDebug("using old data in starts at list case, list_seg->seq %" PRIu32 " policy %" PRIu32 " overlap %" PRIu32 "", list_seg->seq, os_policy, overlap); + SCLogDebug("using old data in starts at list case, " + "list_seg->seq %" PRIu32 " policy %" PRIu32 " " + "overlap %" PRIu32 "", list_seg->seq, os_policy, + overlap); } break; case OS_POLICY_LAST: @@ -706,7 +870,10 @@ static int HandleSegmentStartsAtSameListSegment(TcpStream *stream, TcpSegment *l if (end_after == TRUE) { StreamTcpSegmentDataReplace(list_seg, seg, seg->seq, overlap); } else { - SCLogDebug("using old data in starts at list case, list_seg->seq %" PRIu32 " policy %" PRIu32 " overlap %" PRIu32 "", list_seg->seq, os_policy, overlap); + SCLogDebug("using old data in starts at list case, " + "list_seg->seq %" PRIu32 " policy %" PRIu32 " " + "overlap %" PRIu32 "", list_seg->seq, os_policy, + overlap); } break; case OS_POLICY_BSD: @@ -718,7 +885,9 @@ static int HandleSegmentStartsAtSameListSegment(TcpStream *stream, TcpSegment *l case OS_POLICY_MACOS: case OS_POLICY_FIRST: default: - SCLogDebug("using old data in starts at list case, list_seg->seq %" PRIu32 " policy %" PRIu32 " overlap %" PRIu32 "", list_seg->seq, os_policy, overlap); + SCLogDebug("using old data in starts at list case, list_seg->seq" + " %" PRIu32 " policy %" PRIu32 " overlap %" PRIu32 "", + list_seg->seq, os_policy, overlap); break; } @@ -742,7 +911,11 @@ static int HandleSegmentStartsAtSameListSegment(TcpStream *stream, TcpSegment *l * \param os_policy OS_POLICY of the given stream. */ -static int HandleSegmentStartsAfterListSegment(TcpStream *stream, TcpSegment *list_seg, TcpSegment *seg, uint8_t os_policy) { +static int HandleSegmentStartsAfterListSegment(TcpStream *stream, + TcpSegment *list_seg, + TcpSegment *seg, + uint8_t os_policy) +{ uint16_t overlap = 0; uint16_t packet_length; char end_before = FALSE; @@ -750,7 +923,9 @@ static int HandleSegmentStartsAfterListSegment(TcpStream *stream, TcpSegment *li char end_same = FALSE; char handle_beyond = FALSE; - if (SEQ_LT((seg->seq + seg->payload_len), (list_seg->seq + list_seg->payload_len))) { + if (SEQ_LT((seg->seq + seg->payload_len), (list_seg->seq + + list_seg->payload_len))) + { /* seg starts after list, ends before list end * [bbbb[ababab]bbbb] where a = seg, b = list_seg * overlap is the part [ababab] which is seg->payload_len */ @@ -776,7 +951,9 @@ static int HandleSegmentStartsAfterListSegment(TcpStream *stream, TcpSegment *li list_seg->payload_len, overlap); } else if (SEQ_LT(seg->seq, list_seg->seq + list_seg->payload_len) && - SEQ_GT((seg->seq + seg->payload_len), (list_seg->seq + list_seg->payload_len))) { + SEQ_GT((seg->seq + seg->payload_len), (list_seg->seq + + list_seg->payload_len))) + { /* seg starts after seq, before end, ends beyond seq. * * [bbb[ababab]aaa] where a = seg, b = list_seg. @@ -800,23 +977,30 @@ static int HandleSegmentStartsAfterListSegment(TcpStream *stream, TcpSegment *li if (list_seg->next != NULL) { /* first see if we have space left to fill up */ - if (SEQ_LT((list_seg->seq + list_seg->payload_len), list_seg->next->seq)) { + if (SEQ_LT((list_seg->seq + list_seg->payload_len), + list_seg->next->seq)) + { fill_gap = TRUE; } /* then see if we overlap (partly) with the next seg */ - if (SEQ_GT((seg->seq + seg->payload_len), list_seg->next->seq)) { + if (SEQ_GT((seg->seq + seg->payload_len), list_seg->next->seq)) + { handle_beyond = TRUE; } } - SCLogDebug("fill_gap %s, handle_beyond %s", fill_gap?"TRUE":"FALSE", handle_beyond?"TRUE":"FALSE"); + SCLogDebug("fill_gap %s, handle_beyond %s", fill_gap?"TRUE":"FALSE", + handle_beyond?"TRUE":"FALSE"); if (fill_gap == TRUE) { - /* if there is a gap after this list_seg we fill it now with a new seg */ - SCLogDebug("filling gap: list_seg->next->seq %"PRIu32"", list_seg->next?list_seg->next->seq:0); + /* if there is a gap after this list_seg we fill it now with a + * new seg */ + SCLogDebug("filling gap: list_seg->next->seq %"PRIu32"", + list_seg->next?list_seg->next->seq:0); - packet_length = list_seg->next->seq - (list_seg->seq + list_seg->payload_len); + packet_length = list_seg->next->seq - (list_seg->seq + + list_seg->payload_len); if (packet_length > (seg->payload_len - overlap)) { packet_length = seg->payload_len - overlap; } @@ -824,6 +1008,9 @@ static int HandleSegmentStartsAfterListSegment(TcpStream *stream, TcpSegment *li TcpSegment *new_seg = StreamTcpGetSegment(packet_length); if (new_seg == NULL) { + uint16_t idx = segment_pool_idx[packet_length]; + SCLogError(SC_ERR_POOL_EMPTY, "segment_pool[%"PRIu16"] is" + " empty", idx); return -1; } new_seg->payload_len = packet_length; @@ -834,9 +1021,12 @@ static int HandleSegmentStartsAfterListSegment(TcpStream *stream, TcpSegment *li new_seg->prev = list_seg; 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); + 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); - StreamTcpSegmentDataReplace(new_seg, seg, new_seg->seq, new_seg->payload_len); + StreamTcpSegmentDataReplace(new_seg, seg, new_seg->seq, + new_seg->payload_len); /*update the stream last_seg in case of removal of list_seg*/ if (stream->seg_list_tail == list_seg) @@ -850,7 +1040,10 @@ static int HandleSegmentStartsAfterListSegment(TcpStream *stream, TcpSegment *li StreamTcpSegmentDataReplace(list_seg, seg, seg->seq, overlap); end_after = FALSE; } else { - SCLogDebug("using old data in starts beyond list case, list_seg->seq %" PRIu32 " policy %" PRIu32 " overlap %" PRIu32 "", list_seg->seq, os_policy, overlap); + SCLogDebug("using old data in starts beyond list case, " + "list_seg->seq %" PRIu32 " policy %" PRIu32 " " + "overlap %" PRIu32 "", list_seg->seq, os_policy, + overlap); } break; case OS_POLICY_LAST: @@ -867,7 +1060,10 @@ static int HandleSegmentStartsAfterListSegment(TcpStream *stream, TcpSegment *li case OS_POLICY_MACOS: case OS_POLICY_FIRST: default: /* DEFAULT POLICY */ - SCLogDebug("using old data in starts beyond list case, list_seg->seq %" PRIu32 " policy %" PRIu32 " overlap %" PRIu32 "", list_seg->seq, os_policy, overlap); + SCLogDebug("using old data in starts beyond list case, " + "list_seg->seq %" PRIu32 " policy %" PRIu32 " " + "overlap %" PRIu32 "", list_seg->seq, os_policy, + overlap); break; } if (end_before == TRUE || end_same == TRUE || handle_beyond == FALSE) { @@ -880,13 +1076,14 @@ static int HandleSegmentStartsAfterListSegment(TcpStream *stream, TcpSegment *li return 0; } -int StreamTcpReassembleHandleSegmentHandleData(TcpSession *ssn, TcpStream *stream, Packet *p) { +int StreamTcpReassembleHandleSegmentHandleData(TcpSession *ssn, + TcpStream *stream, Packet *p) +{ TcpSegment *seg = StreamTcpGetSegment(p->payload_len); if (seg == NULL) { -#ifdef DEBUG - printf("StreamTcpGetSegment returned NULL\n"); -#endif + uint16_t idx = segment_pool_idx[p->payload_len]; + SCLogError(SC_ERR_POOL_EMPTY, "segment_pool[%"PRIu16"] is empty", idx); return -1; } @@ -897,16 +1094,16 @@ int StreamTcpReassembleHandleSegmentHandleData(TcpSession *ssn, TcpStream *strea seg->prev = NULL; if (ReassembleInsertSegment(stream, seg) != 0) { -#ifdef DEBUG - printf("ReassembleInsertSegment failed\n"); -#endif + SCLogError(SC_ERR_REASSEMBLY_FAILED, "ReassembleInsertSegment failed"); return -1; } return 0; } -static void StreamTcpSetupMsg(TcpSession *ssn, TcpStream *stream, Packet *p, StreamMsg *smsg) { +static void StreamTcpSetupMsg(TcpSession *ssn, TcpStream *stream, Packet *p, + StreamMsg *smsg) +{ if (stream->ra_base_seq == stream->isn) { smsg->flags = STREAM_START; } else if (ssn->state > TCP_ESTABLISHED) { @@ -941,7 +1138,9 @@ static void StreamTcpSetupMsg(TcpSession *ssn, TcpStream *stream, Packet *p, Str /** \brief Check the minimum size limits for reassembly. * \retval 0 don't reassemble yet * \retval 1 do reassemble */ -static int StreamTcpReassembleCheckLimit(TcpSession *ssn, TcpStream *stream, Packet *p) { +static int StreamTcpReassembleCheckLimit(TcpSession *ssn, TcpStream *stream, + Packet *p) +{ /* some states mean we reassemble no matter how much data we have */ if (ssn->state >= TCP_TIME_WAIT) @@ -952,7 +1151,10 @@ static int StreamTcpReassembleCheckLimit(TcpSession *ssn, TcpStream *stream, Pac if (stream->ra_base_seq == stream->isn) { if (StreamMsgQueueGetMinInitChunkLen(STREAM_TOSERVER) > (stream->last_ack - stream->ra_base_seq)) { - SCLogDebug("toserver min init chunk len not yet reached: last_ack %"PRIu32", ra_base_seq %"PRIu32", len %"PRIu32"", stream->last_ack, stream->ra_base_seq, StreamMsgQueueGetMinInitChunkLen(STREAM_TOSERVER)); + SCLogDebug("toserver min init chunk len not yet reached: " + "last_ack %"PRIu32", ra_base_seq %"PRIu32", len " + "%"PRIu32"", stream->last_ack, stream->ra_base_seq, + StreamMsgQueueGetMinInitChunkLen(STREAM_TOSERVER)); return 0; } } else { @@ -966,7 +1168,8 @@ static int StreamTcpReassembleCheckLimit(TcpSession *ssn, TcpStream *stream, Pac if (stream->ra_base_seq == stream->isn) { if (StreamMsgQueueGetMinInitChunkLen(STREAM_TOCLIENT) > (stream->last_ack - stream->ra_base_seq)) { - SCLogDebug("StreamTcpReassembleCheckLimit: toclient min init chunk len not yet reached"); + SCLogDebug("StreamTcpReassembleCheckLimit: toclient min init " + "chunk len not yet reached"); return 0; } } else { @@ -981,7 +1184,10 @@ static int StreamTcpReassembleCheckLimit(TcpSession *ssn, TcpStream *stream, Pac return 1; } -int StreamTcpReassembleHandleSegmentUpdateACK (TcpReassemblyThreadCtx *ra_ctx, TcpSession *ssn, TcpStream *stream, Packet *p) { +int StreamTcpReassembleHandleSegmentUpdateACK (TcpReassemblyThreadCtx *ra_ctx, + TcpSession *ssn, TcpStream *stream, + Packet *p) +{ if (stream->seg_list == NULL) return 0; @@ -1007,11 +1213,15 @@ int StreamTcpReassembleHandleSegmentUpdateACK (TcpReassemblyThreadCtx *ra_ctx, T /* If packets are fully before ra_base_seq, skip them. We do this * 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); + 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); /** \todo we should probably not even insert them into the seglist */ if (SEQ_LEQ((seg->seq + seg->payload_len), (stream->ra_base_seq+1))) { - SCLogDebug("removing pre ra_base_seq %"PRIu32" seg %p seq %"PRIu32" len %"PRIu16"", stream->ra_base_seq, seg, seg->seq, seg->payload_len); + SCLogDebug("removing pre ra_base_seq %"PRIu32" seg %p seq %"PRIu32"" + " len %"PRIu16"", stream->ra_base_seq, seg, seg->seq, + seg->payload_len); TcpSegment *next_seg = seg->next; @@ -1035,9 +1245,12 @@ int StreamTcpReassembleHandleSegmentUpdateACK (TcpReassemblyThreadCtx *ra_ctx, T /* we've run into a sequence gap */ if (SEQ_GT(seg->seq, next_seq)) { - /* see what the length of the gap is, gap length is seg->seq - (ra_base_seq +1) */ + /* see what the length of the gap is, gap length is seg->seq - + * (ra_base_seq +1) */ uint32_t gap_len = seg->seq - next_seq; - SCLogDebug("expected next_seq %" PRIu32 ", got %" PRIu32 " , stream->last_ack %" PRIu32 ". Seq gap %" PRIu32"", next_seq, seg->seq, stream->last_ack, gap_len); + SCLogDebug("expected next_seq %" PRIu32 ", got %" PRIu32 " , " + "stream->last_ack %" PRIu32 ". Seq gap %" PRIu32"", + next_seq, seg->seq, stream->last_ack, gap_len); next_seq = seg->seq; @@ -1049,16 +1262,16 @@ int StreamTcpReassembleHandleSegmentUpdateACK (TcpReassemblyThreadCtx *ra_ctx, T if (smsg == NULL) { smsg = StreamMsgGetFromPool(); if (smsg == NULL) { - printf("StreamTcpReassembleHandleSegmentUpdateACK: couldn't " - "get a stream msg from the pool\n"); + SCLogError(SC_ERR_POOL_EMPTY, "stream_msg_pool is empty"); return -1; } } StreamTcpSetupMsg(ssn, stream, p, smsg); /* We have missed the packet and end host has ack'd it, so - IDS should advance it's ra_base_seq and should not consider this packet - any longer, even if it is retransmitted, as end host will drop it anyway */ + * IDS should advance it's ra_base_seq and should not consider this + * packet any longer, even if it is retransmitted, as end host will + * drop it anyway */ stream->ra_base_seq = seg->seq - 1; smsg->flags |= STREAM_GAP; @@ -1071,12 +1284,13 @@ int StreamTcpReassembleHandleSegmentUpdateACK (TcpReassemblyThreadCtx *ra_ctx, T /* if the segment ends beyond ra_base_seq we need to consider it */ if (SEQ_GT((seg->seq + seg->payload_len), stream->ra_base_seq)) { - SCLogDebug("seg->seq %" PRIu32 ", seg->payload_len %" PRIu32 ", stream->ra_base_seq %" PRIu32 "", - seg->seq, seg->payload_len, stream->ra_base_seq); + SCLogDebug("seg->seq %" PRIu32 ", seg->payload_len %" PRIu32 ", " + "stream->ra_base_seq %" PRIu32 "", seg->seq, + seg->payload_len, stream->ra_base_seq); if (smsg == NULL) { smsg = StreamMsgGetFromPool(); if (smsg == NULL) { - printf("StreamTcpReassembleHandleSegmentUpdateACK: couldn't get a stream msg from the pool\n"); + SCLogError(SC_ERR_POOL_EMPTY, "stream_msg_pool is empty"); return -1; } @@ -1089,7 +1303,8 @@ int StreamTcpReassembleHandleSegmentUpdateACK (TcpReassemblyThreadCtx *ra_ctx, T payload_offset = stream->ra_base_seq - seg->seq; if (SEQ_LT(stream->last_ack, (seg->seq + seg->payload_len))) { - payload_len = ((seg->seq + seg->payload_len) - stream->last_ack) - payload_offset; + payload_len = ((seg->seq + seg->payload_len) - + stream->last_ack) - payload_offset; } else { payload_len = seg->payload_len - payload_offset; } @@ -1111,7 +1326,9 @@ int StreamTcpReassembleHandleSegmentUpdateACK (TcpReassemblyThreadCtx *ra_ctx, T copy_size = payload_len; } BUG_ON(copy_size > sizeof(smsg->data.data)); - memcpy(smsg->data.data + smsg_offset, seg->payload + payload_offset, copy_size); + + memcpy(smsg->data.data + smsg_offset, seg->payload + payload_offset, + copy_size); smsg_offset += copy_size; stream->ra_base_seq += copy_size; SCLogDebug("stream->ra_base_seq %"PRIu32"", stream->ra_base_seq); @@ -1123,26 +1340,28 @@ int StreamTcpReassembleHandleSegmentUpdateACK (TcpReassemblyThreadCtx *ra_ctx, T smsg = NULL; } - /* if the payload len is bigger than what we copied, we handle the rest of the - payload next... */ + /* if the payload len is bigger than what we copied, we handle the + * rest of the payload next... */ if (copy_size < payload_len) { - SCLogDebug("copy_size %" PRIu32 " < %" PRIu32 "", copy_size, payload_len); + SCLogDebug("copy_size %" PRIu32 " < %" PRIu32 "", copy_size, + payload_len); payload_offset += copy_size; payload_len -= copy_size; BUG_ON(payload_offset > seg->payload_len); - /* we need a while loop here as the packets theoretically can be 64k */ + /* we need a while loop here as the packets theoretically can be + * 64k */ char segment_done = FALSE; while (segment_done == FALSE) { - SCLogDebug("new msg at offset %" PRIu32 ", payload_len %" PRIu32 "", payload_offset, payload_len); + SCLogDebug("new msg at offset %" PRIu32 ", payload_len " + "%" PRIu32 "", payload_offset, payload_len); /* get a new message XXX we need a setup function */ smsg = StreamMsgGetFromPool(); if (smsg == NULL) { - printf("StreamTcpReassembleHandleSegmentUpdateACK: " - "couldn't get a stream msg from the pool (while loop)\n"); + SCLogError(SC_ERR_POOL_EMPTY, "stream_msg_pool is empty"); return -1; } smsg_offset = 0; @@ -1155,15 +1374,20 @@ int StreamTcpReassembleHandleSegmentUpdateACK (TcpReassemblyThreadCtx *ra_ctx, T } BUG_ON(copy_size > sizeof(smsg->data.data)); - SCLogDebug("copy payload_offset %" PRIu32 ", smsg_offset %" PRIu32 ", copy_size %" PRIu32 "", - payload_offset, smsg_offset, copy_size); - memcpy(smsg->data.data + smsg_offset, seg->payload + payload_offset, copy_size); + SCLogDebug("copy payload_offset %" PRIu32 ", smsg_offset " + "%" PRIu32 ", copy_size %" PRIu32 "", + payload_offset, smsg_offset, copy_size); + memcpy(smsg->data.data + smsg_offset, seg->payload + + payload_offset, copy_size); smsg_offset += copy_size; stream->ra_base_seq += copy_size; - SCLogDebug("stream->ra_base_seq %"PRIu32"", stream->ra_base_seq); + + SCLogDebug("stream->ra_base_seq %"PRIu32"", + stream->ra_base_seq); smsg->data.data_len += copy_size; - SCLogDebug("copied payload_offset %" PRIu32 ", smsg_offset %" PRIu32 ", copy_size %" PRIu32 "", - payload_offset, smsg_offset, copy_size); + SCLogDebug("copied payload_offset %" PRIu32 ", " + "smsg_offset %" PRIu32 ", copy_size %" PRIu32 "", + payload_offset, smsg_offset, copy_size); if (smsg->data.data_len == sizeof (smsg->data.data)) { StreamMsgPutInQueue(ra_ctx->stream_q,smsg); smsg = NULL; @@ -1228,7 +1452,8 @@ int StreamTcpReassembleProcessAppLayer(TcpReassemblyThreadCtx *ra_ctx) if (smsg == NULL) break; - /** Handle the stream msg. No need to use locking, flow is already locked */ + /** Handle the stream msg. No need to use locking, flow is already + * locked */ r = AppLayerHandleMsg(smsg, FALSE); if (r < 0) break; @@ -1238,26 +1463,35 @@ int StreamTcpReassembleProcessAppLayer(TcpReassemblyThreadCtx *ra_ctx) SCReturnInt(r); } -int StreamTcpReassembleHandleSegment(TcpReassemblyThreadCtx *ra_ctx, TcpSession *ssn, TcpStream *stream, Packet *p) { - //printf("StreamTcpReassembleHandleSegment: ssn %p, stream %p, p %p, p->payload_len %"PRIu16"\n", ssn, stream, p, p->payload_len); +int StreamTcpReassembleHandleSegment(TcpReassemblyThreadCtx *ra_ctx, + TcpSession *ssn, TcpStream *stream, + Packet *p) +{ + SCEnter(); + SCLogDebug("ssn %p, stream %p, p %p, p->payload_len %"PRIu16"\n", + ssn, stream, p, p->payload_len); /* handle ack received */ - if (StreamTcpReassembleHandleSegmentUpdateACK(ra_ctx, ssn, stream, p) != 0) { - SCLogDebug("StreamTcpReassembleHandleSegmentUpdateACK error"); - return -1; + if (StreamTcpReassembleHandleSegmentUpdateACK(ra_ctx, ssn, stream, p) != 0) + { + SCLogError(SC_ERR_REASSEMBLY_FAILED, + "StreamTcpReassembleHandleSegmentUpdateACK error"); + SCReturnInt(-1); } if (p->payload_len > 0) { if (StreamTcpReassembleHandleSegmentHandleData(ssn, stream, p) != 0) { - SCLogDebug("StreamTcpReassembleHandleSegmentHandleData error"); - return -1; + SCLogError(SC_ERR_REASSEMBLY_FAILED, + "StreamTcpReassembleHandleSegmentHandleData error"); + SCReturnInt(-1); } } - return 0; + SCReturnInt(0); } -/** \brief Initialize the l7data ptr in the TCP session used by the L7 Modules for data storage. +/** \brief Initialize the l7data ptr in the TCP session used by the L7 Modules + * for data storage. * * \param ssn TcpSesssion to init the ptrs for * \param cnt number of items in the array @@ -1290,7 +1524,9 @@ void StreamL7DataPtrInit(TcpSession *ssn, uint8_t cnt) { * * \todo VJ We can remove the abort()s later. */ -void StreamTcpSegmentDataReplace(TcpSegment *dst_seg, TcpSegment *src_seg, uint32_t start_point, uint16_t len) { +void StreamTcpSegmentDataReplace(TcpSegment *dst_seg, TcpSegment *src_seg, + uint32_t start_point, uint16_t len) +{ uint32_t seq; uint16_t s_cnt = 0; uint16_t dst_pos = 0; @@ -1325,7 +1561,8 @@ void StreamTcpSegmentDataReplace(TcpSegment *dst_seg, TcpSegment *src_seg, uint3 * \warning Both segments need to be properly initialized. */ -void StreamTcpSegmentDataCopy(TcpSegment *dst_seg, TcpSegment *src_seg) { +void StreamTcpSegmentDataCopy(TcpSegment *dst_seg, TcpSegment *src_seg) +{ uint32_t i; uint16_t dst_pos = 0; uint16_t src_pos = 0; @@ -1335,7 +1572,8 @@ void StreamTcpSegmentDataCopy(TcpSegment *dst_seg, TcpSegment *src_seg) { else dst_pos = dst_seg->seq - src_seg->seq; - for (i = src_seg->seq; SEQ_LT(i, (src_seg->seq + src_seg->payload_len)); i++) { + for (i = src_seg->seq; SEQ_LT(i, (src_seg->seq + src_seg->payload_len)); i++) + { dst_seg->payload[dst_pos] = src_seg->payload[src_pos]; dst_pos++; @@ -1349,19 +1587,25 @@ void StreamTcpSegmentDataCopy(TcpSegment *dst_seg, TcpSegment *src_seg) { * \param len Length which tells the required size of needed segment. */ -TcpSegment* StreamTcpGetSegment(uint16_t len) { +TcpSegment* StreamTcpGetSegment(uint16_t len) +{ uint16_t idx = segment_pool_idx[len]; SCLogDebug("%" PRIu32 " for payload_len %" PRIu32 "", idx, len); + SCMutexLock(&segment_pool_mutex[idx]); TcpSegment *seg = (TcpSegment *) PoolGet(segment_pool[idx]); - SCLogDebug("segment_pool[%u]->empty_list_size %u, segment_pool[%u]->alloc_list_size %u, alloc %u", - idx, segment_pool[idx]->empty_list_size, idx, segment_pool[idx]->alloc_list_size, segment_pool[idx]->allocated); - //PoolPrintSaturation(segment_pool[idx]); + + SCLogDebug("segment_pool[%u]->empty_list_size %u, segment_pool[%u]->alloc_" + "list_size %u, alloc %u", idx, segment_pool[idx]->empty_list_size, + idx, segment_pool[idx]->alloc_list_size, + segment_pool[idx]->allocated); SCMutexUnlock(&segment_pool_mutex[idx]); - SCLogDebug("StreamTcpGetSegment: seg we return is %p", seg); + SCLogDebug("seg we return is %p", seg); if (seg == NULL) { - SCLogDebug("segment_pool[%u]->empty_list_size %u, alloc %u", idx, segment_pool[idx]->empty_list_size, segment_pool[idx]->allocated); + SCLogError(SC_ERR_POOL_EMPTY, "segment_pool[%u]->empty_list_size %u, " + "alloc %u", idx, segment_pool[idx]->empty_list_size, + segment_pool[idx]->allocated); } else { #ifdef DEBUG SCMutexLock(&segment_pool_cnt_mutex); @@ -1378,14 +1622,16 @@ TcpSegment* StreamTcpGetSegment(uint16_t len) { * \param seg Segment which will be returned back to the pool. */ -void StreamTcpSegmentReturntoPool(TcpSegment *seg) { +void StreamTcpSegmentReturntoPool(TcpSegment *seg) +{ seg->next = NULL; seg->prev = NULL; uint16_t idx = segment_pool_idx[seg->pool_size]; SCMutexLock(&segment_pool_mutex[idx]); PoolReturn(segment_pool[idx], (void *) seg); - SCLogDebug("segment_pool[%"PRIu16"]->empty_list_size %"PRIu32"", idx,segment_pool[idx]->empty_list_size); + SCLogDebug("segment_pool[%"PRIu16"]->empty_list_size %"PRIu32"", + idx,segment_pool[idx]->empty_list_size); SCMutexUnlock(&segment_pool_mutex[idx]); #ifdef DEBUG diff --git a/src/stream-tcp.c b/src/stream-tcp.c index e05f9bf0e6..17394add2d 100644 --- a/src/stream-tcp.c +++ b/src/stream-tcp.c @@ -56,7 +56,12 @@ extern void StreamTcpSegmentReturntoPool(TcpSegment *); int StreamTcpGetFlowState(void *); static int ValidTimestamp(TcpSession * , Packet *); +#ifndef UNITTESTS #define STREAMTCP_DEFAULT_SESSIONS 262144 +#else +#define STREAMTCP_DEFAULT_SESSIONS 32768 +#endif + #define STREAMTCP_DEFAULT_PREALLOC 32768 #define STREAMTCP_NEW_TIMEOUT 60 @@ -75,7 +80,8 @@ static uint64_t ssn_pool_cnt; static SCMutex ssn_pool_cnt_mutex; #endif -void TmModuleStreamTcpRegister (void) { +void TmModuleStreamTcpRegister (void) +{ tmm_modules[TMM_STREAMTCP].name = "StreamTcp"; tmm_modules[TMM_STREAMTCP].ThreadInit = StreamTcpThreadInit; tmm_modules[TMM_STREAMTCP].Func = StreamTcp; @@ -84,7 +90,8 @@ void TmModuleStreamTcpRegister (void) { tmm_modules[TMM_STREAMTCP].RegisterTests = StreamTcpRegisterTests; } -void StreamTcpReturnStreamSegments (TcpStream *stream) { +void StreamTcpReturnStreamSegments (TcpStream *stream) +{ TcpSegment *seg = stream->seg_list; TcpSegment *next_seg; @@ -105,7 +112,8 @@ void StreamTcpReturnStreamSegments (TcpStream *stream) { * * \param ssn Void ptr to the ssn. */ -void StreamTcpSessionClear(void *ssnptr) { +void StreamTcpSessionClear(void *ssnptr) +{ TcpSession *ssn = (TcpSession *)ssnptr; if (ssn == NULL) return; @@ -132,7 +140,8 @@ void StreamTcpSessionClear(void *ssnptr) { * * \param p Packet used to identify the stream. */ -static void StreamTcpSessionPktFree (Packet *p) { +static void StreamTcpSessionPktFree (Packet *p) +{ TcpSession *ssn = (TcpSession *)p->flow->protoctx; if (ssn == NULL) return; @@ -160,7 +169,8 @@ static void StreamTcpSessionPktFree (Packet *p) { * \param null NULL ptr (value of null is ignored) * \retval ptr void ptr to TcpSession structure with all vars set to 0/NULL */ -void *StreamTcpSessionPoolAlloc(void *null) { +void *StreamTcpSessionPoolAlloc(void *null) +{ void *ptr = malloc(sizeof(TcpSession)); if (ptr == NULL) return NULL; @@ -171,7 +181,8 @@ void *StreamTcpSessionPoolAlloc(void *null) { /** \brief Pool free function * \param s Void ptr to TcpSession memory */ -void StreamTcpSessionPoolFree(void *s) { +void StreamTcpSessionPoolFree(void *s) +{ if (s == NULL) return; @@ -189,52 +200,70 @@ void StreamTcpSessionPoolFree(void *s) { * be get printed. */ -void StreamTcpInitConfig(char quiet) { +void StreamTcpInitConfig(char quiet) +{ - //if (quiet == FALSE) - // printf("Initializing Stream:\n"); + SCLogDebug("Initializing Stream"); memset(&stream_config, 0, sizeof(stream_config)); /** set config defaults */ - stream_config.max_sessions = STREAMTCP_DEFAULT_SESSIONS; - stream_config.prealloc_sessions = STREAMTCP_DEFAULT_PREALLOC; + if ((ConfGetBool("stream.max_sessions", &stream_config.max_sessions)) == 0) + { + stream_config.max_sessions = STREAMTCP_DEFAULT_SESSIONS; + } + if ((ConfGetBool("stream.prealloc_sessions", + &stream_config.prealloc_sessions)) == 0) + { + stream_config.prealloc_sessions = STREAMTCP_DEFAULT_PREALLOC; + } + if ((ConfGetBool("stream.midstream", &stream_config.midstream)) == 0) { - stream_config.midstream = TRUE;/*In the final patch it will be FALSE*/ + stream_config.midstream = FALSE;/*In the final patch it will be FALSE*/ } - if ((ConfGetBool("stream.async_oneside", &stream_config.async_oneside)) == 0) { - stream_config.async_oneside = TRUE; /*In the final patch it will be FALSE*/ + if ((ConfGetBool("stream.async_oneside", &stream_config.async_oneside)) == 0) + { + stream_config.async_oneside = FALSE; /*In the final patch it will be FALSE*/ } - ssn_pool = PoolInit(stream_config.max_sessions, stream_config.prealloc_sessions, StreamTcpSessionPoolAlloc, NULL, StreamTcpSessionPoolFree); + ssn_pool = PoolInit(stream_config.max_sessions, + stream_config.prealloc_sessions, + StreamTcpSessionPoolAlloc, NULL, + StreamTcpSessionPoolFree); if (ssn_pool == NULL) { - exit(1); + SCLogError(SC_ERR_POOL_INIT_FAILED, "ssn_pool is not initialized"); + exit(EXIT_FAILURE); } SCMutexInit(&ssn_pool_mutex, NULL); StreamTcpReassembleInit(quiet); - /* set the default TCP timeout, free function and flow state function values. */ - FlowSetProtoTimeout(IPPROTO_TCP, STREAMTCP_NEW_TIMEOUT, STREAMTCP_EST_TIMEOUT, STREAMTCP_CLOSED_TIMEOUT); - FlowSetProtoEmergencyTimeout(IPPROTO_TCP, STREAMTCP_EMERG_NEW_TIMEOUT, STREAMTCP_EMERG_EST_TIMEOUT, STREAMTCP_EMERG_CLOSED_TIMEOUT); + /* set the default TCP timeout, free function and flow state function + * values. */ + FlowSetProtoTimeout(IPPROTO_TCP, STREAMTCP_NEW_TIMEOUT, + STREAMTCP_EST_TIMEOUT, STREAMTCP_CLOSED_TIMEOUT); + FlowSetProtoEmergencyTimeout(IPPROTO_TCP, STREAMTCP_EMERG_NEW_TIMEOUT, + STREAMTCP_EMERG_EST_TIMEOUT, + STREAMTCP_EMERG_CLOSED_TIMEOUT); FlowSetProtoFreeFunc(IPPROTO_TCP, StreamTcpSessionClear); FlowSetFlowStateFunc(IPPROTO_TCP, StreamTcpGetFlowState); } -void StreamTcpFreeConfig(char quiet) { +void StreamTcpFreeConfig(char quiet) +{ StreamTcpReassembleFree(quiet); if (ssn_pool != NULL) { PoolFree(ssn_pool); ssn_pool = NULL; } else { - printf("ERROR: ssn_pool is NULL\n"); - exit(1); + SCLogError(SC_ERR_POOL_EMPTY, "ssn_pool is NULL"); + exit(EXIT_FAILURE); } -#ifdef DEBUG + SCLogDebug("ssn_pool_cnt %"PRIu64"", ssn_pool_cnt); -#endif + SCMutexDestroy(&ssn_pool_mutex); } @@ -245,7 +274,8 @@ void StreamTcpFreeConfig(char quiet) { * * \retval TcpSession A new TCP session with field initilaized to 0/NULL. */ -TcpSession *StreamTcpNewSession (Packet *p) { +TcpSession *StreamTcpNewSession (Packet *p) +{ TcpSession *ssn = (TcpSession *)p->flow->protoctx; if (ssn == NULL) { @@ -254,8 +284,10 @@ TcpSession *StreamTcpNewSession (Packet *p) { SCMutexUnlock(&ssn_pool_mutex); ssn = (TcpSession *)p->flow->protoctx; - if (ssn == NULL) + if (ssn == NULL) { + SCLogError(SC_ERR_POOL_EMPTY, "ssn_pool is empty"); return NULL; + } ssn->state = TCP_NONE; ssn->aldata = NULL; @@ -270,7 +302,9 @@ TcpSession *StreamTcpNewSession (Packet *p) { return ssn; } -static inline void StreamTcpPacketSetState(Packet *p, TcpSession *ssn, uint8_t state) { +static inline void StreamTcpPacketSetState(Packet *p, TcpSession *ssn, + uint8_t state) +{ if (state == ssn->state) return; @@ -288,7 +322,8 @@ static inline void StreamTcpPacketSetState(Packet *p, TcpSession *ssn, uint8_t s * \param ssn TcpSession to whom this packet belongs * \param p Packet whose flag has to be changed */ -static inline void StreamTcpPacketSwitchDir(TcpSession *ssn, Packet *p) { +static inline void StreamTcpPacketSwitchDir(TcpSession *ssn, Packet *p) +{ SCLogDebug("ssn %p: switching pkt direction", ssn); if (PKT_IS_TOSERVER(p)) { @@ -305,11 +340,13 @@ static inline void StreamTcpPacketSwitchDir(TcpSession *ssn, Packet *p) { * packets while the session state is None which means a newly * initialized structure, or a fully closed session. * - * \param tv Thread Variable containig input/output queue, cpu affinity etc. + * \param tv Thread Variable containig input/output queue, cpu affinity * \param p Packet which has to be handled in this TCP state. * \param stt Strean Thread module registered to handle the stream handling */ -static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn) { +static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p, + StreamTcpThread *stt, TcpSession *ssn) +{ switch (p->tcph->th_flags) { case TH_SYN: { @@ -330,10 +367,12 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p, StreamTcpThread * ssn->client.ra_base_seq = ssn->client.isn; ssn->client.next_seq = ssn->client.isn + 1; - /*Set the stream timestamp value, if packet has timestamp option enabled.*/ + /*Set the stream timestamp value, if packet has timestamp option + * enabled.*/ if (p->tcpvars.ts != NULL) { ssn->client.last_ts = TCP_GET_TSVAL(p); - SCLogDebug("ssn %p: p->tcpvars.ts %p, %02x", ssn, p->tcpvars.ts, ssn->client.last_ts); + SCLogDebug("ssn %p: p->tcpvars.ts %p, %02x", ssn, p->tcpvars.ts, + ssn->client.last_ts); if (ssn->client.last_ts == 0) ssn->client.flags |= STREAMTCP_FLAG_ZERO_TIMESTAMP; @@ -348,8 +387,10 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p, StreamTcpThread * ssn->server.wscale = TCP_GET_WSCALE(p); } - SCLogDebug("ssn %p: ssn->client.isn %" PRIu32 ", ssn->client.next_seq %" PRIu32 ", ssn->client.last_ack %"PRIu32"", - ssn, ssn->client.isn, ssn->client.next_seq, ssn->client.last_ack); + SCLogDebug("ssn %p: ssn->client.isn %" PRIu32 ", " + "ssn->client.next_seq %" PRIu32 ", ssn->client.last_ack " + "%"PRIu32"", ssn, ssn->client.isn, ssn->client.next_seq, + ssn->client.last_ack); break; } case TH_SYN|TH_ACK: @@ -365,7 +406,8 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p, StreamTcpThread * } /* set the state */ StreamTcpPacketSetState(p, ssn, TCP_SYN_RECV); - SCLogDebug("ssn %p: =~ midstream picked ssn state is now TCP_SYN_RECV", ssn); + SCLogDebug("ssn %p: =~ midstream picked ssn state is now " + "TCP_SYN_RECV", ssn); ssn->flags |= STREAMTCP_FLAG_MIDSTREAM; /* Flag used to change the direct in the later stage in the session */ ssn->flags |= STREAMTCP_FLAG_MIDSTREAM_SYNACK; @@ -390,16 +432,23 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p, StreamTcpThread * ssn->server.wscale = TCP_WSCALE_MAX; } - SCLogDebug("ssn %p: ssn->client.isn %"PRIu32", ssn->client.next_seq %"PRIu32", ssn->client.last_ack %"PRIu32"", - ssn, ssn->client.isn, ssn->client.next_seq, ssn->client.last_ack); - SCLogDebug("ssn %p: ssn->server.isn %"PRIu32", ssn->server.next_seq %"PRIu32", ssn->server.last_ack %"PRIu32"", - ssn, ssn->server.isn, ssn->server.next_seq, ssn->server.last_ack); - - /*Set the timestamp value for both streams, if packet has timestamp option enabled.*/ + SCLogDebug("ssn %p: ssn->client.isn %"PRIu32", ssn->client.next_seq" + " %"PRIu32", ssn->client.last_ack %"PRIu32"", ssn, + ssn->client.isn, ssn->client.next_seq, + ssn->client.last_ack); + SCLogDebug("ssn %p: ssn->server.isn %"PRIu32", ssn->server.next_seq" + " %"PRIu32", ssn->server.last_ack %"PRIu32"", ssn, + ssn->server.isn, ssn->server.next_seq, + ssn->server.last_ack); + + /* Set the timestamp value for both streams, if packet has timestamp + * option enabled.*/ if (p->tcpvars.ts != NULL) { ssn->server.last_ts = TCP_GET_TSVAL(p); ssn->client.last_ts = TCP_GET_TSECR(p); - SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32" ssn->client.last_ts %" PRIu32"", ssn, ssn->server.last_ts, ssn->client.last_ts); + SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32" " + "ssn->client.last_ts %" PRIu32"", ssn, + ssn->server.last_ts, ssn->client.last_ts); ssn->flags |= STREAMTCP_FLAG_TIMESTAMP; @@ -415,7 +464,8 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p, StreamTcpThread * } break; - /* Handle SYN/ACK and 3WHS shake missed together as it is almost similar. */ + /* Handle SYN/ACK and 3WHS shake missed together as it is almost + * similar. */ case TH_ACK: case TH_ACK|TH_PUSH: if (stream_config.midstream == FALSE) @@ -428,7 +478,8 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p, StreamTcpThread * } /* set the state */ StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED); - SCLogDebug("ssn %p: =~ midstream picked ssn state is now TCP_ESTABLISHED", ssn); + SCLogDebug("ssn %p: =~ midstream picked ssn state is now " + "TCP_ESTABLISHED", ssn); ssn->flags = STREAMTCP_FLAG_MIDSTREAM; ssn->flags |= STREAMTCP_FLAG_MIDSTREAM_ESTABLISHED; @@ -449,21 +500,26 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p, StreamTcpThread * ssn->server.last_ack = TCP_GET_ACK(p); ssn->server.next_win = ssn->server.last_ack; - SCLogDebug("ssn %p: ssn->client.next_win %"PRIu32", ssn->server.next_win %"PRIu32"", - ssn, ssn->client.next_win, ssn->server.next_win); - SCLogDebug("ssn %p: ssn->client.last_ack %"PRIu32", ssn->server.last_ack %"PRIu32"", - ssn, ssn->client.last_ack, ssn->server.last_ack); + SCLogDebug("ssn %p: ssn->client.next_win %"PRIu32", " + "ssn->server.next_win %"PRIu32"", ssn, + ssn->client.next_win, ssn->server.next_win); + SCLogDebug("ssn %p: ssn->client.last_ack %"PRIu32", " + "ssn->server.last_ack %"PRIu32"", ssn, + ssn->client.last_ack, ssn->server.last_ack); /** window scaling for midstream pickups, we can't do much other * than assume that it's set to the max value: 14 */ ssn->client.wscale = TCP_WSCALE_MAX; ssn->server.wscale = TCP_WSCALE_MAX; - /*Set the timestamp value for both streams, if packet has timestamp option enabled.*/ + /* Set the timestamp value for both streams, if packet has timestamp + * option enabled.*/ if (p->tcpvars.ts != NULL) { ssn->client.last_ts = TCP_GET_TSVAL(p); ssn->server.last_ts = TCP_GET_TSECR(p); - SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32" ssn->client.last_ts %" PRIu32"", ssn, ssn->server.last_ts, ssn->client.last_ts); + SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32" " + "ssn->client.last_ts %" PRIu32"", ssn, + ssn->server.last_ts, ssn->client.last_ts); ssn->flags |= STREAMTCP_FLAG_TIMESTAMP; @@ -478,9 +534,11 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p, StreamTcpThread * ssn->client.last_ts = 0; } - /*If no stream reassembly/application layer protocol inspection, then simple return*/ + /* If no stream reassembly/application layer protocol inspection, + * then simple return */ if (! (ssn->flags & STREAMTCP_FLAG_NOCLIENT_REASSEMBLY)) - StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->client, p); + StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->client, + p); break; case TH_RST: @@ -504,26 +562,31 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p, StreamTcpThread * * SYN, SYN/ACK, RSTpackets and correspondingly changes the connection * state. * - * \param tv Thread Variable containig input/output queue, cpu affinity etc. + * \param tv Thread Variable containig input/output queue, cpu affinity * \param p Packet which has to be handled in this TCP state. * \param stt Strean Thread module registered to handle the stream handling */ -static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn) { +static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, + StreamTcpThread *stt, TcpSession *ssn) +{ if (ssn == NULL) return -1; - SCLogDebug("ssn %p: pkt received: %s", ssn, PKT_IS_TOCLIENT(p) ? "toclient":"toserver"); + SCLogDebug("ssn %p: pkt received: %s", ssn, PKT_IS_TOCLIENT(p) ? + "toclient":"toserver"); switch (p->tcph->th_flags) { case TH_SYN: SCLogDebug("ssn %p: SYN packet on state SYN_SENT... resent", ssn); if (ssn->flags & STREAMTCP_FLAG_4WHS) - SCLogDebug("ssn %p: SYN packet on state SYN_SENT... resent of 4WHS SYN", ssn); + SCLogDebug("ssn %p: SYN packet on state SYN_SENT... resent of " + "4WHS SYN", ssn); if (PKT_IS_TOCLIENT(p)) { /** a SYN only packet in the opposite direction could be: - * http://www.breakingpointsystems.com/community/blog/tcp-portals-the-three-way-handshake-is-a-lie + * http://www.breakingpointsystems.com/community/blog/tcp- + * portals-the-three-way-handshake-is-a-lie * * \todo improve resetting the session */ @@ -539,10 +602,12 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea ssn->server.ra_base_seq = ssn->server.isn; ssn->server.next_seq = ssn->server.isn + 1; - /* Set the stream timestamp value, if packet has timestamp option enabled. */ + /* Set the stream timestamp value, if packet has timestamp + * option enabled. */ if (p->tcpvars.ts != NULL) { ssn->server.last_ts = TCP_GET_TSVAL(p); - SCLogDebug("ssn %p: p->tcpvars.ts %p, %02x", ssn, p->tcpvars.ts, ssn->server.last_ts); + SCLogDebug("ssn %p: p->tcpvars.ts %p, %02x", ssn, + p->tcpvars.ts, ssn->server.last_ts); if (ssn->server.last_ts == 0) ssn->server.flags |= STREAMTCP_FLAG_ZERO_TIMESTAMP; @@ -556,10 +621,16 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea ssn->server.wscale = TCP_GET_WSCALE(p); } - SCLogDebug("ssn %p: 4WHS ssn->server.isn %" PRIu32 ", ssn->server.next_seq %" PRIu32 ", ssn->server.last_ack %"PRIu32"", - ssn, ssn->server.isn, ssn->server.next_seq, ssn->server.last_ack); - SCLogDebug("ssn %p: 4WHS ssn->client.isn %" PRIu32 ", ssn->client.next_seq %" PRIu32 ", ssn->client.last_ack %"PRIu32"", - ssn, ssn->client.isn, ssn->client.next_seq, ssn->client.last_ack); + SCLogDebug("ssn %p: 4WHS ssn->server.isn %" PRIu32 ", " + "ssn->server.next_seq %" PRIu32 ", " + "ssn->server.last_ack %"PRIu32"", ssn, + ssn->server.isn, ssn->server.next_seq, + ssn->server.last_ack); + SCLogDebug("ssn %p: 4WHS ssn->client.isn %" PRIu32 ", " + "ssn->client.next_seq %" PRIu32 ", " + "ssn->client.last_ack %"PRIu32"", ssn, + ssn->client.isn, ssn->client.next_seq, + ssn->client.last_ack); } break; @@ -570,15 +641,18 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea /* Check if the SYN/ACK packet ack's the earlier * received SYN packet. */ if (!(SEQ_EQ(TCP_GET_ACK(p), ssn->server.isn + 1))) { - SCLogDebug("ssn %p: 4WHS ACK mismatch, packet ACK %" PRIu32 " != %" PRIu32 " from stream", - ssn, TCP_GET_ACK(p), ssn->server.isn + 1); + SCLogDebug("ssn %p: 4WHS ACK mismatch, packet ACK %"PRIu32"" + " != %" PRIu32 " from stream", ssn, + TCP_GET_ACK(p), ssn->server.isn + 1); return -1; } - /* Check if the SYN/ACK packet SEQ's the *FIRST* received SYN packet. */ + /* Check if the SYN/ACK packet SEQ's the *FIRST* received SYN + * packet. */ if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->client.isn))) { - SCLogDebug("ssn %p: 4WHS SEQ mismatch, packet SEQ %" PRIu32 " != %" PRIu32 " from *first* SYN pkt", - ssn, TCP_GET_SEQ(p), ssn->client.isn); + SCLogDebug("ssn %p: 4WHS SEQ mismatch, packet SEQ %"PRIu32"" + " != %" PRIu32 " from *first* SYN pkt", ssn, + TCP_GET_SEQ(p), ssn->client.isn); return -1; } @@ -593,13 +667,18 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea ssn->client.next_seq = ssn->client.isn + 1; ssn->server.window = TCP_GET_WINDOW(p); - SCLogDebug("ssn %p: 4WHS window %" PRIu32 "", ssn, ssn->client.window); - - /* Set the timestamp values used to validate the timestamp of received - packets. */ - if ((p->tcpvars.ts != NULL) && (ssn->server.flags & STREAMTCP_FLAG_TIMESTAMP)) { + SCLogDebug("ssn %p: 4WHS window %" PRIu32 "", ssn, + ssn->client.window); + + /* Set the timestamp values used to validate the timestamp of + * received packets. */ + if ((p->tcpvars.ts != NULL) && (ssn->server.flags & + STREAMTCP_FLAG_TIMESTAMP)) + { ssn->client.last_ts = TCP_GET_TSVAL(p); - SCLogDebug("ssn %p: 4WHS ssn->client.last_ts %" PRIu32" ssn->server.last_ts %" PRIu32"", ssn, ssn->client.last_ts, ssn->server.last_ts); + SCLogDebug("ssn %p: 4WHS ssn->client.last_ts %" PRIu32" " + "ssn->server.last_ts %" PRIu32"", ssn, + ssn->client.last_ts, ssn->server.last_ts); ssn->server.flags &= ~STREAMTCP_FLAG_TIMESTAMP; ssn->flags |= STREAMTCP_FLAG_TIMESTAMP; ssn->client.last_pkt_ts = p->ts.tv_sec; @@ -617,7 +696,9 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea /** check for the presense of the ws ptr to determine if we * support wscale at all */ - if (ssn->flags & STREAMTCP_FLAG_SERVER_WSCALE && p->tcpvars.ws != NULL) { + if ((ssn->flags & STREAMTCP_FLAG_SERVER_WSCALE) && + (p->tcpvars.ws != NULL)) + { ssn->server.wscale = TCP_GET_WSCALE(p); } else { ssn->server.wscale = 0; @@ -625,10 +706,16 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea ssn->client.next_win = ssn->client.last_ack + ssn->client.window; ssn->server.next_win = ssn->server.last_ack + ssn->server.window; - SCLogDebug("ssn %p: 4WHS ssn->client.next_win %" PRIu32 "", ssn, ssn->client.next_win); - SCLogDebug("ssn %p: 4WHS ssn->server.next_win %" PRIu32 "", ssn, ssn->server.next_win); - SCLogDebug("ssn %p: 4WHS ssn->client.isn %" PRIu32 ", ssn->client.next_seq %" PRIu32 ", ssn->client.last_ack %" PRIu32 " (ssn->server.last_ack %" PRIu32 ")", - ssn, ssn->client.isn, ssn->client.next_seq, ssn->client.last_ack, ssn->server.last_ack); + SCLogDebug("ssn %p: 4WHS ssn->client.next_win %" PRIu32 "", ssn, + ssn->client.next_win); + SCLogDebug("ssn %p: 4WHS ssn->server.next_win %" PRIu32 "", ssn, + ssn->server.next_win); + SCLogDebug("ssn %p: 4WHS ssn->client.isn %" PRIu32 ", " + "ssn->client.next_seq %" PRIu32 ", " + "ssn->client.last_ack %" PRIu32 " " + "(ssn->server.last_ack %" PRIu32 ")", ssn, + ssn->client.isn, ssn->client.next_seq, + ssn->client.last_ack, ssn->server.last_ack); /* done here */ break; @@ -642,8 +729,9 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea /* Check if the SYN/ACK packet ack's the earlier * received SYN packet. */ if (!(SEQ_EQ(TCP_GET_ACK(p), ssn->client.isn + 1))) { - SCLogDebug("ssn %p: ACK mismatch, packet ACK %" PRIu32 " != %" PRIu32 " from stream", - ssn, TCP_GET_ACK(p), ssn->client.isn + 1); + SCLogDebug("ssn %p: ACK mismatch, packet ACK %" PRIu32 " != " + "%" PRIu32 " from stream", ssn, TCP_GET_ACK(p), + ssn->client.isn + 1); return -1; } @@ -659,11 +747,15 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea ssn->client.window = TCP_GET_WINDOW(p); SCLogDebug("ssn %p: window %" PRIu32 "", ssn, ssn->server.window); - /*Set the timestamp values used to validate the timestamp of received - packets.*/ - if ((p->tcpvars.ts != NULL) && (ssn->client.flags & STREAMTCP_FLAG_TIMESTAMP)) { + /* Set the timestamp values used to validate the timestamp of + * received packets.*/ + if ((p->tcpvars.ts != NULL) && + (ssn->client.flags & STREAMTCP_FLAG_TIMESTAMP)) + { ssn->server.last_ts = TCP_GET_TSVAL(p); - SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32" ssn->client.last_ts %" PRIu32"", ssn, ssn->server.last_ts, ssn->client.last_ts); + SCLogDebug("ssn %p: ssn->server.last_ts %" PRIu32" " + "ssn->client.last_ts %" PRIu32"", ssn, + ssn->server.last_ts, ssn->client.last_ts); ssn->client.flags &= ~STREAMTCP_FLAG_TIMESTAMP; ssn->flags |= STREAMTCP_FLAG_TIMESTAMP; ssn->server.last_pkt_ts = p->ts.tv_sec; @@ -681,7 +773,9 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea /** check for the presense of the ws ptr to determine if we * support wscale at all */ - if (ssn->flags & STREAMTCP_FLAG_SERVER_WSCALE && p->tcpvars.ws != NULL) { + if ((ssn->flags & STREAMTCP_FLAG_SERVER_WSCALE) && + (p->tcpvars.ws != NULL)) + { ssn->client.wscale = TCP_GET_WSCALE(p); } else { ssn->client.wscale = 0; @@ -689,15 +783,22 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea ssn->server.next_win = ssn->server.last_ack + ssn->server.window; ssn->client.next_win = ssn->client.last_ack + ssn->client.window; - SCLogDebug("ssn %p: ssn->server.next_win %" PRIu32 "", ssn, ssn->server.next_win); - SCLogDebug("ssn %p: ssn->client.next_win %" PRIu32 "", ssn, ssn->client.next_win); - SCLogDebug("ssn %p: ssn->server.isn %" PRIu32 ", ssn->server.next_seq %" PRIu32 ", ssn->server.last_ack %" PRIu32 " (ssn->client.last_ack %" PRIu32 ")", - ssn, ssn->server.isn, ssn->server.next_seq, ssn->server.last_ack, ssn->client.last_ack); + SCLogDebug("ssn %p: ssn->server.next_win %" PRIu32 "", ssn, + ssn->server.next_win); + SCLogDebug("ssn %p: ssn->client.next_win %" PRIu32 "", ssn, + ssn->client.next_win); + SCLogDebug("ssn %p: ssn->server.isn %" PRIu32 ", " + "ssn->server.next_seq %" PRIu32 ", " + "ssn->server.last_ack %" PRIu32 " " + "(ssn->client.last_ack %" PRIu32 ")", ssn, + ssn->server.isn, ssn->server.next_seq, + ssn->server.last_ack, ssn->client.last_ack); /* unset the 4WHS flag as we received this SYN/ACK as part of a * (so far) valid 3WHS */ if (ssn->flags & STREAMTCP_FLAG_4WHS) - SCLogDebug("ssn %p: STREAMTCP_FLAG_4WHS unset, normal SYN/ACK so considering 3WHS", ssn); + SCLogDebug("ssn %p: STREAMTCP_FLAG_4WHS unset, normal SYN/ACK" + " so considering 3WHS", ssn); ssn->flags &=~ STREAMTCP_FLAG_4WHS; break; @@ -715,7 +816,8 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea your thoughts ?? It will quite relax then in checking.*/ if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->client.next_seq))) { SCLogDebug("ssn %p: SEQ mismatch, packet SEQ %" PRIu32 " != " - "%" PRIu32 " from stream",ssn, TCP_GET_SEQ(p), ssn->client.next_seq); + "%" PRIu32 " from stream",ssn, TCP_GET_SEQ(p), + ssn->client.next_seq); return -1; } @@ -735,9 +837,9 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea ssn->server.next_win = ssn->server.last_ack; SCLogDebug("ssn %p: synsent => Asynchronous stream, packet SEQ" - " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "), " + " %" PRIu32 ", payload size %" PRIu32 " (%" PRIu32 "), " "ssn->client.next_seq %" PRIu32 "" - , ssn, TCP_GET_SEQ(p), p->payload_len, TCP_GET_SEQ(p) + ,ssn, TCP_GET_SEQ(p), p->payload_len, TCP_GET_SEQ(p) + p->payload_len, ssn->client.next_seq); ssn->client.wscale = TCP_WSCALE_MAX; @@ -745,7 +847,9 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea /*Set the timestamp values used to validate the timestamp of received packets.*/ - if (p->tcpvars.ts != NULL && (ssn->client.flags & STREAMTCP_FLAG_TIMESTAMP)) { + if (p->tcpvars.ts != NULL && + (ssn->client.flags & STREAMTCP_FLAG_TIMESTAMP)) + { ssn->flags |= STREAMTCP_FLAG_TIMESTAMP; ssn->client.flags &= ~STREAMTCP_FLAG_TIMESTAMP; ssn->client.last_pkt_ts = p->ts.tv_sec; @@ -759,8 +863,14 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea case TH_RST: case TH_RST|TH_ACK: if(ValidReset(ssn, p)){ - if(SEQ_EQ(TCP_GET_SEQ(p), ssn->client.isn) && SEQ_EQ(TCP_GET_WINDOW(p), 0) && SEQ_EQ(TCP_GET_ACK(p), (ssn->client.isn + 1))) { + if(SEQ_EQ(TCP_GET_SEQ(p), ssn->client.isn) && + SEQ_EQ(TCP_GET_WINDOW(p), 0) && + SEQ_EQ(TCP_GET_ACK(p), (ssn->client.isn + 1))) + { StreamTcpPacketSetState(p, ssn, TCP_CLOSED); + SCLogDebug("ssn %p: Reset received and state changed to " + "TCP_CLOSED", ssn); + StreamTcpSessionPktFree(p); } } else return -1; @@ -778,12 +888,14 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea * SYN, SYN/ACK, ACK, FIN, RST packets and correspondingly changes * the connection state. * - * \param tv Thread Variable containig input/output queue, cpu affinity etc. + * \param tv Thread Variable containig input/output queue, cpu affinity * \param p Packet which has to be handled in this TCP state. * \param stt Strean Thread module registered to handle the stream handling */ -static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn) { +static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p, + StreamTcpThread *stt, TcpSession *ssn) +{ if (ssn == NULL) return -1; @@ -792,13 +904,14 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p, StreamTcpThrea SCLogDebug("ssn %p: SYN packet on state SYN_RECV... resent", ssn); break; case TH_SYN|TH_ACK: - SCLogDebug("ssn %p: SYN/ACK packet on state SYN_RECV... resent", ssn); + SCLogDebug("ssn %p: SYN/ACK packet on state SYN_RECV. resent", ssn); break; case TH_ACK: case TH_ACK|TH_PUSH: - /* If the timestamp option is enabled for both the streams, then validate the received packet - timestamp value against the stream->last_ts. If the timestamp is valid then process the packet normally - otherwise the drop the packet (RFC 1323)*/ + /* If the timestamp option is enabled for both the streams, then + * validate the received packet timestamp value against the + * stream->last_ts. If the timestamp is valid then process the + * packet normally otherwise the drop the packet (RFC 1323)*/ if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) { if (!ValidTimestamp(ssn, p)) return -1; @@ -814,24 +927,29 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p, StreamTcpThrea ssn->server.next_seq += p->payload_len; ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale; - ssn->client.next_win = ssn->client.last_ack + ssn->client.window; + ssn->client.next_win = ssn->client.last_ack + + ssn->client.window; - /*If no stream reassembly/application layer protocol inspection, then simple return*/ + /* If no stream reassembly/application layer protocol + * inspection, then simple return*/ if (!(ssn->flags & STREAMTCP_FLAG_NOSERVER_REASSEMBLY)) - StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->server, p); + StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, + &ssn->server, p); } else { SCLogDebug("ssn %p: 4WHS wrong seq nr on packet", ssn); return -1; } - SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ %" PRIu32 ", ACK %" PRIu32 "", - ssn, p->payload_len, TCP_GET_SEQ(p), TCP_GET_ACK(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)); StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED); SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn); - SCLogDebug("ssn %p: ssn->client.next_win %" PRIu32 ", ssn->client.last_ack %"PRIu32"", - ssn, ssn->client.next_win, ssn->client.last_ack); + SCLogDebug("ssn %p: ssn->client.next_win %" PRIu32 ", " + "ssn->client.last_ack %"PRIu32"", ssn, + ssn->client.next_win, ssn->client.last_ack); break; } @@ -841,12 +959,15 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p, StreamTcpThrea * case) or from server itself (asynchronous streams). Therefore * the check has been avoided in this case */ if (PKT_IS_TOCLIENT(p)) { - /* special case, handle 4WHS, so SYN/ACK in the opposite direction */ + /* special case, handle 4WHS, so SYN/ACK in the opposite + * direction */ if (ssn->flags & STREAMTCP_FLAG_MIDSTREAM_SYNACK) { - SCLogDebug("ssn %p: ACK received on midstream SYN/ACK pickup session",ssn); + SCLogDebug("ssn %p: ACK received on midstream SYN/ACK " + "pickup session",ssn); /* fall through */ } else { - SCLogDebug("ssn %p: ACK received in the wrong direction",ssn); + SCLogDebug("ssn %p: ACK received in the wrong direction", + ssn); return -1; } } @@ -864,22 +985,25 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p, StreamTcpThrea if (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) { ssn->client.window = TCP_GET_WINDOW(p); - ssn->server.next_win = ssn->server.last_ack + ssn->server.window; - /** window scaling for midstream pickups, we can't do much other - * than assume that it's set to the max value: 14 */ + ssn->server.next_win = ssn->server.last_ack + + ssn->server.window; + /* window scaling for midstream pickups, we can't do much + * other than assume that it's set to the max value: 14 */ ssn->server.wscale = TCP_WSCALE_MAX; ssn->client.wscale = TCP_WSCALE_MAX; } - /*If no stream reassembly/application layer protocol inspection, then simple return*/ + /* If no stream reassembly/application layer protocol inspection + * then simple return*/ if (!(ssn->flags & STREAMTCP_FLAG_NOCLIENT_REASSEMBLY)) - StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->client, p); + StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, + &ssn->client, p); /* If asynchronous stream handling is allowed then set the session, if packet's seq number is equal the expected seq no.*/ } else if (stream_config.async_oneside == TRUE && - (SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq))) { - + (SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq))) + { /*set the ASYNC flag used to indicate the session as async stream and helps in relaxing the windows checks.*/ ssn->flags |= STREAMTCP_FLAG_ASYNC; @@ -891,9 +1015,10 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p, StreamTcpThrea if (ssn->flags & STREAMTCP_FLAG_MIDSTREAM) { ssn->server.window = TCP_GET_WINDOW(p); - ssn->client.next_win = ssn->server.last_ack + ssn->server.window; - /** window scaling for midstream pickups, we can't do much other - * than assume that it's set to the max value: 14 */ + ssn->client.next_win = ssn->server.last_ack + + ssn->server.window; + /* window scaling for midstream pickups, we can't do much + * other than assume that it's set to the max value: 14 */ ssn->server.wscale = TCP_WSCALE_MAX; ssn->client.wscale = TCP_WSCALE_MAX; } @@ -904,22 +1029,27 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p, StreamTcpThrea , ssn, TCP_GET_SEQ(p), p->payload_len, TCP_GET_SEQ(p) + p->payload_len, ssn->server.next_seq); - /*If no stream reassembly/application layer protocol inspection, then simple return*/ + /* If no stream reassembly/application layer protocol inspection + * then simple return*/ if (!(ssn->flags & STREAMTCP_FLAG_NOSERVER_REASSEMBLY)) - StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->server, p); + StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, + &ssn->server, p); } else { SCLogDebug("ssn %p: wrong seq nr on packet", ssn); return -1; } - SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 ", ACK %" PRIu32 "", - ssn, p->payload_len, TCP_GET_SEQ(p), TCP_GET_ACK(p)); + SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 "" + ", ACK %" PRIu32 "", ssn, p->payload_len, TCP_GET_SEQ(p), + TCP_GET_ACK(p)); StreamTcpPacketSetState(p, ssn, TCP_ESTABLISHED); SCLogDebug("ssn %p: =~ ssn state is now TCP_ESTABLISHED", ssn); - SCLogDebug("ssn %p: ssn->server.next_win %" PRIu32 ", ssn->server.last_ack %"PRIu32"", ssn, ssn->server.next_win, ssn->server.last_ack); + SCLogDebug("ssn %p: ssn->server.next_win %" PRIu32 ", " + "ssn->server.last_ack %"PRIu32"", ssn, + ssn->server.next_win, ssn->server.last_ack); break; case TH_RST: @@ -927,6 +1057,10 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p, StreamTcpThrea if(ValidReset(ssn, p)) { StreamTcpPacketSetState(p, ssn, TCP_CLOSED); + SCLogDebug("ssn %p: Reset received and state changed to " + "TCP_CLOSED", ssn); + + StreamTcpSessionPktFree(p); } else return -1; break; @@ -1187,7 +1321,10 @@ static int HandleEstablishedPacketToClient(TcpSession *ssn, Packet *p, * \param stt Strean Thread module registered to handle the stream handling */ -static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn) { +static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p, + StreamTcpThread *stt, + TcpSession *ssn) +{ if (ssn == NULL) return -1; @@ -1196,7 +1333,8 @@ static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p, StreamTcpT SCLogDebug("ssn %p: SYN packet on state ESTABLISED... resent", ssn); break; case TH_SYN|TH_ACK: - SCLogDebug("ssn %p: SYN/ACK packet on state ESTABLISHED... resent", ssn); + SCLogDebug("ssn %p: SYN/ACK packet on state ESTABLISHED... resent", + ssn); break; case TH_ACK: case TH_ACK|TH_PUSH: @@ -1239,8 +1377,11 @@ static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p, StreamTcpT return -1; } - SCLogDebug("StreamTcpPacketStateEstablished (%p): FIN received SEQ %" PRIu32 ", last ACK %" PRIu32 ", next win %" PRIu32 ", win %" PRIu32 "", - ssn, ssn->server.next_seq, ssn->client.last_ack, ssn->server.next_win, ssn->server.window); + SCLogDebug("StreamTcpPacketStateEstablished (%p): FIN received SEQ" + " %" PRIu32 ", last ACK %" PRIu32 ", next win %"PRIu32"," + " win %" PRIu32 "", ssn, ssn->server.next_seq, + ssn->client.last_ack, ssn->server.next_win, + ssn->server.window); if((StreamTcpHandleFin(stt, ssn, p)) == -1) return -1; @@ -1251,37 +1392,48 @@ static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p, StreamTcpT if(ValidReset(ssn, p)) { if(PKT_IS_TOSERVER(p)) { StreamTcpPacketSetState(p, ssn, TCP_CLOSED); - SCLogDebug("ssn %p: Reset received and state changed to TCP_CLOSED", ssn); + SCLogDebug("ssn %p: Reset received and state changed to " + "TCP_CLOSED", ssn); ssn->client.next_seq = TCP_GET_ACK(p); ssn->server.next_seq = TCP_GET_SEQ(p) + p->payload_len + 1; - SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", ssn, ssn->server.next_seq); + SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", ssn, + ssn->server.next_seq); ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.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_NOCLIENT_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); + 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); + StreamTcpSessionPktFree(p); } else { StreamTcpPacketSetState(p, ssn, TCP_CLOSED); - SCLogDebug("ssn %p: Reset received and state changed to TCP_CLOSED", ssn); + SCLogDebug("ssn %p: Reset received and state changed to " + "TCP_CLOSED", ssn); ssn->server.next_seq = TCP_GET_SEQ(p) + p->payload_len + 1; ssn->client.next_seq = TCP_GET_ACK(p); - SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", ssn, ssn->server.next_seq); + SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", ssn, + ssn->server.next_seq); ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale; if (SEQ_GT(TCP_GET_ACK(p),ssn->client.last_ack)) ssn->client.last_ack = TCP_GET_ACK(p); if (!(ssn->flags & STREAMTCP_FLAG_NOSERVER_REASSEMBLY)) - StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->server, p); - SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK %" PRIu32 "", - ssn, ssn->server.next_seq, ssn->client.last_ack); + StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, + &ssn->server, p); + SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK " + "%" PRIu32 "", ssn, ssn->server.next_seq, + ssn->client.last_ack); + + StreamTcpSessionPktFree(p); } } else return -1; @@ -1297,29 +1449,35 @@ static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p, StreamTcpT * \brief Function to handle the FIN packets for states TCP_SYN_RECV and * TCP_ESTABLISHED and changes to another TCP state as required. * - * \param tv Thread Variable containig input/output queue, cpu affinity etc. + * \param tv Thread Variable containig input/output queue, cpu affinity * \param p Packet which has to be handled in this TCP state. * \param stt Strean Thread module registered to handle the stream handling */ -static int StreamTcpHandleFin(StreamTcpThread *stt, TcpSession *ssn, Packet *p) { +static int StreamTcpHandleFin(StreamTcpThread *stt, TcpSession *ssn, Packet *p) +{ if (PKT_IS_TOSERVER(p)) { - SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 ", ACK %" PRIu32 "", - ssn, p->payload_len, TCP_GET_SEQ(p), TCP_GET_ACK(p)); + 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); + 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); return -1; } StreamTcpPacketSetState(p, ssn, TCP_CLOSE_WAIT); SCLogDebug("ssn %p: state changed to TCP_CLOSE_WAIT", ssn); - ssn->client.next_seq = TCP_GET_ACK(p); - ssn->server.next_seq = TCP_GET_SEQ(p) + p->payload_len + 1; - SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", ssn, ssn->server.next_seq); + ssn->client.next_seq = TCP_GET_SEQ(p) + p->payload_len + 1; + ssn->server.next_seq = TCP_GET_ACK(p); + SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", ssn, + ssn->server.next_seq); ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale; if (SEQ_GT(TCP_GET_ACK(p),ssn->server.last_ack)) @@ -1331,11 +1489,16 @@ static int StreamTcpHandleFin(StreamTcpThread *stt, TcpSession *ssn, Packet *p) SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK %" PRIu32 "", ssn, ssn->client.next_seq, ssn->server.last_ack); } else { /* implied to client */ - 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->server.next_seq) || SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + ssn->server.window))) { - SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != %" PRIu32 " from stream", - ssn, TCP_GET_SEQ(p), ssn->server.next_seq); + 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->server.next_seq) || + SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + + ssn->server.window))) + { + SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != " + "%" PRIu32 " from stream", ssn, TCP_GET_SEQ(p), + ssn->server.next_seq); return -1; } @@ -1344,7 +1507,8 @@ static int StreamTcpHandleFin(StreamTcpThread *stt, TcpSession *ssn, Packet *p) ssn->server.next_seq = TCP_GET_SEQ(p) + p->payload_len + 1; ssn->client.next_seq = TCP_GET_ACK(p); - SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", ssn, ssn->server.next_seq); + SCLogDebug("ssn %p: ssn->server.next_seq %" PRIu32 "", ssn, + ssn->server.next_seq); ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale; if (SEQ_GT(TCP_GET_ACK(p),ssn->client.last_ack)) @@ -1364,12 +1528,14 @@ static int StreamTcpHandleFin(StreamTcpThread *stt, TcpSession *ssn, Packet *p) * ACK, FIN, RST packets and correspondingly changes the connection * state. * - * \param tv Thread Variable containig input/output queue, cpu affinity etc. + * \param tv Thread Variable containig input/output queue, cpu affinity * \param p Packet which has to be handled in this TCP state. * \param stt Strean Thread module registered to handle the stream handling */ -static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn) { +static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, + StreamTcpThread *stt, TcpSession *ssn) +{ if (ssn == NULL) return -1; @@ -1382,8 +1548,9 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, StreamTcpThre } if (PKT_IS_TOSERVER(p)) { - SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 ", ACK %" PRIu32 "", - ssn, p->payload_len, TCP_GET_SEQ(p), TCP_GET_ACK(p)); + SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ " + "%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len, + TCP_GET_SEQ(p), TCP_GET_ACK(p)); StreamTcpPacketSetState(p, ssn, TCP_FIN_WAIT2); SCLogDebug("ssn %p: state changed to TCP_FIN_WAIT2", ssn); @@ -1394,13 +1561,17 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, StreamTcpThre ssn->server.last_ack = TCP_GET_ACK(p); if (! (ssn->flags & STREAMTCP_FLAG_NOCLIENT_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); + 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); } else { /* implied to client */ - SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ %" PRIu32 ", ACK %" PRIu32 "", - ssn, p->payload_len, TCP_GET_SEQ(p), TCP_GET_ACK(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)); StreamTcpPacketSetState(p, ssn, TCP_FIN_WAIT2); + SCLogDebug("ssn %p: state changed to TCP_FIN_WAIT2", ssn); ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale; @@ -1408,9 +1579,11 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, StreamTcpThre ssn->client.last_ack = TCP_GET_ACK(p); if (!(ssn->flags & STREAMTCP_FLAG_NOSERVER_REASSEMBLY)) - StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->server, p); - SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK %" PRIu32 "", - ssn, ssn->server.next_seq, ssn->client.last_ack); + StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, + &ssn->server, p); + SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK " + "%" PRIu32 "", ssn, ssn->server.next_seq, + ssn->client.last_ack); } break; case TH_FIN: @@ -1423,12 +1596,17 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, StreamTcpThre } if (PKT_IS_TOSERVER(p)) { - 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); + 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); return -1; } @@ -1441,16 +1619,23 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, StreamTcpThre ssn->server.last_ack = TCP_GET_ACK(p); if (! (ssn->flags & STREAMTCP_FLAG_NOCLIENT_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); + 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); } else { /* implied to client */ - 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->server.next_seq) || SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + ssn->server.window))) { - SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != %" PRIu32 " from stream", - ssn, TCP_GET_SEQ(p), ssn->server.next_seq); + 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->server.next_seq) || + SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + + ssn->server.window))) + { + SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 "" + " != %" PRIu32 " from stream", ssn, + TCP_GET_SEQ(p), ssn->server.next_seq); return -1; } @@ -1463,9 +1648,11 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, StreamTcpThre ssn->client.last_ack = TCP_GET_ACK(p); if (!(ssn->flags & STREAMTCP_FLAG_NOSERVER_REASSEMBLY)) - StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->server, p); - SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK %" PRIu32 "", - ssn, ssn->server.next_seq, ssn->client.last_ack); + StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, + &ssn->server, p); + SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK " + "%" PRIu32 "", ssn, ssn->server.next_seq, + ssn->client.last_ack); } break; case TH_RST: @@ -1473,7 +1660,10 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, StreamTcpThre if(ValidReset(ssn, p)) { StreamTcpPacketSetState(p, ssn, TCP_CLOSED); - SCLogDebug("ssn %p: Reset received state changed to TCP_CLOSED", ssn); + SCLogDebug("ssn %p: Reset received state changed to TCP_CLOSED", + ssn); + + StreamTcpSessionPktFree(p); } else return -1; @@ -1491,12 +1681,14 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, StreamTcpThre * ACK, RST, FIN packets and correspondingly changes the connection * state. * - * \param tv Thread Variable containig input/output queue, cpu affinity etc. + * \param tv Thread Variable containig input/output queue, cpu affinity * \param p Packet which has to be handled in this TCP state. * \param stt Strean Thread module registered to handle the stream handling */ -static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn) { +static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p, + StreamTcpThread *stt, TcpSession *ssn) +{ if (ssn == NULL) return -1; @@ -1509,12 +1701,14 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p, StreamTcpThre } if (PKT_IS_TOSERVER(p)) { - SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 ", ACK %" PRIu32 "", - ssn, p->payload_len, TCP_GET_SEQ(p), TCP_GET_ACK(p)); + 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 (TCP_GET_SEQ(p) != ssn->client.next_seq) { - SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != %" PRIu32 " from stream", - ssn, TCP_GET_SEQ(p), ssn->client.next_seq); + SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 "" + " != %" PRIu32 " from stream", ssn, + TCP_GET_SEQ(p), ssn->client.next_seq); return -1; } StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT); @@ -1526,16 +1720,20 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p, StreamTcpThre ssn->server.last_ack = TCP_GET_ACK(p); if (! (ssn->flags & STREAMTCP_FLAG_NOCLIENT_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); + 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); } else { /* implied to client */ - SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ %" PRIu32 ", ACK %" PRIu32 "", - ssn, p->payload_len, TCP_GET_SEQ(p), TCP_GET_ACK(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)); if (TCP_GET_SEQ(p) != ssn->server.next_seq) { - SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != %" PRIu32 " from stream", - ssn, TCP_GET_SEQ(p), ssn->server.next_seq); + SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 "" + " != %" PRIu32 " from stream", ssn, + TCP_GET_SEQ(p), ssn->server.next_seq); return -1; } StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT); @@ -1547,9 +1745,11 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p, StreamTcpThre ssn->client.last_ack = TCP_GET_ACK(p); if (!(ssn->flags & STREAMTCP_FLAG_NOSERVER_REASSEMBLY)) - StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->server, p); - SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK %" PRIu32 "", - ssn, ssn->server.next_seq, ssn->client.last_ack); + StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, + &ssn->server, p); + SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK " + "%" PRIu32 "", ssn, ssn->server.next_seq, + ssn->client.last_ack); } break; case TH_RST: @@ -1557,7 +1757,10 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p, StreamTcpThre if(ValidReset(ssn, p)) { StreamTcpPacketSetState(p, ssn, TCP_CLOSED); - SCLogDebug("ssn %p: Reset received state changed to TCP_CLOSED", ssn); + SCLogDebug("ssn %p: Reset received state changed to TCP_CLOSED", + ssn); + + StreamTcpSessionPktFree(p); } else return -1; @@ -1570,12 +1773,17 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p, StreamTcpThre } if (PKT_IS_TOSERVER(p)) { - 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); + 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); return -1; } @@ -1587,17 +1795,24 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p, StreamTcpThre ssn->server.last_ack = TCP_GET_ACK(p); if (! (ssn->flags & STREAMTCP_FLAG_NOCLIENT_REASSEMBLY)) - StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->client, p); + 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); + SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK " + "%" PRIu32 "", ssn, ssn->client.next_seq, + ssn->server.last_ack); } else { /* implied to client */ - 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->server.next_seq) || SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + ssn->server.window))) { - SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != %" PRIu32 " from stream", - ssn, TCP_GET_SEQ(p), ssn->server.next_seq); + 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->server.next_seq) || + SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + + ssn->server.window))) + { + SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ " + "%" PRIu32 " != %" PRIu32 " from stream", ssn, + TCP_GET_SEQ(p), ssn->server.next_seq); return -1; } @@ -1609,9 +1824,11 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p, StreamTcpThre ssn->client.last_ack = TCP_GET_ACK(p); if (!(ssn->flags & STREAMTCP_FLAG_NOSERVER_REASSEMBLY)) - StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->server, p); - SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK %" PRIu32 "", - ssn, ssn->server.next_seq, ssn->client.last_ack); + StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, + &ssn->server, p); + SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK " + "%" PRIu32 "", ssn, ssn->server.next_seq, + ssn->client.last_ack); } break; default: @@ -1627,12 +1844,14 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p, StreamTcpThre * the connection goes to TCP_TIME_WAIT state. The state has been * reached as both end application has been closed. * - * \param tv Thread Variable containig input/output queue, cpu affinity etc. + * \param tv Thread Variable containig input/output queue, cpu affinity * \param p Packet which has to be handled in this TCP state. * \param stt Strean Thread module registered to handle the stream handling */ -static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn) { +static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *p, + StreamTcpThread *stt, TcpSession *ssn) +{ if (ssn == NULL) return -1; @@ -1645,12 +1864,14 @@ static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *p, StreamTcpThrea } if (PKT_IS_TOSERVER(p)) { - SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 ", ACK %" PRIu32 "", - ssn, p->payload_len, TCP_GET_SEQ(p), TCP_GET_ACK(p)); + 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 (TCP_GET_SEQ(p) != ssn->client.next_seq) { - SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != %" PRIu32 " from stream", - ssn, TCP_GET_SEQ(p), ssn->client.next_seq); + SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 "" + " != %" PRIu32 " from stream", ssn, + TCP_GET_SEQ(p), ssn->client.next_seq); return -1; } @@ -1663,16 +1884,20 @@ static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *p, StreamTcpThrea ssn->server.last_ack = TCP_GET_ACK(p); if (! (ssn->flags & STREAMTCP_FLAG_NOCLIENT_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); + 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); } else { /* implied to client */ - SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ %" PRIu32 ", ACK %" PRIu32 "", - ssn, p->payload_len, TCP_GET_SEQ(p), TCP_GET_ACK(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)); if (TCP_GET_SEQ(p) != ssn->server.next_seq) { - SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != %" PRIu32 " from stream", - ssn, TCP_GET_SEQ(p), ssn->server.next_seq); + SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 "" + " != %" PRIu32 " from stream", ssn, + TCP_GET_SEQ(p), ssn->server.next_seq); return -1; } @@ -1684,9 +1909,11 @@ static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *p, StreamTcpThrea ssn->client.last_ack = TCP_GET_ACK(p); if (!(ssn->flags & STREAMTCP_FLAG_NOSERVER_REASSEMBLY)) - StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->server, p); - SCLogDebug("StreamTcpPacketStateClosing (%p): =+ next SEQ %" PRIu32 ", last ACK %" PRIu32 "", - ssn, ssn->server.next_seq, ssn->client.last_ack); + StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, + &ssn->server, p); + SCLogDebug("StreamTcpPacketStateClosing (%p): =+ next SEQ " + "%" PRIu32 ", last ACK %" PRIu32 "", ssn, + ssn->server.next_seq, ssn->client.last_ack); } break; default: @@ -1701,17 +1928,20 @@ static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *p, StreamTcpThrea * packet from server the connection goes to TCP_LAST_ACK state. * The state is possible only for server host. * - * \param tv Thread Variable containig input/output queue, cpu affinity etc. + * \param tv Thread Variable containig input/output queue, cpu affinity * \param p Packet which has to be handled in this TCP state. * \param stt Strean Thread module registered to handle the stream handling */ -static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn) { +static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p, + StreamTcpThread *stt, TcpSession *ssn) +{ if (ssn == NULL) return -1; switch(p->tcph->th_flags) { case TH_FIN: + case TH_FIN|TH_ACK: if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) { if (!ValidTimestamp(ssn, p)) @@ -1719,12 +1949,17 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p, StreamTcpThr } 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)); - - if (SEQ_LT(TCP_GET_SEQ(p), ssn->server.next_seq) || SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + ssn->server.window))) { - SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != %" PRIu32 " from stream", - ssn, TCP_GET_SEQ(p), ssn->server.next_seq); + 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->server.next_seq) || + SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + + ssn->server.window))) + { + SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 "" + " != %" PRIu32 " from stream", ssn, + TCP_GET_SEQ(p), ssn->server.next_seq); return -1; } @@ -1736,11 +1971,45 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p, StreamTcpThr ssn->client.last_ack = TCP_GET_ACK(p); if (!(ssn->flags & STREAMTCP_FLAG_NOSERVER_REASSEMBLY)) - StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->server, p); - SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK %" PRIu32 "", - ssn, ssn->server.next_seq, ssn->client.last_ack); + StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, + &ssn->server, p); + SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK " + "%" PRIu32 "", ssn, ssn->server.next_seq, + ssn->client.last_ack); } break; + case TH_ACK: + if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) { + if (!ValidTimestamp(ssn, p)) + return -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)); + + if (SEQ_LT(TCP_GET_SEQ(p), ssn->server.next_seq) || + SEQ_GT(TCP_GET_SEQ(p), (ssn->server.last_ack + + ssn->server.window))) + { + SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 "" + " != %" PRIu32 " from stream", ssn, + TCP_GET_SEQ(p), ssn->server.next_seq); + return -1; + } + ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale; + + if (SEQ_GT(TCP_GET_ACK(p),ssn->client.last_ack)) + ssn->client.last_ack = TCP_GET_ACK(p); + + if (!(ssn->flags & STREAMTCP_FLAG_NOSERVER_REASSEMBLY)) + StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, + &ssn->server, p); + SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK " + "%" PRIu32 "", ssn, ssn->server.next_seq, + ssn->client.last_ack); + } default: SCLogDebug("ssn %p: default case", ssn); break; @@ -1753,12 +2022,14 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p, StreamTcpThr * the connection goes to TCP_CLOSED state and stream memory is * returned back to pool. The state is possible only for server host. * - * \param tv Thread Variable containig input/output queue, cpu affinity etc. + * \param tv Thread Variable containig input/output queue, cpu affinity * \param p Packet which has to be handled in this TCP state. * \param stt Strean Thread module registered to handle the stream handling */ -static int StreamTcpPakcetStateLastAck(ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn) { +static int StreamTcpPakcetStateLastAck(ThreadVars *tv, Packet *p, + StreamTcpThread *stt, TcpSession *ssn) +{ if (ssn == NULL) return -1; @@ -1771,12 +2042,14 @@ static int StreamTcpPakcetStateLastAck(ThreadVars *tv, Packet *p, StreamTcpThrea } if (PKT_IS_TOSERVER(p)) { - SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 ", ACK %" PRIu32 "", - ssn, p->payload_len, TCP_GET_SEQ(p), TCP_GET_ACK(p)); + 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 (TCP_GET_SEQ(p) != ssn->client.next_seq) { - SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != %" PRIu32 " from stream", - ssn, TCP_GET_SEQ(p), ssn->client.next_seq); + SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 "" + " != %" PRIu32 " from stream", ssn, + TCP_GET_SEQ(p), ssn->client.next_seq); return -1; } @@ -1789,9 +2062,13 @@ static int StreamTcpPakcetStateLastAck(ThreadVars *tv, Packet *p, StreamTcpThrea ssn->server.last_ack = TCP_GET_ACK(p); if (! (ssn->flags & STREAMTCP_FLAG_NOCLIENT_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); + 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); + + StreamTcpSessionPktFree(p); } break; default: @@ -1806,12 +2083,14 @@ static int StreamTcpPakcetStateLastAck(ThreadVars *tv, Packet *p, StreamTcpThrea * the connection goes to TCP_CLOSED state and stream memory is * returned back to pool. * - * \param tv Thread Variable containig input/output queue, cpu affinity etc. + * \param tv Thread Variable containig input/output queue, cpu affinity * \param p Packet which has to be handled in this TCP state. * \param stt Strean Thread module registered to handle the stream handling */ -static int StreamTcpPacketStateTimeWait(ThreadVars *tv, Packet *p, StreamTcpThread *stt, TcpSession *ssn) { +static int StreamTcpPacketStateTimeWait(ThreadVars *tv, Packet *p, + StreamTcpThread *stt, TcpSession *ssn) +{ if (ssn == NULL) return -1; @@ -1824,12 +2103,14 @@ static int StreamTcpPacketStateTimeWait(ThreadVars *tv, Packet *p, StreamTcpThre } if (PKT_IS_TOSERVER(p)) { - SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 ", ACK %" PRIu32 "", - ssn, p->payload_len, TCP_GET_SEQ(p), TCP_GET_ACK(p)); + 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 (TCP_GET_SEQ(p) != ssn->client.next_seq) { - SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != %" PRIu32 " from stream", - ssn, TCP_GET_SEQ(p), ssn->client.next_seq); + SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 "" + " != %" PRIu32 " from stream", ssn, + TCP_GET_SEQ(p), ssn->client.next_seq); return -1; } @@ -1842,16 +2123,22 @@ static int StreamTcpPacketStateTimeWait(ThreadVars *tv, Packet *p, StreamTcpThre ssn->server.last_ack = TCP_GET_ACK(p); if (! (ssn->flags & STREAMTCP_FLAG_NOCLIENT_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); + 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); + + StreamTcpSessionPktFree(p); } 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)); + 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 (TCP_GET_SEQ(p) != ssn->server.next_seq) { - SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != %" PRIu32 " from stream", - ssn, TCP_GET_SEQ(p), ssn->server.next_seq); + SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 "" + " != %" PRIu32 " from stream", ssn, + TCP_GET_SEQ(p), ssn->server.next_seq); return -1; } @@ -1863,9 +2150,13 @@ static int StreamTcpPacketStateTimeWait(ThreadVars *tv, Packet *p, StreamTcpThre ssn->client.last_ack = TCP_GET_ACK(p); if (!(ssn->flags & STREAMTCP_FLAG_NOSERVER_REASSEMBLY)) - StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, &ssn->server, p); - SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK %" PRIu32 "", - ssn, ssn->server.next_seq, ssn->client.last_ack); + StreamTcpReassembleHandleSegment(stt->ra_ctx, ssn, + &ssn->server, p); + SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK " + "%" PRIu32 "", ssn, ssn->server.next_seq, + ssn->client.last_ack); + + StreamTcpSessionPktFree(p); } break; default: @@ -1929,10 +2220,10 @@ static int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt) SCReturnInt(-1); break; case TCP_CLOSED: - //printf("StreamTcpPacket: packet received on closed state\n"); + SCLogDebug("packet received on closed state"); break; default: - //printf("StreamTcpPacket: packet received on default state\n"); + SCLogDebug("packet received on default state"); break; } } @@ -1977,7 +2268,8 @@ TmEcode StreamTcpThreadInit(ThreadVars *tv, void *initdata, void **data) *data = (void *)stt; stt->counter_tcp_sessions = SCPerfTVRegisterCounter("tcp.sessions", tv, - SC_PERF_TYPE_UINT64, "NULL"); + SC_PERF_TYPE_UINT64, + "NULL"); tv->sc_perf_pca = SCPerfGetAllCountersArray(&tv->sc_perf_pctx); SCPerfAddToClubbedTMTable(tv->name, &tv->sc_perf_pctx); @@ -1986,7 +2278,8 @@ TmEcode StreamTcpThreadInit(ThreadVars *tv, void *initdata, void **data) if (stt->ra_ctx == NULL) return TM_ECODE_FAILED; - SCLogDebug("StreamTcp thread specific ctx online at %p, reassembly ctx %p", stt, stt->ra_ctx); + SCLogDebug("StreamTcp thread specific ctx online at %p, reassembly ctx %p", + stt, stt->ra_ctx); return TM_ECODE_OK; } @@ -2009,7 +2302,8 @@ TmEcode StreamTcpThreadDeinit(ThreadVars *tv, void *data) return TM_ECODE_OK; } -void StreamTcpExitPrintStats(ThreadVars *tv, void *data) { +void StreamTcpExitPrintStats(ThreadVars *tv, void *data) +{ StreamTcpThread *stt = (StreamTcpThread *)data; if (stt == NULL) { return; @@ -2019,14 +2313,15 @@ void StreamTcpExitPrintStats(ThreadVars *tv, void *data) { } /** - * \brief Function to check the validity of the RST packets based on the target - * OS of the given packet. + * \brief Function to check the validity of the RST packets based on the + * target OS of the given packet. * * \param ssn TCP session to which the given packet belongs * \param p Packet which has to be checked for its validity */ -static int ValidReset(TcpSession *ssn, Packet *p) { +static int ValidReset(TcpSession *ssn, Packet *p) +{ uint8_t os_policy; @@ -2044,18 +2339,24 @@ static int ValidReset(TcpSession *ssn, Packet *p) { case OS_POLICY_HPUX11: if(PKT_IS_TOSERVER(p)){ if(SEQ_GEQ(TCP_GET_SEQ(p), ssn->client.next_seq)) { - SCLogDebug("reset is Valid! Packet SEQ: %" PRIu32 "", TCP_GET_SEQ(p)); + SCLogDebug("reset is Valid! Packet SEQ: %" PRIu32 "", + TCP_GET_SEQ(p)); return 1; } else { - SCLogDebug("reset is not Valid! Packet SEQ: %" PRIu32 " and server SEQ: %" PRIu32 "", TCP_GET_SEQ(p), ssn->client.next_seq); + SCLogDebug("reset is not Valid! Packet SEQ: %" PRIu32 " " + "and server SEQ: %" PRIu32 "", TCP_GET_SEQ(p), + ssn->client.next_seq); return 0; } } else { /* implied to client */ if(SEQ_GEQ(TCP_GET_SEQ(p), ssn->server.next_seq)) { - SCLogDebug("reset is valid! Packet SEQ: %" PRIu32 "", TCP_GET_SEQ(p)); + SCLogDebug("reset is valid! Packet SEQ: %" PRIu32 "", + TCP_GET_SEQ(p)); return 1; } else { - SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " and client SEQ: %" PRIu32 "", TCP_GET_SEQ(p), ssn->server.next_seq); + SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " " + "and client SEQ: %" PRIu32 "", TCP_GET_SEQ(p), + ssn->server.next_seq); return 0; } } @@ -2064,23 +2365,37 @@ static int ValidReset(TcpSession *ssn, Packet *p) { case OS_POLICY_LINUX: case OS_POLICY_SOLARIS: if(PKT_IS_TOSERVER(p)){ - if(SEQ_GEQ((TCP_GET_SEQ(p)+p->payload_len), ssn->client.last_ack)) { /*window base is needed !!*/ - if(SEQ_LT(TCP_GET_SEQ(p), (ssn->client.next_seq + ssn->client.window))) { - SCLogDebug("reset is Valid! Packet SEQ: %" PRIu32 "", TCP_GET_SEQ(p)); + if(SEQ_GEQ((TCP_GET_SEQ(p)+p->payload_len), + ssn->client.last_ack)) + { /*window base is needed !!*/ + if(SEQ_LT(TCP_GET_SEQ(p), + (ssn->client.next_seq + ssn->client.window))) + { + SCLogDebug("reset is Valid! Packet SEQ: %" PRIu32 "", + TCP_GET_SEQ(p)); return 1; } } else { - SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " and server SEQ: %" PRIu32 "", TCP_GET_SEQ(p), ssn->client.next_seq); + SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " and" + " server SEQ: %" PRIu32 "", TCP_GET_SEQ(p), + ssn->client.next_seq); return 0; } } else { /* implied to client */ - if(SEQ_GEQ((TCP_GET_SEQ(p) + p->payload_len), ssn->server.last_ack)) { /*window base is needed !!*/ - if(SEQ_LT(TCP_GET_SEQ(p), (ssn->server.next_seq + ssn->server.window))) { - SCLogDebug("reset is Valid! Packet SEQ: %" PRIu32 "", TCP_GET_SEQ(p)); + if(SEQ_GEQ((TCP_GET_SEQ(p) + p->payload_len), + ssn->server.last_ack)) + { /*window base is needed !!*/ + if(SEQ_LT(TCP_GET_SEQ(p), + (ssn->server.next_seq + ssn->server.window))) + { + SCLogDebug("reset is Valid! Packet SEQ: %" PRIu32 "", + TCP_GET_SEQ(p)); return 1; } } else { - SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " and client SEQ: %" PRIu32 "", TCP_GET_SEQ(p), ssn->server.next_seq); + SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " and" + " client SEQ: %" PRIu32 "", TCP_GET_SEQ(p), + ssn->server.next_seq); return 0; } } @@ -2097,18 +2412,24 @@ static int ValidReset(TcpSession *ssn, Packet *p) { case OS_POLICY_VISTA: if(PKT_IS_TOSERVER(p)) { if(SEQ_EQ(TCP_GET_SEQ(p), ssn->client.next_seq)) { - SCLogDebug("reset is valid! Packet SEQ: %" PRIu32 "", TCP_GET_SEQ(p)); + SCLogDebug("reset is valid! Packet SEQ: %" PRIu32 "", + TCP_GET_SEQ(p)); return 1; } else { - SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " and server SEQ: %" PRIu32 "", TCP_GET_SEQ(p), ssn->client.next_seq); + SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " " + "and server SEQ: %" PRIu32 "", TCP_GET_SEQ(p), + ssn->client.next_seq); return 0; } } else { /* implied to client */ if(SEQ_EQ(TCP_GET_SEQ(p), ssn->server.next_seq)) { - SCLogDebug("reset is valid! Packet SEQ: %" PRIu32 "", TCP_GET_SEQ(p)); + SCLogDebug("reset is valid! Packet SEQ: %" PRIu32 "", + TCP_GET_SEQ(p)); return 1; } else { - SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " and client SEQ: %" PRIu32 "", TCP_GET_SEQ(p), ssn->server.next_seq); + SCLogDebug("reset is not valid! Packet SEQ: %" PRIu32 " and" + " client SEQ: %" PRIu32 "", TCP_GET_SEQ(p), + ssn->server.next_seq); return 0; } } @@ -2121,10 +2442,12 @@ static int ValidReset(TcpSession *ssn, Packet *p) { * \brief Function to return the FLOW state depending upon the TCP session state. * * \param s TCP session of which the state has to be returned - * \retval The FLOW_STATE_ depends upon the TCP sesison state, default is FLOW_STATE_CLOSED + * \retval The FLOW_STATE_ depends upon the TCP sesison state, default is + * FLOW_STATE_CLOSED */ -int StreamTcpGetFlowState(void *s) { +int StreamTcpGetFlowState(void *s) +{ TcpSession *ssn = (TcpSession *)s; if (ssn == NULL) return FLOW_STATE_CLOSED; @@ -2150,15 +2473,16 @@ int StreamTcpGetFlowState(void *s) { } /** - * \brief Function to check the validity of the received timestamp based on the target - * OS of the given stream. + * \brief Function to check the validity of the received timestamp based on + * the target OS of the given stream. * * \param ssn TCP session to which the given packet belongs * \param p Packet which has to be checked for its validity * \retval If timestamp is valid, function returns 1 otherwise 0 */ -static int ValidTimestamp (TcpSession *ssn, Packet *p) { +static int ValidTimestamp (TcpSession *ssn, Packet *p) +{ TcpStream *sender_stream; TcpStream *receiver_stream; @@ -2181,8 +2505,8 @@ static int ValidTimestamp (TcpSession *ssn, Packet *p) { switch (receiver_stream->os_policy) { case OS_POLICY_LINUX: case OS_POLICY_WINDOWS2K3: - /*Linux and windows 2003 does not allow the use of 0 as timestamp - in the 3whs. */ + /* Linux and windows 2003 does not allow the use of 0 as + * timestamp in the 3whs. */ ssn->flags &= ~STREAMTCP_FLAG_TIMESTAMP; check_ts = 0; break; @@ -2194,7 +2518,8 @@ static int ValidTimestamp (TcpSession *ssn, Packet *p) { if (SEQ_EQ(sender_stream->next_seq, TCP_GET_SEQ(p))) { sender_stream->last_ts = ts; check_ts = 0; /*next packet will be checked for validity - and stream TS has been updated with this one.*/ + and stream TS has been updated with this + one.*/ } break; default: @@ -2218,8 +2543,8 @@ static int ValidTimestamp (TcpSession *ssn, Packet *p) { /*Old Linux and windows allowed packet with 0 timestamp.*/ break; default: - /* other OS simply drop the pakcet with 0 timestamp, when 3whs - has valid timestamp*/ + /* other OS simply drop the pakcet with 0 timestamp, when + * 3whs has valid timestamp*/ return 0; } } @@ -2228,35 +2553,49 @@ static int ValidTimestamp (TcpSession *ssn, Packet *p) { int32_t result = 0; if (receiver_stream->os_policy == OS_POLICY_LINUX) { - result = (int32_t) ((ts - sender_stream->last_ts) + 1); /* Linux accepts TS which are off by one.*/ + /* Linux accepts TS which are off by one.*/ + result = (int32_t) ((ts - sender_stream->last_ts) + 1); } else { result = (int32_t) (ts - sender_stream->last_ts); } - if (sender_stream->last_pkt_ts == 0 && (ssn->flags & STREAMTCP_FLAG_MIDSTREAM)) + if (sender_stream->last_pkt_ts == 0 && + (ssn->flags & STREAMTCP_FLAG_MIDSTREAM)) + { sender_stream->last_pkt_ts = p->ts.tv_sec; + } if (result < 0) { - SCLogDebug("timestamp is not valid sender_stream->last_ts %" PRIu32 " p->tcpvars->ts %" PRIu32 " result %" PRId32 "", sender_stream->last_ts, ts, result); + SCLogDebug("timestamp is not valid sender_stream->last_ts " + "%" PRIu32 " p->tcpvars->ts %" PRIu32 " result " + "%" PRId32 "", sender_stream->last_ts, ts, result); ret = 0; - } else if ((sender_stream->last_ts != 0) && (((uint32_t) p->ts.tv_sec) > sender_stream->last_pkt_ts + PAWS_24DAYS)) { - SCLogDebug("packet is not valid sender_stream->last_pkt_ts %" PRIu32 " p->ts.tv_sec %" PRIu32 "", sender_stream->last_pkt_ts, (uint32_t) p->ts.tv_sec); + } else if ((sender_stream->last_ts != 0) && + (((uint32_t) p->ts.tv_sec) > + sender_stream->last_pkt_ts + PAWS_24DAYS)) + { + SCLogDebug("packet is not valid sender_stream->last_pkt_ts " + "%" PRIu32 " p->ts.tv_sec %" PRIu32 "", + sender_stream->last_pkt_ts, (uint32_t) p->ts.tv_sec); ret = 0; } if (ret == 1) { - /*Update the timestamp and last seen packet time for this stream.*/ + /* Update the timestamp and last seen packet time for this + * stream */ if (SEQ_EQ(sender_stream->next_seq, TCP_GET_SEQ(p))) sender_stream->last_ts = ts; sender_stream->last_pkt_ts = p->ts.tv_sec; } if (ret == 0) { - /*if the timestamp of packet is not valid then, check if the current - stream timestamp is not so old. if so then we need to accept the packet - and update the stream->last_ts (RFC 1323)*/ + /* if the timestamp of packet is not valid then, check if the + * current stream timestamp is not so old. if so then we need to + * accept the packet and update the stream->last_ts (RFC 1323)*/ if ((SEQ_EQ(sender_stream->next_seq, TCP_GET_SEQ(p))) - && (((uint32_t) p->ts.tv_sec > (sender_stream->last_pkt_ts + PAWS_24DAYS)))) { + && (((uint32_t) p->ts.tv_sec > + (sender_stream->last_pkt_ts + PAWS_24DAYS)))) + { sender_stream->last_ts = ts; sender_stream->last_pkt_ts = p->ts.tv_sec; ret = 1; @@ -2279,8 +2618,10 @@ static int ValidTimestamp (TcpSession *ssn, Packet *p) { * \param direction direction to set the flag in */ -void StreamTcpSetSessionNoReassemblyFlag (TcpSession *ssn, char direction) { - direction ? (ssn->flags |= STREAMTCP_FLAG_NOSERVER_REASSEMBLY) : (ssn->flags |= STREAMTCP_FLAG_NOCLIENT_REASSEMBLY); +void StreamTcpSetSessionNoReassemblyFlag (TcpSession *ssn, char direction) +{ + direction ? (ssn->flags |= STREAMTCP_FLAG_NOSERVER_REASSEMBLY) : + (ssn->flags |= STREAMTCP_FLAG_NOCLIENT_REASSEMBLY); } #ifdef UNITTESTS diff --git a/src/stream-tcp.h b/src/stream-tcp.h index 9aaa4a85c1..37bc0259d9 100644 --- a/src/stream-tcp.h +++ b/src/stream-tcp.h @@ -8,8 +8,8 @@ #define STREAM_VERBOSE FALSE /*global flow data*/ typedef struct TcpStreamCnf_ { - uint32_t max_sessions; - uint32_t prealloc_sessions; + int max_sessions; + int prealloc_sessions; int midstream; int async_oneside; } TcpStreamCnf; diff --git a/src/util-error.c b/src/util-error.c index c3c2b43777..98b123a5bd 100644 --- a/src/util-error.c +++ b/src/util-error.c @@ -49,6 +49,9 @@ const char * SCErrorToString(SCError err) CASE_CODE (SC_INVALID_NUM_BYTES); CASE_CODE (SC_ERR_ARG_LEN_LONG); CASE_CODE (SC_ALPARSER_ERR); + CASE_CODE (SC_ERR_POOL_EMPTY); + CASE_CODE (SC_ERR_REASSEMBLY_FAILED); + CASE_CODE (SC_ERR_POOL_INIT_FAILED); default: return "UNKNOWN_ERROR"; } diff --git a/src/util-error.h b/src/util-error.h index c3ffafce0e..8e29274162 100644 --- a/src/util-error.h +++ b/src/util-error.h @@ -49,6 +49,9 @@ typedef enum { SC_NUMERIC_VALUE_ERANGE, SC_INVALID_NUM_BYTES, SC_ERR_ARG_LEN_LONG, + SC_ERR_POOL_EMPTY, + SC_ERR_REASSEMBLY_FAILED, + SC_ERR_POOL_INIT_FAILED, SC_NFQ_OPEN, SC_NFQ_BIND, SC_NFQ_UNBIND,