Pool update. Stream reassembly start.

remotes/origin/master-1.0.x
Victor Julien 16 years ago
parent 8397413942
commit 668e9514d7

@ -87,7 +87,8 @@ alert-debuglog.c alert-debuglog.h \
log-httplog.c log-httplog.h \
alert-unified-log.c alert-unified-log.h \
alert-unified-alert.c alert-unified-alert.h \
stream-tcp.c stream-tcp.h \
stream-tcp.c stream-tcp.h stream-tcp-private.h \
stream-tcp-reassemble.c stream-tcp-reassemble.h \
respond-reject.c respond-reject.h \
respond-reject-libnet11.h respond-reject-libnet11.c

@ -0,0 +1,56 @@
#ifndef __STREAM_TCP_PRIVATE_H__
#define __STREAM_TCP_PRIVATE_H__
typedef struct _TcpSegment {
u_int8_t *payload;
u_int16_t payload_len; /* actual size of the payload */
u_int32_t seq;
u_int16_t pool_size; /* size of the memory */
struct _TcpSegment *next;
struct _TcpSegment *prev;
} TcpSegment;
typedef struct _TcpStream {
u_int32_t isn; /* initial sequence number */
u_int32_t next_seq; /* next expected sequence number */
u_int32_t last_ack; /* last ack'd sequence number */
u_int32_t next_win; /* next max seq within window */
u_int8_t wscale;
u_int16_t window;
/* reassembly */
u_int32_t ra_base_seq; /* reassembled seq. We've reassembled up to this point. */
TcpSegment *seg_list;
} TcpStream;
/* from /usr/include/netinet/tcp.h */
enum
{
TCP_ESTABLISHED = 1,
TCP_SYN_SENT,
TCP_SYN_RECV,
TCP_FIN_WAIT1,
TCP_FIN_WAIT2,
TCP_TIME_WAIT,
TCP_CLOSE,
TCP_CLOSE_WAIT,
TCP_LAST_ACK,
TCP_LISTEN,
TCP_CLOSING /* now a valid state */
};
/* Macro's for comparing Sequence numbers
* Page 810 from TCP/IP Illustrated, Volume 2. */
#define SEQ_EQ(a,b) ((int)((a) - (b)) == 0)
#define SEQ_LT(a,b) ((int)((a) - (b)) < 0)
#define SEQ_LEQ(a,b) ((int)((a) - (b)) <= 0)
#define SEQ_GT(a,b) ((int)((a) - (b)) > 0)
#define SEQ_GEQ(a,b) ((int)((a) - (b)) >= 0)
typedef struct _TcpSession {
u_int8_t state;
TcpStream server;
TcpStream client;
} TcpSession;
#endif /* __STREAM_TCP_PRIVATE_H__ */

@ -0,0 +1,313 @@
/* 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 "vips.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"
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) {
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);
ReassembleInsertSegment(stream, seg);
return 0;
}
int StreamTcpReassembleHandleSegmentUpdateACK (TcpSession *ssn, TcpStream *stream, Packet *p) {
if (stream->seg_list == NULL)
return 0;
char remove = FALSE;
TcpSegment *seg = stream->seg_list;
printf("STREAM START\n");
for ( ; seg != NULL && SEQ_LT(seg->seq,stream->last_ack); seg = seg->next) {
if (SEQ_GEQ(seg->seq,stream->ra_base_seq)) {
if (SEQ_GT(stream->ra_base_seq, seg->seq)) {
u_int16_t offset = stream->ra_base_seq - seg->seq;
if (SEQ_LT(stream->last_ack,(seg->seq + seg->payload_len))) {
PrintRawDataFp(stdout, (seg->payload + offset), (stream->last_ack - seg->seq - offset));
} else {
PrintRawDataFp(stdout, (seg->payload + offset), (seg->payload_len - offset));
remove = TRUE;
}
} else {
if (SEQ_LT(stream->last_ack,(seg->seq + seg->payload_len))) {
PrintRawDataFp(stdout,seg->payload,(stream->last_ack - seg->seq));
} else {
PrintRawDataFp(stdout,seg->payload,seg->payload_len);
remove = TRUE;
}
}
}
/* done with this segment, return it to the pool */
if (remove == TRUE) {
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;
}
}
printf("STREAM END\n");
/* The base sequence number of the reassembly is updated to last ack */
stream->ra_base_seq = stream->last_ack;
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;
}

