Have reassembly errors also set a stream event.

remotes/origin/master-1.1.x
Victor Julien 15 years ago
parent 0f072648e6
commit 66c40f782c

@ -173,6 +173,9 @@ enum {
STREAM_PKT_INVALID_ACK,
STREAM_RST_INVALID_ACK,
STREAM_REASSEMBLY_SEGMENT_BEFORE_BASE_SEQ,
STREAM_REASSEMBLY_NO_SEGMENT,
/* should always be last! */
DECODE_EVENT_MAX,
};

@ -24,8 +24,7 @@
* Reference:
* Judy Novak, Steve Sturges: Target-Based TCP Stream Reassembly August, 2007
*
* \todo segment insert fasttrack: most pkts are in order
*/
*/
#include <arpa/inet.h>
@ -461,14 +460,17 @@ static inline uint32_t StreamTcpReassembleGetRaBaseSeq(TcpStream *stream)
}
/**
* \internal
* \brief Function to handle the insertion newly arrived segment,
* The packet is handled based on its target OS.
*
* \param stream The given TCP stream to which this new segment belongs
* \param seg Newly arrived segment
* \param p received packet
* \retval 0 success
* \retval -1 error
*
* \retval 0 success
* \retval -1 error -- either we hit a memory issue (OOM/memcap) or we received
* a segment before ra_base_seq.
*/
static int ReassembleInsertSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
@ -479,7 +481,9 @@ static int ReassembleInsertSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ct
TcpSegment *list_seg = stream->seg_list;
TcpSegment *next_list_seg = NULL;
#if DEBUG
PrintList(stream->seg_list);
#endif
int ret_value = 0;
char return_seg = FALSE;
@ -493,6 +497,8 @@ static int ReassembleInsertSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ct
stream->last_ack, StreamTcpReassembleGetRaBaseSeq(stream));
return_seg = TRUE;
ret_value = -1;
StreamTcpSetEvent(p, STREAM_REASSEMBLY_SEGMENT_BEFORE_BASE_SEQ);
goto end;
}
@ -500,6 +506,7 @@ static int ReassembleInsertSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ct
"ra_app_base_seq %"PRIu32, (TCP_GET_SEQ(p)+p->payload_len),
stream->last_ack, stream->ra_app_base_seq);
/* fast track */
if (list_seg == NULL) {
SCLogDebug("empty list, inserting seg %p seq %" PRIu32 ", "
"len %" PRIu32 "", seg, seg->seq, seg->payload_len);
@ -639,9 +646,9 @@ end:
* \param prev_seg Previous segment in the stream segment list
* \param p Packet
*
* \retval 1 done
* \retval 0 not done yet
* \retval -1 error
* \retval 1 success and done
* \retval 0 success, but not done yet
* \retval -1 error, will *only* happen on memory errors
*/
static int HandleSegmentStartsBeforeListSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
@ -729,6 +736,8 @@ static int HandleSegmentStartsBeforeListSegment(ThreadVars *tv, TcpReassemblyThr
TcpSegment *new_seg = StreamTcpGetSegment(tv, ra_ctx, packet_length);
if (new_seg == NULL) {
SCLogDebug("segment_pool[%"PRIu16"] is empty", segment_pool_idx[packet_length]);
StreamTcpSetEvent(p, STREAM_REASSEMBLY_NO_SEGMENT);
SCReturnInt(-1);
}
new_seg->payload_len = packet_length;
@ -791,6 +800,8 @@ static int HandleSegmentStartsBeforeListSegment(ThreadVars *tv, TcpReassemblyThr
TcpSegment *new_seg = StreamTcpGetSegment(tv, ra_ctx, packet_length);
if (new_seg == NULL) {
SCLogDebug("segment_pool[%"PRIu16"] is empty", segment_pool_idx[packet_length]);
StreamTcpSetEvent(p, STREAM_REASSEMBLY_NO_SEGMENT);
SCReturnInt(-1);
}
@ -849,6 +860,8 @@ static int HandleSegmentStartsBeforeListSegment(ThreadVars *tv, TcpReassemblyThr
TcpSegment *new_seg = StreamTcpGetSegment(tv, ra_ctx, packet_length);
if (new_seg == NULL) {
SCLogDebug("segment_pool[%"PRIu16"] is empty", segment_pool_idx[packet_length]);
StreamTcpSetEvent(p, STREAM_REASSEMBLY_NO_SEGMENT);
SCReturnInt(-1);
}
new_seg->payload_len = packet_length;
@ -900,64 +913,66 @@ static int HandleSegmentStartsBeforeListSegment(ThreadVars *tv, TcpReassemblyThr
} else {
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 = 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(tv, ra_ctx, packet_length);
if (new_seg == NULL) {
SCLogDebug("segment_pool[%"PRIu16"] is empty",
segment_pool_idx[packet_length]);
SCReturnInt(-1);
}
new_seg->payload_len = packet_length;
TcpSegment *new_seg = StreamTcpGetSegment(tv, ra_ctx, packet_length);
if (new_seg == NULL) {
SCLogDebug("segment_pool[%"PRIu16"] is empty",
segment_pool_idx[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 {
new_seg->seq = seg->seq;
}
SCLogDebug("new_seg->seq %"PRIu32" and new->payload_len "
"%" PRIu16"", new_seg->seq, new_seg->payload_len);
new_seg->next = list_seg->next;
new_seg->prev = list_seg->prev;
StreamTcpSetEvent(p, STREAM_REASSEMBLY_NO_SEGMENT);
SCReturnInt(-1);
}
new_seg->payload_len = packet_length;
/* create a new seg, copy the list_seg data over */
StreamTcpSegmentDataCopy(new_seg, list_seg);
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;
}
SCLogDebug("new_seg->seq %"PRIu32" and new->payload_len "
"%" PRIu16"", new_seg->seq, new_seg->payload_len);
new_seg->next = list_seg->next;
new_seg->prev = list_seg->prev;
/* 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);
/* create a new seg, copy the list_seg data over */
StreamTcpSegmentDataCopy(new_seg, list_seg);
/* copy the part after list_seg */
copy_len = (seg->seq + seg->payload_len) -
(list_seg->seq + list_seg->payload_len);
StreamTcpSegmentDataReplace(new_seg, seg, (list_seg->seq +
list_seg->payload_len), copy_len);
/* 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);
if (new_seg->prev != NULL) {
new_seg->prev->next = new_seg;
}
/* copy the part after list_seg */
copy_len = (seg->seq + seg->payload_len) -
(list_seg->seq + list_seg->payload_len);
StreamTcpSegmentDataReplace(new_seg, seg, (list_seg->seq +
list_seg->payload_len), copy_len);
/*update the stream last_seg in case of removal of list_seg*/
if (stream->seg_list_tail == list_seg)
stream->seg_list_tail = new_seg;
if (new_seg->prev != NULL) {
new_seg->prev->next = new_seg;
}
StreamTcpSegmentReturntoPool(list_seg);
list_seg = new_seg;
return_after = TRUE;
/*update the stream last_seg in case of removal of list_seg*/
if (stream->seg_list_tail == list_seg)
stream->seg_list_tail = new_seg;
StreamTcpSegmentReturntoPool(list_seg);
list_seg = new_seg;
return_after = TRUE;
}
}
@ -1025,9 +1040,10 @@ static int HandleSegmentStartsBeforeListSegment(ThreadVars *tv, TcpReassemblyThr
* \param list_seg Original Segment in the stream
* \param seg Newly arrived segment
* \param prev_seg Previous segment in the stream segment list
* \retval 1 done
* \retval 0 not done yet
* \retval -1 error
*
* \retval 1 success and done
* \retval 0 success, but not done yet
* \retval -1 error, will *only* happen on memory errors
*/
static int HandleSegmentStartsAtSameListSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
@ -1130,6 +1146,8 @@ static int HandleSegmentStartsAtSameListSegment(ThreadVars *tv, TcpReassemblyThr
TcpSegment *new_seg = StreamTcpGetSegment(tv, ra_ctx, packet_length);
if (new_seg == NULL) {
SCLogDebug("egment_pool[%"PRIu16"] is empty", segment_pool_idx[packet_length]);
StreamTcpSetEvent(p, STREAM_REASSEMBLY_NO_SEGMENT);
return -1;
}
new_seg->payload_len = packet_length;
@ -1208,6 +1226,7 @@ static int HandleSegmentStartsAtSameListSegment(ThreadVars *tv, TcpReassemblyThr
}
/**
* \internal
* \brief Function to handle the newly arrived segment, when newly arrived
* starts with the sequence number higher than the original segment and
* ends at different position relative to original segment.
@ -1216,9 +1235,10 @@ static int HandleSegmentStartsAtSameListSegment(ThreadVars *tv, TcpReassemblyThr
* \param list_seg Original Segment in the stream
* \param seg Newly arrived segment
* \param prev_seg Previous segment in the stream segment list
* \retval 1 done
* \retval 0 not done yet
* \retval -1 error
* \retval 1 success and done
* \retval 0 success, but not done yet
* \retval -1 error, will *only* happen on memory errors
*/
static int HandleSegmentStartsAfterListSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
@ -1325,6 +1345,8 @@ static int HandleSegmentStartsAfterListSegment(ThreadVars *tv, TcpReassemblyThre
TcpSegment *new_seg = StreamTcpGetSegment(tv, ra_ctx, packet_length);
if (new_seg == NULL) {
SCLogDebug("segment_pool[%"PRIu16"] is empty", segment_pool_idx[packet_length]);
StreamTcpSetEvent(p, STREAM_REASSEMBLY_NO_SEGMENT);
SCReturnInt(-1);
}
new_seg->payload_len = packet_length;
@ -1457,6 +1479,16 @@ static uint32_t StreamTcpReassembleCheckDepth(TcpStream *stream,
SCReturnUInt(0);
}
/**
* \brief Insert a packets TCP data into the stream reassembly engine.
*
* \retval 0 good segment, as far as we checked.
* \retval -1 badness, reason to drop in inline mode
*
* If the retval is 0 the segment is inserted correctly, or overlap is handled,
* or it wasn't added because of reassembly depth.
*
*/
int StreamTcpReassembleHandleSegmentHandleData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
TcpSession *ssn, TcpStream *stream, Packet *p)
{
@ -1490,6 +1522,8 @@ int StreamTcpReassembleHandleSegmentHandleData(ThreadVars *tv, TcpReassemblyThre
TcpSegment *seg = StreamTcpGetSegment(tv, ra_ctx, p->payload_len);
if (seg == NULL) {
SCLogDebug("segment_pool[%"PRIu16"] is empty", segment_pool_idx[p->payload_len]);
StreamTcpSetEvent(p, STREAM_REASSEMBLY_NO_SEGMENT);
SCReturnInt(-1);
}
@ -1704,7 +1738,9 @@ static int StreamTcpReassembleAppLayer (TcpReassemblyThreadCtx *ra_ctx,
}
SCLogDebug("stream->seg_list %p", stream->seg_list);
#ifdef DEBUG
PrintList(stream->seg_list);
#endif
if (stream->seg_list == NULL) {
/* send an empty EOF msg if we have no segments but TCP state

@ -66,6 +66,8 @@ int StreamTcpCheckMemcap(uint32_t);
void StreamTcpPseudoPacketSetupHeader(Packet *, Packet *);
Packet *StreamTcpPseudoSetup(Packet *, uint8_t *, uint32_t);
void StreamTcpSetEvent(Packet *p, uint8_t e);
/** ------- Inline functions: ------ */
/**

Loading…
Cancel
Save