Improve stream gap handling. Instead of giving up as soon as we see a gap we now wait much longer before we decide it's a gap.

remotes/origin/master-1.1.x
Victor Julien 16 years ago
parent 6ffb9da9be
commit aa04d9eefb

@ -270,6 +270,8 @@ int StreamTcpReassembleInit(char quiet)
#ifdef DEBUG #ifdef DEBUG
extern uint32_t applayererrors; extern uint32_t applayererrors;
extern uint32_t applayerhttperrors; extern uint32_t applayerhttperrors;
static uint32_t dbg_app_layer_gap;
static uint32_t dbg_app_layer_gap_candidate;
#endif #endif
void StreamTcpReassembleFree(char quiet) void StreamTcpReassembleFree(char quiet)
@ -309,6 +311,8 @@ void StreamTcpReassembleFree(char quiet)
SCMutexDestroy(&segment_pool_cnt_mutex); SCMutexDestroy(&segment_pool_cnt_mutex);
SCLogInfo("applayererrors %u", applayererrors); SCLogInfo("applayererrors %u", applayererrors);
SCLogInfo("applayerhttperrors %u", applayerhttperrors); SCLogInfo("applayerhttperrors %u", applayerhttperrors);
SCLogInfo("dbg_app_layer_gap %u", dbg_app_layer_gap);
SCLogInfo("dbg_app_layer_gap_candidate %u", dbg_app_layer_gap_candidate);
#endif #endif
} }
@ -460,9 +464,30 @@ static int ReassembleInsertSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ct
TcpSegment *list_seg = stream->seg_list; TcpSegment *list_seg = stream->seg_list;
TcpSegment *next_list_seg = NULL; TcpSegment *next_list_seg = NULL;
PrintList(stream->seg_list);
int ret_value = 0; int ret_value = 0;
char return_seg = FALSE; char return_seg = FALSE;
/* before our ra_app_base_seq we don't insert it in our list,
* or ra_raw_base_seq if in stream gap state */
if ((!(stream->flags & STREAMTCP_STREAM_FLAG_GAP) &&
SEQ_LEQ((TCP_GET_SEQ(p)+p->payload_len),(stream->ra_app_base_seq+1))) ||
(stream->flags & STREAMTCP_STREAM_FLAG_GAP &&
SEQ_LEQ((TCP_GET_SEQ(p)+p->payload_len),(stream->ra_raw_base_seq+1))))
{
SCLogDebug("not inserting: SEQ+payload %"PRIu32", last_ack %"PRIu32", "
"ra_app_base_seq %"PRIu32, (TCP_GET_SEQ(p)+p->payload_len),
stream->last_ack, stream->ra_app_base_seq);
return_seg = TRUE;
ret_value = -1;
goto end;
}
SCLogDebug("SEQ+payload %"PRIu32", last_ack %"PRIu32", "
"ra_app_base_seq %"PRIu32, (TCP_GET_SEQ(p)+p->payload_len),
stream->last_ack, stream->ra_app_base_seq);
if (list_seg == NULL) { if (list_seg == NULL) {
SCLogDebug("empty list, inserting seg %p seq %" PRIu32 ", " SCLogDebug("empty list, inserting seg %p seq %" PRIu32 ", "
"len %" PRIu32 "", seg, seg->seq, seg->payload_len); "len %" PRIu32 "", seg, seg->seq, seg->payload_len);
@ -1261,6 +1286,8 @@ static int HandleSegmentStartsAfterListSegment(ThreadVars *tv, TcpReassemblyThre
{ {
handle_beyond = TRUE; handle_beyond = TRUE;
} }
} else {
fill_gap = TRUE;
} }
SCLogDebug("fill_gap %s, handle_beyond %s", fill_gap?"TRUE":"FALSE", SCLogDebug("fill_gap %s, handle_beyond %s", fill_gap?"TRUE":"FALSE",
@ -1269,11 +1296,15 @@ static int HandleSegmentStartsAfterListSegment(ThreadVars *tv, TcpReassemblyThre
if (fill_gap == TRUE) { if (fill_gap == TRUE) {
/* if there is a gap after this list_seg we fill it now with a /* if there is a gap after this list_seg we fill it now with a
* new seg */ * new seg */
SCLogDebug("filling gap: list_seg->next->seq %"PRIu32"", if (list_seg->next != NULL) {
list_seg->next?list_seg->next->seq:0); 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 + packet_length = list_seg->next->seq - (list_seg->seq +
list_seg->payload_len); list_seg->payload_len);
} else {
packet_length = seg->payload_len - overlap;
}
if (packet_length > (seg->payload_len - overlap)) { if (packet_length > (seg->payload_len - overlap)) {
packet_length = seg->payload_len - overlap; packet_length = seg->payload_len - overlap;
} }
@ -1300,7 +1331,7 @@ static int HandleSegmentStartsAfterListSegment(ThreadVars *tv, TcpReassemblyThre
StreamTcpSegmentDataReplace(new_seg, seg, new_seg->seq, StreamTcpSegmentDataReplace(new_seg, seg, new_seg->seq,
new_seg->payload_len); new_seg->payload_len);
/*update the stream last_seg in case of removal of list_seg*/ /* update the stream last_seg in case of removal of list_seg */
if (stream->seg_list_tail == list_seg) if (stream->seg_list_tail == list_seg)
stream->seg_list_tail = new_seg; stream->seg_list_tail = new_seg;
} }
@ -1399,8 +1430,6 @@ int StreamTcpReassembleHandleSegmentHandleData(ThreadVars *tv, TcpReassemblyThre
memcpy(seg->payload, p->payload, p->payload_len); memcpy(seg->payload, p->payload, p->payload_len);
seg->payload_len = p->payload_len; seg->payload_len = p->payload_len;
seg->seq = TCP_GET_SEQ(p); seg->seq = TCP_GET_SEQ(p);
seg->next = NULL;
seg->prev = NULL;
stream->reassembly_depth += p->payload_len; stream->reassembly_depth += p->payload_len;
if (ReassembleInsertSegment(tv, ra_ctx, stream, seg, p) != 0) { if (ReassembleInsertSegment(tv, ra_ctx, stream, seg, p) != 0) {
@ -1470,9 +1499,12 @@ static void StreamTcpSetupMsg(TcpSession *ssn, TcpStream *stream, Packet *p,
SCReturn; SCReturn;
} }
/** \brief Check the minimum size limits for reassembly. /**
* \brief Check the minimum size limits for reassembly.
*
* \retval 0 don't reassemble yet * \retval 0 don't reassemble yet
* \retval 1 do reassemble */ * \retval 1 do reassemble
*/
static int StreamTcpReassembleRawCheckLimit(TcpSession *ssn, TcpStream *stream, static int StreamTcpReassembleRawCheckLimit(TcpSession *ssn, TcpStream *stream,
Packet *p) Packet *p)
{ {
@ -1708,14 +1740,7 @@ static int StreamTcpReassembleAppLayer (TcpReassemblyThreadCtx *ra_ctx,
seg = next_seg; seg = next_seg;
continue; continue;
} }
/*
if ((ssn->flags & STREAMTCP_FLAG_APPPROTO_DETECTION_COMPLETED) &&
(seg->flags & SEGMENTTCP_FLAG_APPLAYER_PROCESSED)) {
TcpSegment *next_seg = seg->next;
seg = next_seg;
continue;
}
*/
/* If packets are fully before ra_base_seq, skip them. We do this /* 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, * because we've reassembled up to the ra_base_seq point already,
* so we won't do anything with segments before it anyway. */ * so we won't do anything with segments before it anyway. */
@ -1747,19 +1772,11 @@ static int StreamTcpReassembleAppLayer (TcpReassemblyThreadCtx *ra_ctx,
/* we've run into a sequence gap */ /* we've run into a sequence gap */
if (SEQ_GT(seg->seq, next_seq)) { if (SEQ_GT(seg->seq, next_seq)) {
/* see what the length of the gap is, gap length is seg->seq -
* (ra_base_seq +1) */
#ifdef DEBUG
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);
#endif
next_seq = seg->seq;
/* pass on data before the gap */ /* first, pass on data before the gap */
if (data_len > 0) { if (data_len > 0) {
SCLogDebug("pre GAP data");
STREAM_SET_FLAGS(ssn, stream, p, flags); STREAM_SET_FLAGS(ssn, stream, p, flags);
/* if app layer protocol has not been detected till yet, /* if app layer protocol has not been detected till yet,
@ -1783,33 +1800,57 @@ static int StreamTcpReassembleAppLayer (TcpReassemblyThreadCtx *ra_ctx,
} }
} }
/* we need to update the ra_base_seq, if app layer proto has /* don't conclude it's a gap straight away. If ra_base_seq is lower
been detected and we are setting new stream message. Otherwise * than last_ack - the window, we consider it a gap. */
every smsg will be with flag STREAM_START set, which we if (SEQ_GT((stream->last_ack - stream->window), ra_base_seq) ||
don't want :-) */ ssn->state > TCP_ESTABLISHED)
if (ssn->flags & STREAMTCP_FLAG_APPPROTO_DETECTION_COMPLETED) { {
stream->ra_app_base_seq = ra_base_seq; /* see what the length of the gap is, gap length is seg->seq -
} else { * (ra_base_seq +1) */
stream->tmp_ra_app_base_seq = ra_base_seq; #ifdef DEBUG
} 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);
#endif
/* We have missed the packet and end host has ack'd it, so next_seq = seg->seq;
* 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 */
ra_base_seq = seg->seq - 1;
/* send gap signal */ /* we need to update the ra_base_seq, if app layer proto has
STREAM_SET_FLAGS(ssn, stream, p, flags); been detected and we are setting new stream message. Otherwise
AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn, every smsg will be with flag STREAM_START set, which we
NULL, 0, flags|STREAM_GAP); don't want :-) */
data_len = 0; if (ssn->flags & STREAMTCP_FLAG_APPPROTO_DETECTION_COMPLETED) {
stream->ra_app_base_seq = ra_base_seq;
} else {
stream->tmp_ra_app_base_seq = ra_base_seq;
}
/* set a GAP flag and make sure not bothering this stream anymore */ /* We have missed the packet and end host has ack'd it, so
stream->flags |= STREAMTCP_STREAM_FLAG_GAP; * IDS should advance it's ra_base_seq and should not consider this
/* flag reassembly as started, so the to_client part can start */ * packet any longer, even if it is retransmitted, as end host will
ssn->flags |= STREAMTCP_FLAG_TOSERVER_REASSEMBLY_STARTED; * drop it anyway */
break; ra_base_seq = seg->seq - 1;
/* send gap signal */
STREAM_SET_FLAGS(ssn, stream, p, flags);
AppLayerHandleTCPData(&ra_ctx->dp_ctx, p->flow, ssn,
NULL, 0, flags|STREAM_GAP);
data_len = 0;
/* set a GAP flag and make sure not bothering this stream anymore */
stream->flags |= STREAMTCP_STREAM_FLAG_GAP;
/* flag reassembly as started, so the to_client part can start */
ssn->flags |= STREAMTCP_FLAG_TOSERVER_REASSEMBLY_STARTED;
dbg_app_layer_gap++;
break;
} else {
SCLogDebug("possible GAP, but waiting to see if out of order "
"packets might solve that");
dbg_app_layer_gap_candidate++;
break;
}
} }
/* if the segment ends beyond ra_base_seq we need to consider it */ /* if the segment ends beyond ra_base_seq we need to consider it */
@ -1848,6 +1889,12 @@ static int StreamTcpReassembleAppLayer (TcpReassemblyThreadCtx *ra_ctx,
SCLogDebug("payload_offset is %"PRIu16", payload_len is %"PRIu16"" SCLogDebug("payload_offset is %"PRIu16", payload_len is %"PRIu16""
" and stream->last_ack is %"PRIu32"", payload_offset, " and stream->last_ack is %"PRIu32"", payload_offset,
payload_len, stream->last_ack); payload_len, stream->last_ack);
if (payload_len == 0) {
SCLogDebug("no payload_len, so bail out");
break;
}
/* copy the data into the smsg */ /* copy the data into the smsg */
uint16_t copy_size = sizeof(data) - data_len; uint16_t copy_size = sizeof(data) - data_len;
if (copy_size > payload_len) { if (copy_size > payload_len) {
@ -2093,10 +2140,13 @@ static int StreamTcpReassembleRaw (TcpReassemblyThreadCtx *ra_ctx,
SCLogDebug("seg %p", seg); SCLogDebug("seg %p", seg);
/* if app layer protocol has been detected, then remove all the segments /* if app layer protocol has been detected, then remove all the segments
which has been previously processed and reassembled */ * which has been previously processed and reassembled
*
* If the stream is in GAP state the app layer flag won't be set */
if ((ssn->flags & STREAMTCP_FLAG_APPPROTO_DETECTION_COMPLETED) && if ((ssn->flags & STREAMTCP_FLAG_APPPROTO_DETECTION_COMPLETED) &&
(seg->flags & SEGMENTTCP_FLAG_RAW_PROCESSED) && (seg->flags & SEGMENTTCP_FLAG_RAW_PROCESSED) &&
(seg->flags & SEGMENTTCP_FLAG_APPLAYER_PROCESSED)) (seg->flags & SEGMENTTCP_FLAG_APPLAYER_PROCESSED ||
stream->flags & STREAMTCP_STREAM_FLAG_GAP))
{ {
SCLogDebug("segment(%p) of length %"PRIu16" has been processed," SCLogDebug("segment(%p) of length %"PRIu16" has been processed,"
" so return it to pool", seg, seg->payload_len); " so return it to pool", seg, seg->payload_len);
@ -2119,10 +2169,7 @@ static int StreamTcpReassembleRaw (TcpReassemblyThreadCtx *ra_ctx,
ra_base_seq or if they are beyond ra_base_seq, but the segment offset ra_base_seq or if they are beyond ra_base_seq, but the segment offset
from which we need to copy in to smsg is beyond the stream->last_ack. from which we need to copy in to smsg is beyond the stream->last_ack.
As we are copying until the stream->last_ack only */ As we are copying until the stream->last_ack only */
if (SEQ_LT((seg->seq + seg->payload_len), ra_base_seq))
/** \todo we should probably not even insert them into the seglist */
if (SEQ_LEQ((seg->seq + seg->payload_len), (ra_base_seq+1)) ||
SEQ_LEQ(stream->last_ack, (ra_base_seq + (ra_base_seq - seg->seq))))
{ {
SCLogDebug("removing pre ra_base_seq %"PRIu32" seg %p seq %"PRIu32"" SCLogDebug("removing pre ra_base_seq %"PRIu32" seg %p seq %"PRIu32""
" len %"PRIu16"", ra_base_seq, seg, seg->seq, " len %"PRIu16"", ra_base_seq, seg, seg->seq,
@ -2138,15 +2185,6 @@ static int StreamTcpReassembleRaw (TcpReassemblyThreadCtx *ra_ctx,
/* we've run into a sequence gap */ /* we've run into a sequence gap */
if (SEQ_GT(seg->seq, next_seq)) { if (SEQ_GT(seg->seq, next_seq)) {
/* 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);
next_seq = seg->seq;
/* pass on pre existing smsg (if any) */ /* pass on pre existing smsg (if any) */
if (smsg != NULL && smsg->data.data_len > 0) { if (smsg != NULL && smsg->data.data_len > 0) {
/* if app layer protocol has not been detected till yet, /* if app layer protocol has not been detected till yet,
@ -2159,30 +2197,49 @@ static int StreamTcpReassembleRaw (TcpReassemblyThreadCtx *ra_ctx,
smsg = NULL; smsg = NULL;
} }
if (smsg == NULL) { /* don't conclude it's a gap straight away. If ra_base_seq is lower
smsg = StreamMsgGetFromPool(); * than last_ack - the window, we consider it a gap. */
if (SEQ_GT((stream->last_ack - stream->window), ra_base_seq) ||
ssn->state > TCP_ESTABLISHED)
{
/* 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);
next_seq = seg->seq;
if (smsg == NULL) { if (smsg == NULL) {
SCLogDebug("stream_msg_pool is empty"); smsg = StreamMsgGetFromPool();
return -1; if (smsg == NULL) {
SCLogDebug("stream_msg_pool is empty");
return -1;
}
} }
} stream->ra_raw_base_seq = ra_base_seq;
stream->ra_raw_base_seq = ra_base_seq;
StreamTcpSetupMsg(ssn, stream, p, smsg); StreamTcpSetupMsg(ssn, stream, p, smsg);
/* We have missed the packet and end host has ack'd it, so /* 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 * 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 * packet any longer, even if it is retransmitted, as end host will
* drop it anyway */ * drop it anyway */
ra_base_seq = seg->seq - 1; ra_base_seq = seg->seq - 1;
SCLogDebug("setting STREAM_GAP"); SCLogDebug("setting STREAM_GAP");
smsg->flags |= STREAM_GAP; smsg->flags |= STREAM_GAP;
smsg->gap.gap_size = gap_len; smsg->gap.gap_size = gap_len;
StreamMsgPutInQueue(ra_ctx->stream_q,smsg); StreamMsgPutInQueue(ra_ctx->stream_q,smsg);
smsg = NULL; smsg = NULL;
smsg_offset = 0; smsg_offset = 0;
} else {
SCLogDebug("possible GAP, but waiting to see if out of order "
"packets might solve that");
break;
}
} }
/* if the segment ends beyond ra_base_seq we need to consider it */ /* if the segment ends beyond ra_base_seq we need to consider it */
@ -2190,18 +2247,6 @@ static int StreamTcpReassembleRaw (TcpReassemblyThreadCtx *ra_ctx,
SCLogDebug("seg->seq %" PRIu32 ", seg->payload_len %" PRIu32 ", " SCLogDebug("seg->seq %" PRIu32 ", seg->payload_len %" PRIu32 ", "
"ra_base_seq %" PRIu32 "", seg->seq, "ra_base_seq %" PRIu32 "", seg->seq,
seg->payload_len, ra_base_seq); seg->payload_len, ra_base_seq);
if (smsg == NULL) {
smsg = StreamMsgGetFromPool();
if (smsg == NULL) {
SCLogDebug("stream_msg_pool is empty");
return -1;
}
smsg_offset = 0;
StreamTcpSetupMsg(ssn, stream, p, smsg);
}
smsg->data.seq = ra_base_seq;
/* handle segments partly before ra_base_seq */ /* handle segments partly before ra_base_seq */
if (SEQ_GT(ra_base_seq, seg->seq)) { if (SEQ_GT(ra_base_seq, seg->seq)) {
@ -2234,6 +2279,26 @@ static int StreamTcpReassembleRaw (TcpReassemblyThreadCtx *ra_ctx,
SCLogDebug("payload_offset is %"PRIu16", payload_len is %"PRIu16"" SCLogDebug("payload_offset is %"PRIu16", payload_len is %"PRIu16""
" and stream->last_ack is %"PRIu32"", payload_offset, " and stream->last_ack is %"PRIu32"", payload_offset,
payload_len, stream->last_ack); payload_len, stream->last_ack);
if (payload_len == 0) {
SCLogDebug("no payload_len, so bail out");
break;
}
if (smsg == NULL) {
smsg = StreamMsgGetFromPool();
if (smsg == NULL) {
SCLogDebug("stream_msg_pool is empty");
return -1;
}
smsg_offset = 0;
StreamTcpSetupMsg(ssn, stream, p, smsg);
}
smsg->data.seq = ra_base_seq;
/* copy the data into the smsg */ /* copy the data into the smsg */
uint16_t copy_size = sizeof (smsg->data.data) - smsg_offset; uint16_t copy_size = sizeof (smsg->data.data) - smsg_offset;
if (copy_size > payload_len) { if (copy_size > payload_len) {
@ -2781,8 +2846,9 @@ void StreamTcpSegmentDataCopy(TcpSegment *dst_seg, TcpSegment *src_seg)
* \brief Function to get the segment of required length from the pool. * \brief Function to get the segment of required length from the pool.
* *
* \param len Length which tells the required size of needed segment. * \param len Length which tells the required size of needed segment.
*
* \retval seg Segment from the pool or NULL
*/ */
TcpSegment* StreamTcpGetSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, uint16_t len) TcpSegment* StreamTcpGetSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, uint16_t len)
{ {
uint16_t idx = segment_pool_idx[len]; uint16_t idx = segment_pool_idx[len];
@ -2806,13 +2872,17 @@ TcpSegment* StreamTcpGetSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
/* Increment the counter to show that we are not able to serve the /* Increment the counter to show that we are not able to serve the
segment request due to memcap limit */ segment request due to memcap limit */
SCPerfCounterIncr(ra_ctx->counter_tcp_segment_memcap, tv->sc_perf_pca); SCPerfCounterIncr(ra_ctx->counter_tcp_segment_memcap, tv->sc_perf_pca);
} else { }
#ifdef DEBUG #ifdef DEBUG
SCMutexLock(&segment_pool_cnt_mutex); SCMutexLock(&segment_pool_cnt_mutex);
segment_pool_cnt++; segment_pool_cnt++;
SCMutexUnlock(&segment_pool_cnt_mutex); SCMutexUnlock(&segment_pool_cnt_mutex);
#endif #endif
}
seg->flags = 0;
seg->next = NULL;
seg->prev = NULL;
return seg; return seg;
} }
@ -5088,6 +5158,7 @@ static int StreamTcpReassembleTest35(void) {
p->payload_len = 142; p->payload_len = 142;
stream.last_ack = 2257022285UL; stream.last_ack = 2257022285UL;
stream.ra_raw_base_seq = 2257022172UL; stream.ra_raw_base_seq = 2257022172UL;
stream.ra_app_base_seq = 2257022172UL;
if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, &stream, p, &pq) == -1) { if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, &stream, p, &pq) == -1) {
SCFree(p); SCFree(p);
@ -5183,16 +5254,17 @@ static int StreamTcpReassembleTest36(void) {
/** \test Test the bug 76 condition */ /** \test Test the bug 76 condition */
static int StreamTcpReassembleTest37(void) { static int StreamTcpReassembleTest37(void) {
TcpSession ssn; TcpSession ssn;
Packet *p = SCMalloc(SIZE_OF_PACKET);
if (p == NULL)
return 0;
Flow f; Flow f;
TCPHdr tcph; TCPHdr tcph;
TcpReassemblyThreadCtx *ra_ctx = StreamTcpReassembleInitThreadCtx(); TcpReassemblyThreadCtx *ra_ctx = StreamTcpReassembleInitThreadCtx();
TcpStream stream; TcpStream stream;
memset(&stream, 0, sizeof (TcpStream));
stream.os_policy = OS_POLICY_BSD;
uint8_t packet[1460] = ""; uint8_t packet[1460] = "";
PacketQueue pq;
ThreadVars tv;
Packet *p = SCMalloc(SIZE_OF_PACKET);
if (p == NULL)
return 0;
StreamTcpInitConfig(TRUE); StreamTcpInitConfig(TRUE);
@ -5202,15 +5274,16 @@ static int StreamTcpReassembleTest37(void) {
StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 10); StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 10);
StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 10); StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 10);
PacketQueue pq;
memset(&pq,0,sizeof(PacketQueue));
memset(&ssn, 0, sizeof (TcpSession));
memset(p, 0, SIZE_OF_PACKET); memset(p, 0, SIZE_OF_PACKET);
p->pkt = (uint8_t *)(p + 1); p->pkt = (uint8_t *)(p + 1);
memset(&stream, 0, sizeof (TcpStream));
memset(&pq,0,sizeof(PacketQueue));
memset(&ssn, 0, sizeof (TcpSession));
memset(&f, 0, sizeof (Flow)); memset(&f, 0, sizeof (Flow));
memset(&tcph, 0, sizeof (TCPHdr)); memset(&tcph, 0, sizeof (TCPHdr));
ThreadVars tv;
memset(&tv, 0, sizeof (ThreadVars)); memset(&tv, 0, sizeof (ThreadVars));
FLOW_INITIALIZE(&f); FLOW_INITIALIZE(&f);
f.protoctx = &ssn; f.protoctx = &ssn;
p->src.family = AF_INET; p->src.family = AF_INET;
@ -5222,14 +5295,17 @@ static int StreamTcpReassembleTest37(void) {
p->tcph = &tcph; p->tcph = &tcph;
p->flowflags = FLOW_PKT_TOSERVER; p->flowflags = FLOW_PKT_TOSERVER;
p->payload = packet; p->payload = packet;
stream.os_policy = OS_POLICY_BSD;
p->tcph->th_seq = htonl(3061088537UL); p->tcph->th_seq = htonl(3061088537UL);
p->tcph->th_ack = htonl(1729548549UL); p->tcph->th_ack = htonl(1729548549UL);
p->payload_len = 1391; p->payload_len = 1391;
stream.last_ack = 3061091137UL; stream.last_ack = 3061091137UL;
stream.ra_raw_base_seq = 3061091309UL; stream.ra_raw_base_seq = 3061091309UL;
stream.ra_app_base_seq = 3061091309UL;
if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, &stream, p, &pq) == -1) { /* pre base_seq, so should be rejected */
if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, &stream, p, &pq) != -1) {
SCFree(p); SCFree(p);
return 0; return 0;
} }
@ -5239,6 +5315,7 @@ static int StreamTcpReassembleTest37(void) {
p->payload_len = 1391; p->payload_len = 1391;
stream.last_ack = 3061091137UL; stream.last_ack = 3061091137UL;
stream.ra_raw_base_seq = 3061091309UL; stream.ra_raw_base_seq = 3061091309UL;
stream.ra_app_base_seq = 3061091309UL;
if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, &stream, p, &pq) == -1) { if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, &stream, p, &pq) == -1) {
SCFree(p); SCFree(p);
@ -5250,6 +5327,7 @@ static int StreamTcpReassembleTest37(void) {
p->payload_len = 1391; p->payload_len = 1391;
stream.last_ack = 3061091137UL; stream.last_ack = 3061091137UL;
stream.ra_raw_base_seq = 3061091309UL; stream.ra_raw_base_seq = 3061091309UL;
stream.ra_app_base_seq = 3061091309UL;
if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, &stream, p, &pq) == -1) { if (StreamTcpReassembleHandleSegment(&tv, ra_ctx,&ssn, &stream, p, &pq) == -1) {
SCFree(p); SCFree(p);

Loading…
Cancel
Save