@ -0,0 +1,9 @@
/* Copyright (c) 2008 Victor Julien <victor@inliniac.net> */
#ifndef __STREAM_TCP_REASSEMBLE_H__
#define __STREAM_TCP_REASSEMBLE_H__
/* XXX */
#endif /* __STREAM_TCP_REASSEMBLE_H__ */

@ -23,51 +23,14 @@
#include "util-pool.h"
#include "util-unittest.h"
#include "stream-tcp-private.h"
int StreamTcp (ThreadVars *, Packet *, void *, PacketQueue *);
int StreamTcpThreadInit(ThreadVars *, void *, void **);
int StreamTcpThreadDeinit(ThreadVars *, void *);
void StreamTcpExitPrintStats(ThreadVars *, void *);
typedef struct _TcpStream {
u_int32_t isn; /* initial sequence number */
u_int32_t next_seq; /* next expected sequence number */
u_int32_t last_ack; /* last ack'd sequence number */
u_int32_t next_win; /* next max seq within window */
u_int8_t wscale;
u_int16_t window;
} TcpStream;
/* from /usr/include/netinet/tcp.h */
enum
{
TCP_ESTABLISHED = 1,
TCP_SYN_SENT,
TCP_SYN_RECV,
TCP_FIN_WAIT1,
TCP_FIN_WAIT2,
TCP_TIME_WAIT,
TCP_CLOSE,
TCP_CLOSE_WAIT,
TCP_LAST_ACK,
TCP_LISTEN,
TCP_CLOSING /* now a valid state */
};
/* Macro's for comparing Sequence numbers
* Page 810 from TCP/IP Illustrated, Volume 2. */
#define SEQ_EQ(a,b) ((int)((a) - (b)) == 0)
#define SEQ_LT(a,b) ((int)((a) - (b)) < 0)
#define SEQ_LEQ(a,b) ((int)((a) - (b)) <= 0)
#define SEQ_GT(a,b) ((int)((a) - (b)) > 0)
#define SEQ_GEQ(a,b) ((int)((a) - (b)) >= 0)
typedef struct _TcpSession {
u_int8_t state;
TcpStream server;
TcpStream client;
} TcpSession;
void *StreamTcpSessionAlloc(void) {
void *StreamTcpSessionAlloc(void *null) {
void *ptr = malloc(sizeof(TcpSession));
if (ptr == NULL)
return NULL;
@ -82,6 +45,8 @@ static Pool *ssn_pool;
static pthread_mutex_t ssn_pool_mutex;
void TmModuleStreamTcpRegister (void) {
StreamTcpReassembleInit();
tmm_modules[TMM_STREAMTCP].name = "StreamTcp";
tmm_modules[TMM_STREAMTCP].Init = StreamTcpThreadInit;
tmm_modules[TMM_STREAMTCP].Func = StreamTcp;
@ -89,7 +54,7 @@ void TmModuleStreamTcpRegister (void) {
tmm_modules[TMM_STREAMTCP].Deinit = StreamTcpThreadDeinit;
tmm_modules[TMM_STREAMTCP].RegisterTests = NULL;
ssn_pool = PoolInit(262144, 32768, StreamTcpSessionAlloc, StreamTcpSessionFree);
ssn_pool = PoolInit(262144, 32768, StreamTcpSessionAlloc, NULL, StreamTcpSessionFree);
if (ssn_pool == NULL) {
exit(1);
}
@ -123,6 +88,7 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p, StreamTcpThread *
/* set the sequence numbers and window */
ssn->client.isn = TCP_GET_SEQ(p);
ssn->client.ra_base_seq = ssn->client.isn;
ssn->client.next_seq = ssn->client.isn + 1;
ssn->client.window = TCP_GET_WINDOW(p);
@ -171,6 +137,7 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea
/* sequence number & window */
ssn->server.isn = TCP_GET_SEQ(p);
ssn->server.ra_base_seq = ssn->server.isn;
ssn->server.next_seq = ssn->server.isn + 1;
ssn->server.window = TCP_GET_WINDOW(p);
printf("StreamTcpPacketStateSynSent: (%p): window %u\n", ssn, ssn->server.window);
@ -191,6 +158,10 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea
printf("StreamTcpPacketStateSynSent (%p): ssn->server.isn %u, ssn->server.next_seq %u, ssn->CLIENT.last_ack %u\n",
ssn, ssn->server.isn, ssn->server.next_seq, ssn->client.last_ack);
break;
case TH_RST:
/* seq should be 0, win should be 0, ack should be isn +1.
* check Snort's stream4/5 for more security */
break;
default:
printf("StreamTcpPacketStateSynSent (%p): default case\n", ssn);
break;
@ -274,6 +245,8 @@ static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p, StreamTcpT
ssn->client.next_win = ssn->client.last_ack + ssn->client.window;
printf("StreamTcpPacketStateEstablished (%p): ssn->client.next_win %u\n", ssn, ssn->client.next_win);
}
StreamTcpReassembleHandleSegment(ssn, &ssn->client, p);
} else {
printf("StreamTcpPacketStateEstablished (%p): !!!!! => SEQ mismatch, packet SEQ %u, payload size %u (%u), last_ack %u, next_win %u\n",
ssn, TCP_GET_SEQ(p), p->payload_len, TCP_GET_SEQ(p) + p->payload_len, ssn->client.last_ack, ssn->client.next_win);
@ -301,6 +274,8 @@ static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p, StreamTcpT
ssn->server.next_win = ssn->server.last_ack + ssn->server.window;
printf("StreamTcpPacketStateEstablished (%p): ssn->server.next_win %u\n", ssn, ssn->server.next_win);
}
StreamTcpReassembleHandleSegment(ssn, &ssn->server, p);
} else {
printf("StreamTcpPacketStateEstablished (%p): !!!!! => SEQ mismatch, packet SEQ %u, payload size %u (%u), last_ack %u, next_win %u\n",
ssn, TCP_GET_SEQ(p), p->payload_len, TCP_GET_SEQ(p) + p->payload_len, ssn->server.last_ack, ssn->server.next_win);
@ -333,6 +308,8 @@ static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p, StreamTcpT
if (SEQ_GT(TCP_GET_ACK(p),ssn->server.last_ack))
ssn->server.last_ack = TCP_GET_ACK(p);
StreamTcpReassembleHandleSegment(ssn, &ssn->client, p);
printf("StreamTcpPacketStateEstablished (%p): =+ next SEQ %u, last ACK %u\n",
ssn, ssn->client.next_seq, ssn->server.last_ack);
} else { /* implied to client */
@ -355,10 +332,14 @@ static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p, StreamTcpT
if (SEQ_GT(TCP_GET_ACK(p),ssn->client.last_ack))
ssn->client.last_ack = TCP_GET_ACK(p);
StreamTcpReassembleHandleSegment(ssn, &ssn->server, p);
printf("StreamTcpPacketStateEstablished (%p): =+ next SEQ %u, last ACK %u\n",
ssn, ssn->server.next_seq, ssn->client.last_ack);
}
break;
case TH_RST:
break;
}
return 0;
@ -388,6 +369,8 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, StreamTcpThre
if (SEQ_GT(TCP_GET_ACK(p),ssn->server.last_ack))
ssn->server.last_ack = TCP_GET_ACK(p);
StreamTcpReassembleHandleSegment(ssn, &ssn->client, p);
printf("StreamTcpPacketStateFinWait1 (%p): =+ next SEQ %u, last ACK %u\n",
ssn, ssn->client.next_seq, ssn->server.last_ack);
} else { /* implied to client */
@ -407,6 +390,8 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, StreamTcpThre
if (SEQ_GT(TCP_GET_ACK(p),ssn->client.last_ack))
ssn->client.last_ack = TCP_GET_ACK(p);
StreamTcpReassembleHandleSegment(ssn, &ssn->server, p);
printf("StreamTcpPacketStateFinWait1 (%p): =+ next SEQ %u, last ACK %u\n",
ssn, ssn->server.next_seq, ssn->client.last_ack);
}
@ -438,6 +423,8 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p, StreamTcpThre
if (SEQ_GT(TCP_GET_ACK(p),ssn->server.last_ack))
ssn->server.last_ack = TCP_GET_ACK(p);
StreamTcpReassembleHandleSegment(ssn, &ssn->client, p);
printf("StreamTcpPacketStateFinWait2 (%p): =+ next SEQ %u, last ACK %u\n",
ssn, ssn->client.next_seq, ssn->server.last_ack);
} else { /* implied to client */
@ -457,6 +444,8 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p, StreamTcpThre
if (SEQ_GT(TCP_GET_ACK(p),ssn->client.last_ack))
ssn->client.last_ack = TCP_GET_ACK(p);
StreamTcpReassembleHandleSegment(ssn, &ssn->server, p);
printf("StreamTcpPacketStateFinWait2 (%p): =+ next SEQ %u, last ACK %u\n",
ssn, ssn->server.next_seq, ssn->client.last_ack);
}

