mirror of https://github.com/OISF/suricata
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
506 lines
20 KiB
C
506 lines
20 KiB
C
/* Copyright (c) 2008 Victor Julien <victor@inliniac.net> */
|
|
|
|
/* TODO:
|
|
* - segment insert fasttrack: most pkts are in order
|
|
* - OS depended handling of overlaps, retrans, etc
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <pthread.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <arpa/inet.h>
|
|
#include <netinet/in.h>
|
|
|
|
#include "eidps.h"
|
|
#include "debug.h"
|
|
#include "detect.h"
|
|
#include "flow.h"
|
|
#include "threads.h"
|
|
|
|
#include "threadvars.h"
|
|
#include "tm-modules.h"
|
|
|
|
#include "util-pool.h"
|
|
#include "util-unittest.h"
|
|
#include "util-print.h"
|
|
|
|
#include "stream-tcp-private.h"
|
|
|
|
#include "stream.h"
|
|
|
|
void *TcpSegmentAlloc(void *payload_len) {
|
|
TcpSegment *seg = malloc(sizeof(TcpSegment));
|
|
if (seg == NULL)
|
|
return NULL;
|
|
|
|
memset(seg, 0, sizeof(TcpSegment));
|
|
|
|
seg->pool_size = *((u_int16_t *)payload_len);
|
|
seg->payload_len = seg->pool_size;
|
|
|
|
seg->payload = malloc(seg->payload_len);
|
|
if (seg->payload == NULL) {
|
|
free(seg);
|
|
return NULL;
|
|
}
|
|
|
|
return seg;
|
|
}
|
|
|
|
void TcpSegmentFree(void *ptr) {
|
|
if (ptr == NULL)
|
|
return;
|
|
|
|
TcpSegment *seg = (TcpSegment *)ptr;
|
|
free(seg->payload);
|
|
free(seg);
|
|
return;
|
|
}
|
|
|
|
/* We define serveral pools with prealloced segments with fixed size
|
|
* payloads. We do this to prevent having to do an malloc call for every
|
|
* data segment we receive, which would be a large performance penalty.
|
|
* The cost is in memory of course. */
|
|
#define segment_pool_num 8
|
|
static u_int16_t segment_pool_pktsizes[segment_pool_num] = { 4, 16, 112, 248, 512, 768, 1448, 0xffff };
|
|
static u_int16_t segment_pool_poolsizes[segment_pool_num] = { 1024, 1024, 1024, 1024, 4096, 4096, 1024, 128 };
|
|
static Pool *segment_pool[segment_pool_num];
|
|
static pthread_mutex_t segment_pool_mutex[segment_pool_num];
|
|
/* index to the right pool for all packet sizes. */
|
|
static u_int16_t segment_pool_idx[65536]; /* O(1) lookups of the pool */
|
|
|
|
int StreamTcpReassembleInit(void) {
|
|
StreamMsgQueuesInit();
|
|
|
|
u_int16_t u16 = 0;
|
|
for (u16 = 0; u16 < segment_pool_num; u16++) {
|
|
segment_pool[u16] = PoolInit(segment_pool_poolsizes[u16], segment_pool_poolsizes[u16]/2, TcpSegmentAlloc, (void *)&segment_pool_pktsizes[u16], TcpSegmentFree);
|
|
pthread_mutex_init(&segment_pool_mutex[u16], NULL);
|
|
}
|
|
|
|
u_int16_t idx = 0;
|
|
u16 = 0;
|
|
while (1) {
|
|
if (idx <= segment_pool_pktsizes[u16]) {
|
|
segment_pool_idx[idx] = u16;
|
|
if (segment_pool_pktsizes[u16] == idx)
|
|
u16++;
|
|
}
|
|
|
|
if (idx == 0xffff)
|
|
break;
|
|
|
|
idx++;
|
|
}
|
|
|
|
/*
|
|
printf("pkt 0 : idx %u\n", segment_pool_idx[0]);
|
|
printf("pkt 1 : idx %u\n", segment_pool_idx[1]);
|
|
printf("pkt 1200 : idx %u\n", segment_pool_idx[1200]);
|
|
printf("pkt 32 : idx %u\n", segment_pool_idx[32]);
|
|
printf("pkt 1448 : idx %u\n", segment_pool_idx[1448]);
|
|
printf("pkt 1449 : idx %u\n", segment_pool_idx[1449]);
|
|
printf("pkt 65534: idx %u\n", segment_pool_idx[65534]);
|
|
printf("pkt 65535: idx %u\n", segment_pool_idx[65535]);
|
|
*/
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int ReassembleInsertSegment(TcpStream *stream, TcpSegment *seg) {
|
|
TcpSegment *list_seg = stream->seg_list, *prev_seg = NULL;
|
|
if (list_seg == NULL) {
|
|
printf("ReassembleInsertSegment: empty list, inserting %u, len %u\n", seg->seq, seg->payload_len);
|
|
stream->seg_list = seg;
|
|
return 0;
|
|
}
|
|
|
|
for ( ; list_seg != NULL; prev_seg = list_seg, list_seg = list_seg->next) {
|
|
printf("ReassembleInsertSegment: seg %p, list_seg %p, list_seg->next %p\n", seg, list_seg, list_seg->next);
|
|
|
|
/* seg is entirely before list_seg */
|
|
if (SEQ_LT(seg->seq, list_seg->seq) &&
|
|
SEQ_LT((seg->seq + seg->payload_len), list_seg->seq)) {
|
|
|
|
printf("ReassembleInsertSegment: before list seg: seg->seq %u, list_seg->seq %u, list_seg->payload_len %u\n", seg->seq, list_seg->seq, list_seg->payload_len);
|
|
seg->next = list_seg;
|
|
if (prev_seg == NULL) stream->seg_list = seg;
|
|
else prev_seg->next = seg;
|
|
return 0;
|
|
|
|
/* seg partly overlaps with list_seg, starts before, ends on list seq */
|
|
} else if (SEQ_LT(seg->seq, list_seg->seq) &&
|
|
SEQ_EQ((seg->seq + seg->payload_len), list_seg->seq)) {
|
|
|
|
/* XXX depends on target OS */
|
|
printf("ReassembleInsertSegment: starts before list seg, ends on list seq: seg->seq %u, list_seg->seq %u, list_seg->payload_len %u\n", seg->seq, list_seg->seq, list_seg->payload_len);
|
|
|
|
/* seg partly overlaps with list_seg, starts before, ends inside */
|
|
} else if (SEQ_LT(seg->seq, list_seg->seq) &&
|
|
SEQ_GT((seg->seq + seg->payload_len), list_seg->seq) &&
|
|
SEQ_LT((seg->seq + seg->payload_len),
|
|
(list_seg->seq+list_seg->payload_len))) {
|
|
|
|
/* XXX depends on target OS */
|
|
printf("ReassembleInsertSegment: starts before list seg, ends inside list: seg->seq %u, list_seg->seq %u, list_seg->payload_len %u\n", seg->seq, list_seg->seq, list_seg->payload_len);
|
|
|
|
/* seg fully overlaps list_seg, starts before, at end point */
|
|
} else if (SEQ_LT(seg->seq, list_seg->seq) &&
|
|
SEQ_EQ((seg->seq + seg->payload_len),
|
|
(list_seg->seq + list_seg->payload_len))) {
|
|
|
|
printf("ReassembleInsertSegment: starts before list seg, ends at list end: seg->seq %u, list_seg->seq %u, list_seg->payload_len %u\n", seg->seq, list_seg->seq, list_seg->payload_len);
|
|
|
|
/* seg fully overlaps list_seg, starts before, ends after list endpoint */
|
|
} else if (SEQ_LT(seg->seq, list_seg->seq) &&
|
|
SEQ_GT((seg->seq + seg->payload_len),
|
|
(list_seg->seq + list_seg->payload_len))) {
|
|
|
|
printf("ReassembleInsertSegment: starts before list seg, ends before list end: seg->seq %u, list_seg->seq %u, list_seg->payload_len %u\n", seg->seq, list_seg->seq, list_seg->payload_len);
|
|
|
|
/* seg starts at seq, but end before list_seg end. */
|
|
} else if (SEQ_EQ(seg->seq, list_seg->seq) &&
|
|
SEQ_LT((seg->seq + seg->payload_len),
|
|
(list_seg->seq + list_seg->payload_len))) {
|
|
|
|
printf("ReassembleInsertSegment: starts at list seq, ends before list end: seg->seq %u, list_seg->seq %u, list_seg->payload_len %u\n", seg->seq, list_seg->seq, list_seg->payload_len);
|
|
|
|
/* seg starts at seq, ends at seq, retransmission. */
|
|
} else if (SEQ_EQ(seg->seq, list_seg->seq) &&
|
|
SEQ_EQ((seg->seq + seg->payload_len),
|
|
(list_seg->seq + list_seg->payload_len))) {
|
|
/* check csum, ack, other differences? */
|
|
printf("ReassembleInsertSegment: (retransmission) starts at list seq, ends at list end: seg->seq %u, list_seg->seq %u, list_seg->payload_len %u\n", seg->seq, list_seg->seq, list_seg->payload_len);
|
|
|
|
/* seg starts at seq, ends beyond seq. */
|
|
} else if (SEQ_EQ(seg->seq, list_seg->seq) &&
|
|
SEQ_GT((seg->seq + seg->payload_len),
|
|
(list_seg->seq + list_seg->payload_len))) {
|
|
|
|
printf("ReassembleInsertSegment: starts at list seq, ends beyond list end: seg->seq %u, list_seg->seq %u, list_seg->payload_len %u\n", seg->seq, list_seg->seq, list_seg->payload_len);
|
|
|
|
/* seg starts after seq, before end, ends before seq. */
|
|
} else if (SEQ_GT(seg->seq, list_seg->seq) &&
|
|
SEQ_LT((seg->seq + seg->payload_len),
|
|
(list_seg->seq + list_seg->payload_len))) {
|
|
|
|
printf("ReassembleInsertSegment: starts beyond list seq, ends before list end: seg->seq %u, list_seg->seq %u, list_seg->payload_len %u\n", seg->seq, list_seg->seq, list_seg->payload_len);
|
|
|
|
/* seg starts after seq, before end, ends at seq. */
|
|
} else if (SEQ_GT(seg->seq, list_seg->seq) &&
|
|
SEQ_EQ((seg->seq + seg->payload_len),
|
|
(list_seg->seq + list_seg->payload_len))) {
|
|
|
|
printf("ReassembleInsertSegment: starts beyond list seq, ends at list end: seg->seq %u, list_seg->seq %u, list_seg->payload_len %u\n", seg->seq, list_seg->seq, list_seg->payload_len);
|
|
|
|
/* seg starts after seq, before end, ends beyond seq. */
|
|
} else if (SEQ_GT(seg->seq, list_seg->seq) &&
|
|
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))) {
|
|
|
|
printf("ReassembleInsertSegment: starts beyond list seq, before list end, ends at list end: seg->seq %u, list_seg->seq %u, list_seg->payload_len %u\n", seg->seq, list_seg->seq, list_seg->payload_len);
|
|
|
|
/* seg starts on end seq, ends beyond seq. */
|
|
} else if (SEQ_EQ(seg->seq, (list_seg->seq + list_seg->payload_len)) &&
|
|
SEQ_GT((seg->seq + seg->payload_len),
|
|
(list_seg->seq+list_seg->payload_len))) {
|
|
if (list_seg->next == NULL) {
|
|
printf("ReassembleInsertSegment: (normal insert) starts at list end, ends beyond list end: seg->seq %u, list_seg->seq %u, list_seg->payload_len %u\n", seg->seq, list_seg->seq, list_seg->payload_len);
|
|
list_seg->next = seg;
|
|
return 0;
|
|
} else {
|
|
printf("ReassembleInsertSegment: (normal, inspect more of the list) starts at list seq, ends beyond list end: seg->seq %u, list_seg->seq %u, list_seg->payload_len %u\n", seg->seq, list_seg->seq, list_seg->payload_len);
|
|
}
|
|
|
|
/* seg starts beyond end seq, ends beyond seq. */
|
|
} else if (SEQ_GT(seg->seq, (list_seg->seq + list_seg->payload_len)) &&
|
|
SEQ_GT((seg->seq + seg->payload_len),
|
|
(list_seg->seq+list_seg->payload_len))) {
|
|
printf("ReassembleInsertSegment: starts beyond list end, ends after list end: seg->seq %u, list_seg->seq %u, list_seg->payload_len %u (%u)\n", 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;
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int StreamTcpReassembleHandleSegmentHandleData (TcpSession *ssn, TcpStream *stream, Packet *p) {
|
|
u_int16_t idx = segment_pool_idx[p->payload_len];
|
|
//printf("StreamTcpReassembleHandleSegmentHandleData: idx %u for payload_len %u\n", idx, p->payload_len);
|
|
|
|
mutex_lock(&segment_pool_mutex[idx]);
|
|
//printf("StreamTcpReassembleHandleSegmentHandleData: mutex locked, getting data from pool %p\n", segment_pool[idx]);
|
|
TcpSegment *seg = (TcpSegment *)PoolGet(segment_pool[idx]);
|
|
mutex_unlock(&segment_pool_mutex[idx]);
|
|
|
|
if (seg == NULL) {
|
|
return -1;
|
|
}
|
|
//printf("StreamTcpReassembleHandleSegmentHandleData: seg %p, seg->pool_size %u\n", seg, seg->pool_size);
|
|
|
|
memcpy(seg->payload, p->payload, p->payload_len);
|
|
seg->payload_len = p->payload_len;
|
|
seg->seq = TCP_GET_SEQ(p);
|
|
seg->next = NULL;
|
|
|
|
ReassembleInsertSegment(stream, seg);
|
|
return 0;
|
|
}
|
|
|
|
/* initialize the first msg */
|
|
static void StreamTcpSetupInitMsg(Packet *p, StreamMsg *smsg) {
|
|
smsg->flags |= STREAM_START;
|
|
|
|
if (p->flowflags & FLOW_PKT_TOSERVER) {
|
|
COPY_ADDRESS(&p->flow->src,&smsg->data.src_ip);
|
|
COPY_ADDRESS(&p->flow->dst,&smsg->data.dst_ip);
|
|
COPY_PORT(p->flow->sp,smsg->data.src_port);
|
|
COPY_PORT(p->flow->dp,smsg->data.dst_port);
|
|
|
|
smsg->flags |= STREAM_TOSERVER;
|
|
} else {
|
|
COPY_ADDRESS(&p->flow->dst,&smsg->data.src_ip);
|
|
COPY_ADDRESS(&p->flow->src,&smsg->data.dst_ip);
|
|
COPY_PORT(p->flow->dp,smsg->data.src_port);
|
|
COPY_PORT(p->flow->sp,smsg->data.dst_port);
|
|
|
|
smsg->flags |= STREAM_TOCLIENT;
|
|
}
|
|
}
|
|
|
|
int StreamTcpReassembleHandleSegmentUpdateACK (TcpSession *ssn, TcpStream *stream, Packet *p) {
|
|
if (stream->seg_list == NULL)
|
|
return 0;
|
|
|
|
printf("StreamTcpReassembleHandleSegmentUpdateACK: start\n");
|
|
|
|
StreamMsg *smsg = NULL;
|
|
char remove = FALSE;
|
|
u_int16_t smsg_offset = 0;
|
|
u_int16_t payload_offset = 0;
|
|
u_int16_t payload_len = 0;
|
|
TcpSegment *seg = stream->seg_list;
|
|
|
|
/* check if we have enough data to send to L7 */
|
|
if (p->flowflags & FLOW_PKT_TOSERVER) {
|
|
if (stream->ra_base_seq == stream->isn) {
|
|
if (StreamMsgQueueGetMinInitChunkLen(STREAM_TOSERVER) >
|
|
(stream->last_ack - stream->ra_base_seq))
|
|
return 0;
|
|
} else {
|
|
if (StreamMsgQueueGetMinChunkLen(STREAM_TOSERVER) >
|
|
(stream->last_ack - stream->ra_base_seq))
|
|
return 0;
|
|
}
|
|
} else {
|
|
if (stream->ra_base_seq == stream->isn) {
|
|
if (StreamMsgQueueGetMinInitChunkLen(STREAM_TOCLIENT) >
|
|
(stream->last_ack - stream->ra_base_seq))
|
|
return 0;
|
|
} else {
|
|
if (StreamMsgQueueGetMinChunkLen(STREAM_TOCLIENT) >
|
|
(stream->last_ack - stream->ra_base_seq))
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* loop through the segments and fill one or more msgs */
|
|
for ( ; seg != NULL && SEQ_LT(seg->seq,stream->last_ack); ) {
|
|
printf("StreamTcpReassembleHandleSegmentUpdateACK: seg %p\n", seg);
|
|
|
|
/* if the segment ends beyond ra_base_seq we need to consider it */
|
|
if (SEQ_GEQ((seg->seq + seg->payload_len),stream->ra_base_seq)) {
|
|
/* get a message */
|
|
if (smsg == NULL) {
|
|
smsg = StreamMsgGetFromPool();
|
|
if (smsg == NULL) {
|
|
printf("StreamTcpReassembleHandleSegmentUpdateACK: couldn't "
|
|
"get a stream msg from the pool\n");
|
|
return -1;
|
|
}
|
|
|
|
smsg_offset = 0;
|
|
|
|
if (stream->ra_base_seq == stream->isn) {
|
|
StreamTcpSetupInitMsg(p, smsg);
|
|
}
|
|
smsg->data.data_len = 0;
|
|
smsg->flow = p->flow;
|
|
}
|
|
|
|
/* handle segments partly before ra_base_seq */
|
|
if (SEQ_GT(stream->ra_base_seq, seg->seq)) {
|
|
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;
|
|
//printf("StreamTcpReassembleHandleSegmentUpdateACK: starts "
|
|
// "before ra_base, ends beyond last_ack, payload_offset %u, "
|
|
// "payload_len %u\n", payload_offset, payload_len);
|
|
} else {
|
|
payload_len = seg->payload_len - payload_offset;
|
|
//printf("StreamTcpReassembleHandleSegmentUpdateACK: starts "
|
|
// "before ra_base, ends normal, payload_offset %u, "
|
|
// "payload_len %u\n", payload_offset, payload_len);
|
|
}
|
|
/* handle segments after ra_base_seq */
|
|
} else {
|
|
payload_offset = 0;
|
|
|
|
if (SEQ_LT(stream->last_ack,(seg->seq + seg->payload_len))) {
|
|
payload_len = stream->last_ack - seg->seq;
|
|
//printf("StreamTcpReassembleHandleSegmentUpdateACK: start "
|
|
// "fine, ends beyond last_ack, payload_offset %u, "
|
|
// "payload_len %u\n", payload_offset, payload_len);
|
|
} else {
|
|
payload_len = seg->payload_len;
|
|
//printf("StreamTcpReassembleHandleSegmentUpdateACK: normal "
|
|
// "(smsg_offset %u), payload_offset %u, payload_len %u\n",
|
|
// smsg_offset, payload_offset, payload_len);
|
|
}
|
|
}
|
|
|
|
u_int16_t copy_size = sizeof(smsg->data.data) - smsg_offset;
|
|
if (copy_size > payload_len) {
|
|
copy_size = payload_len;
|
|
}
|
|
printf("StreamTcpReassembleHandleSegmentUpdateACK: copy_size %u "
|
|
"(payload %u)\n", copy_size, payload_len);
|
|
|
|
memcpy(smsg->data.data + smsg_offset, seg->payload + payload_offset, copy_size);
|
|
|
|
smsg_offset += copy_size;
|
|
stream->ra_base_seq += copy_size;
|
|
smsg->data.data_len += copy_size;
|
|
|
|
if (copy_size < payload_len) {
|
|
printf("StreamTcpReassembleHandleSegmentUpdateACK: "
|
|
"copy_size %u < %u\n", copy_size, payload_len);
|
|
|
|
StreamMsgPutInQueue(smsg);
|
|
smsg = NULL;
|
|
payload_offset = copy_size + payload_offset;
|
|
printf("StreamTcpReassembleHandleSegmentUpdateACK: "
|
|
"payload_offset %u\n", payload_offset);
|
|
|
|
/* we need a while loop here as the packets theoretically can be 64k */
|
|
|
|
while (remove == FALSE) {
|
|
printf("StreamTcpReassembleHandleSegmentUpdateACK: "
|
|
"new msg at offset %u, payload_len %u\n", payload_offset, payload_len);
|
|
|
|
/* get a new message */
|
|
smsg = StreamMsgGetFromPool();
|
|
if (smsg == NULL) {
|
|
printf("StreamTcpReassembleHandleSegmentUpdateACK: "
|
|
"couldn't get a stream msg from the pool (while loop)\n");
|
|
return -1;
|
|
}
|
|
smsg_offset = 0;
|
|
smsg->data.data_len = 0;
|
|
smsg->flow = p->flow;
|
|
|
|
copy_size = sizeof(smsg->data.data) - smsg_offset;
|
|
if (copy_size > (payload_len - payload_offset)) {
|
|
copy_size = (payload_len - payload_offset);
|
|
}
|
|
|
|
printf("StreamTcpReassembleHandleSegmentUpdateACK: copy "
|
|
"payload_offset %u, smsg_offset %u, copy_size %u\n",
|
|
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;
|
|
smsg->data.data_len += copy_size;
|
|
|
|
printf("StreamTcpReassembleHandleSegmentUpdateACK: copied "
|
|
"payload_offset %u, smsg_offset %u, copy_size %u\n",
|
|
payload_offset, smsg_offset, copy_size);
|
|
|
|
if ((copy_size + payload_offset) < payload_len) {
|
|
payload_offset += copy_size;
|
|
printf("StreamTcpReassembleHandleSegmentUpdateACK: loop not done\n");
|
|
} else {
|
|
printf("StreamTcpReassembleHandleSegmentUpdateACK: loop done\n");
|
|
payload_offset = 0;
|
|
remove = TRUE;
|
|
}
|
|
}
|
|
} else {
|
|
payload_offset = 0;
|
|
remove = TRUE;
|
|
}
|
|
}
|
|
|
|
TcpSegment *next_seg = seg->next;
|
|
|
|
/* done with this segment, return it to the pool */
|
|
if (remove == TRUE) {
|
|
printf("StreamTcpReassembleHandleSegmentUpdateACK: removing seg %p, "
|
|
"seg->next %p\n", seg, seg->next);
|
|
stream->seg_list = seg->next;
|
|
|
|
u_int16_t idx = segment_pool_idx[seg->pool_size];
|
|
mutex_lock(&segment_pool_mutex[idx]);
|
|
//printf("StreamTcpReassembleHandleSegmentHandleData: mutex locked, getting data from pool %p\n", segment_pool[idx]);
|
|
PoolReturn(segment_pool[idx], (void *)seg);
|
|
mutex_unlock(&segment_pool_mutex[idx]);
|
|
|
|
remove = FALSE;
|
|
}
|
|
|
|
seg = next_seg;
|
|
}
|
|
|
|
/* put the partly filled smsg in the queue to the l7 handler */
|
|
if (smsg != NULL) {
|
|
StreamMsgPutInQueue(smsg);
|
|
smsg = NULL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int StreamTcpReassembleHandleSegment (TcpSession *ssn, TcpStream *stream, Packet *p) {
|
|
/* handle ack received */
|
|
StreamTcpReassembleHandleSegmentUpdateACK(ssn, stream, p);
|
|
|
|
if (p->payload_len > 0) {
|
|
StreamTcpReassembleHandleSegmentHandleData(ssn, stream, p);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Initialize the l7data ptr in the TCP session used
|
|
* by the L7 Modules for data storage.
|
|
*
|
|
* ssn = TcpSesssion
|
|
* cnt = number of items in the array
|
|
*
|
|
* XXX use a pool?
|
|
*/
|
|
void StreamL7DataPtrInit(TcpSession *ssn, u_int8_t cnt) {
|
|
if (cnt == 0)
|
|
return;
|
|
|
|
ssn->l7data = (void **)malloc(sizeof(void *) * cnt);
|
|
if (ssn->l7data != NULL) {
|
|
u_int8_t u;
|
|
for (u = 0; u < cnt; u++) {
|
|
ssn->l7data[u] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|