@ -9,7 +9,7 @@
#include "util-unittest.h"
Pool *PoolInit(u_int32_t size, u_int32_t prealloc_size, void *(*Alloc)(void), void (*Free)(void *))
Pool *PoolInit(u_int32_t size, u_int32_t prealloc_size, void *(*Alloc)(void *), void *AllocData, void (*Free)(void *))
{
Pool *p = NULL;
@ -29,6 +29,7 @@ Pool *PoolInit(u_int32_t size, u_int32_t prealloc_size, void *(*Alloc)(void), vo
memset(p,0,sizeof(Pool));
p->Alloc = Alloc;
p->AllocData = AllocData;
p->Free = Free;
/* alloc the buckets and place them in the empty list */
@ -54,7 +55,7 @@ Pool *PoolInit(u_int32_t size, u_int32_t prealloc_size, void *(*Alloc)(void), vo
p->empty_list = pb->next;
p->empty_list_size--;
pb->data = p->Alloc();
pb->data = p->Alloc(p->AllocData);
pb->next = p->alloc_list;
p->alloc_list = pb;
@ -113,11 +114,29 @@ void *PoolGet(Pool *p) {
return ptr;
}
void PoolReturn(Pool *p, void *data) {
PoolBucket *pb = p->empty_list;
if (pb == NULL)
return;
/* pull from the alloc list */
p->empty_list = pb->next;
p->empty_list_size--;
/* put in the alloc list */
pb->next = p->alloc_list;
p->alloc_list = pb;
p->alloc_list_size++;
pb->data = data;
return;
}
/*
* ONLY TESTS BELOW THIS COMMENT
*/
void *PoolTestAlloc(void) {
void *PoolTestAlloc(void *allocdata) {
return malloc(10);
}
@ -126,7 +145,7 @@ void PoolTestFree(void *ptr) {
}
static int PoolTestInit01 (void) {
Pool *p = PoolInit(10,5,PoolTestAlloc,PoolTestFree);
Pool *p = PoolInit(10,5,PoolTestAlloc,NULL,PoolTestFree);
if (p == NULL)
return 0;
@ -137,7 +156,7 @@ static int PoolTestInit01 (void) {
static int PoolTestInit02 (void) {
int retval = 0;
Pool *p = PoolInit(10,5,PoolTestAlloc,PoolTestFree);
Pool *p = PoolInit(10,5,PoolTestAlloc,NULL,PoolTestFree);
if (p == NULL)
goto end;
@ -176,7 +195,7 @@ end:
static int PoolTestInit03 (void) {
int retval = 0;
Pool *p = PoolInit(10,5,PoolTestAlloc,PoolTestFree);
Pool *p = PoolInit(10,5,PoolTestAlloc,NULL,PoolTestFree);
if (p == NULL)
goto end;

@ -1,31 +1,34 @@
/* Copyright (c) 2008 by Victor Julien <victor@inliniac.net> */
#ifndef __POOL_H__
#define __POOL_H__
#ifndef __UTIL_POOL_H__
#define __UTIL_POOL_H__
/* hash bucket structure */
/* pool bucket structure */
typedef struct _PoolBucket {
void *data;
struct _PoolBucket *next;
} PoolBucket;
/* hash table structure */
/* pool structure */
typedef struct _Pool {
PoolBucket *alloc_list;
u_int32_t alloc_list_size;
PoolBucket *empty_list;
u_int32_t empty_list_size;
void *(*Alloc)(void);
void *(*Alloc)(void *);
void *AllocData;
void (*Free)(void *);
} Pool;
/* prototypes */
Pool* PoolInit(u_int32_t, u_int32_t, void *(*Alloc)(void), void (*Free)(void *));
Pool* PoolInit(u_int32_t, u_int32_t, void *(*Alloc)(void *), void *, void (*Free)(void *));
void PoolFree(Pool *);
void PoolPrint(Pool *);
void *PoolGet(Pool *);
void PoolRegisterTests(void);
#endif /* __POOL_H__ */
#endif /* __UTIL_POOL_H__ */

Loading…
Cancel
Save