Inspect a pseudo packet upon receiving a RST so that we are sure both sides of the TCP session are inspected.

remotes/origin/master-1.1.x
Victor Julien 16 years ago
parent 00f21f34e8
commit 61a9936d55

@ -743,6 +743,7 @@ void AddressDebugPrint(Address *);
#define PKT_STREAM_ADD 0x10 /**< Packet payload was added to reassembled stream */ #define PKT_STREAM_ADD 0x10 /**< Packet payload was added to reassembled stream */
#define PKT_STREAM_EOF 0x20 /**< Stream is in eof state */ #define PKT_STREAM_EOF 0x20 /**< Stream is in eof state */
#define PKT_HAS_FLOW 0x40 #define PKT_HAS_FLOW 0x40
#define PKT_PSEUDO_STREAM_END 0x80 /**< Pseudo packet to end the stream */
#endif /* __DECODE_H__ */ #endif /* __DECODE_H__ */

@ -1454,6 +1454,9 @@ static int StreamTcpReassembleRawCheckLimit(TcpSession *ssn, TcpStream *stream,
if (ssn->state >= TCP_TIME_WAIT) if (ssn->state >= TCP_TIME_WAIT)
SCReturnInt(1); SCReturnInt(1);
if (p->flags & PKT_PSEUDO_STREAM_END)
SCReturnInt(1);
/* check if we have enough data to send to L7 */ /* check if we have enough data to send to L7 */
if (p->flowflags & FLOW_PKT_TOCLIENT) { if (p->flowflags & FLOW_PKT_TOCLIENT) {
SCLogDebug("StreamMsgQueueGetMinInitChunkLen(STREAM_TOSERVER) %"PRIu32, SCLogDebug("StreamMsgQueueGetMinInitChunkLen(STREAM_TOSERVER) %"PRIu32,
@ -2368,10 +2371,17 @@ int StreamTcpReassembleProcessAppLayer(TcpReassemblyThreadCtx *ra_ctx)
do { do {
smsg = StreamMsgGetFromQueue(ra_ctx->stream_q); smsg = StreamMsgGetFromQueue(ra_ctx->stream_q);
if (smsg != NULL) { if (smsg != NULL) {
SCLogDebug("smsg %p, next %p, prev %p, flow %p, q->len %u", smsg, smsg->next, smsg->prev, smsg->flow, ra_ctx->stream_q->len); SCLogDebug("smsg %p, next %p, prev %p, flow %p, q->len %u, "
"smsg->data.datalen %u, direction %s%s",
smsg, smsg->next, smsg->prev, smsg->flow,
ra_ctx->stream_q->len, smsg->data.data_len,
smsg->flags & STREAM_TOSERVER : "toserver":"",
smsg->flags & STREAM_TOCLIENT : "toclient":"");
BUG_ON(smsg->flow == NULL); BUG_ON(smsg->flow == NULL);
//PrintRawDataFp(stderr, smsg->data.data, smsg->data.data_len);
/* Handle the stream msg. No need to use locking, flow is /* Handle the stream msg. No need to use locking, flow is
* already locked at this point. Don't break out of the * already locked at this point. Don't break out of the
* loop if we encounter an error. */ * loop if we encounter an error. */
@ -2402,9 +2412,6 @@ int StreamTcpReassembleHandleSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_
opposing_stream = &ssn->client; opposing_stream = &ssn->client;
} }
/* Create the pseudo packet from the reassembled stream to detect the attack */
StreamTcpReassemblePseudoPacketCreate(opposing_stream, p, pq);
/* handle ack received */ /* handle ack received */
if (StreamTcpReassembleHandleSegmentUpdateACK(ra_ctx, ssn, opposing_stream, p) != 0) if (StreamTcpReassembleHandleSegmentUpdateACK(ra_ctx, ssn, opposing_stream, p) != 0)
{ {
@ -2428,95 +2435,6 @@ int StreamTcpReassembleHandleSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_
SCReturnInt(0); SCReturnInt(0);
} }
/**
* \brief Function to fetch a packet from the packet allocation queue for
* creation of the pseudo packet from the reassembled stream.
*
* @param parent Pointer to the parent of the pseudo packet
* @param pkt pointer to the raw packet of the parent
* @param len length of the packet
* @return upon success returns the pointer to the new pseudo packet
* otherwise NULL
*/
Packet *StreamTcpReassemblePseudoSetup(Packet *parent, uint8_t *pkt, uint32_t len)
{
Packet *p = PacketGetFromQueueOrAlloc();
if (p == NULL || len == 0) {
return NULL;
}
/* set the root ptr to the lowest layer */
if (parent->root != NULL)
p->root = parent->root;
else
p->root = parent;
/* copy packet and set lenght, proto */
p->tunnel_proto = parent->proto;
p->pktlen = len;
memcpy(&p->pkt, pkt, (len - parent->payload_len));
p->recursion_level = parent->recursion_level + 1;
p->ts.tv_sec = parent->ts.tv_sec;
p->ts.tv_usec = parent->ts.tv_usec;
/* set tunnel flags */
/* tell new packet it's part of a tunnel */
SET_TUNNEL_PKT(p);
/* tell parent packet it's part of a tunnel */
SET_TUNNEL_PKT(parent);
/* increment tunnel packet refcnt in the root packet */
TUNNEL_INCR_PKT_TPR(p);
return p;
}
/**
* \brief Function to setup the IP and TCP header of the pseudo packet from
* the newly copied raw packet contents of the parent.
*
* @param np pointer to the pseudo packet
* @param p pointer to the original packet
*/
void StreamTcpReassemblePseudoPacketSetupHeader(Packet *np, Packet *p)
{
/* Setup the IP header */
if (PKT_IS_IPV4(p)) {
np->ip4h = (IPV4Hdr *)(np->pkt + (np->pktlen - IPV4_GET_IPLEN(p)));
PSUEDO_PKT_SET_IPV4HDR(np->ip4h, p->ip4h);
/* Similarly setup the TCP header with ports in opposite direction */
np->tcph = (TCPHdr *)(np->ip4h + IPV4_GET_HLEN(p));
PSUEDO_PKT_SET_TCPHDR(np->tcph, p->tcph);
/* Setup the adress and port details */
SET_IPV4_SRC_ADDR(np, &np->src);
SET_IPV4_DST_ADDR(np, &np->dst);
SET_TCP_SRC_PORT(np, &np->sp);
SET_TCP_DST_PORT(np, &np->dp);
} else if (PKT_IS_IPV6(p)) {
np->ip6h = (IPV6Hdr *)(np->pkt + (np->pktlen - IPV6_GET_PLEN(p) - IPV6_HEADER_LEN));
PSUEDO_PKT_SET_IPV6HDR(np->ip6h, p->ip6h);
/* Similarly setup the TCP header with ports in opposite direction */
np->tcph = (TCPHdr *)(np->ip6h + IPV6_HEADER_LEN);
PSUEDO_PKT_SET_TCPHDR(np->tcph, p->tcph);
/* Setup the adress and port details */
SET_IPV6_SRC_ADDR(np, &np->src);
SET_IPV6_DST_ADDR(np, &np->dst);
SET_TCP_SRC_PORT(np, &np->sp);
SET_TCP_DST_PORT(np, &np->dp);
}
/* Setup the payload pointer to the starting of payload location as in the
original packet, so that we don't overwrite the protocols headers */
np->payload = np->pkt + (np->pktlen - p->payload_len);
np->payload_len = 0;
}
/** /**
* \brief Function to copy the reassembled stream segments in to the pseudo * \brief Function to copy the reassembled stream segments in to the pseudo
* packet payload. * packet payload.
@ -2535,14 +2453,14 @@ void StreamTcpReassemblePseudoPacketCreate(TcpStream *stream, Packet *p,
SCReturn; SCReturn;
} }
Packet *np = StreamTcpReassemblePseudoSetup(p, p->pkt, p->pktlen); Packet *np = StreamTcpPseudoSetup(p, p->pkt, p->pktlen);
if (np == NULL) { if (np == NULL) {
SCLogDebug("The packet received from packet allocation is NULL"); SCLogDebug("The packet received from packet allocation is NULL");
SCReturn; SCReturn;
} }
/* Setup the IP and TCP headers */ /* Setup the IP and TCP headers */
StreamTcpReassemblePseudoPacketSetupHeader(np,p); StreamTcpPseudoPacketSetupHeader(np,p);
/* Start the reassembling of received reassembled segments in to the /* Start the reassembling of received reassembled segments in to the
pseudo packet to scan and detect the unwanted attacks. Resistance is pseudo packet to scan and detect the unwanted attacks. Resistance is
@ -2599,13 +2517,13 @@ void StreamTcpReassemblePseudoPacketCreate(TcpStream *stream, Packet *p,
np->ip6h->s_ip6_plen = (TCP_GET_HLEN(np)) + np->payload_len; np->ip6h->s_ip6_plen = (TCP_GET_HLEN(np)) + np->payload_len;
} }
PacketEnqueue(pq, np); PacketEnqueue(pq, np);
Packet *gap = StreamTcpReassemblePseudoSetup(p, p->pkt, p->pktlen); Packet *gap = StreamTcpPseudoSetup(p, p->pkt, p->pktlen);
if (gap == NULL) { if (gap == NULL) {
SCLogDebug("The packet received from packet allocation is NULL"); SCLogDebug("The packet received from packet allocation is NULL");
SCReturn; SCReturn;
} }
np = gap; np = gap;
StreamTcpReassemblePseudoPacketSetupHeader(np,p); StreamTcpPseudoPacketSetupHeader(np,p);
} }
} }
@ -2675,13 +2593,13 @@ void StreamTcpReassemblePseudoPacketCreate(TcpStream *stream, Packet *p,
np->ip6h->s_ip6_plen = (TCP_GET_HLEN(np)) + np->payload_len; np->ip6h->s_ip6_plen = (TCP_GET_HLEN(np)) + np->payload_len;
} }
PacketEnqueue(pq, np); PacketEnqueue(pq, np);
Packet *newp = StreamTcpReassemblePseudoSetup(p, p->pkt, p->pktlen); Packet *newp = StreamTcpPseudoSetup(p, p->pkt, p->pktlen);
if (newp == NULL) { if (newp == NULL) {
SCLogDebug("The packet received from Allocation queue is NULL"); SCLogDebug("The packet received from Allocation queue is NULL");
SCReturn; SCReturn;
} }
np = newp; np = newp;
StreamTcpReassemblePseudoPacketSetupHeader(np,p); StreamTcpPseudoPacketSetupHeader(np,p);
} }
/* if the payload len is bigger than what we copied, we handle the /* if the payload len is bigger than what we copied, we handle the

@ -74,6 +74,11 @@
typedef struct StreamTcpThread_ { typedef struct StreamTcpThread_ {
uint64_t pkts; uint64_t pkts;
/** queue for pseudo packet(s) that were created in the stream
* process and need further handling. Currently only used when
* receiving (valid) RST packets */
PacketQueue pseudo_queue;
uint16_t counter_tcp_sessions; uint16_t counter_tcp_sessions;
/** sessions not picked up because memcap was reached */ /** sessions not picked up because memcap was reached */
uint16_t counter_tcp_ssn_memcap; uint16_t counter_tcp_ssn_memcap;
@ -94,6 +99,7 @@ extern void StreamTcpSegmentReturntoPool(TcpSegment *);
int StreamTcpGetFlowState(void *); int StreamTcpGetFlowState(void *);
static int ValidTimestamp(TcpSession * , Packet *); static int ValidTimestamp(TcpSession * , Packet *);
void StreamTcpSetOSPolicy(TcpStream*, Packet*); void StreamTcpSetOSPolicy(TcpStream*, Packet*);
void StreamTcpPseudoPacketCreateStreamEndPacket(Packet *, TcpSession *, PacketQueue *);
static Pool *ssn_pool = NULL; static Pool *ssn_pool = NULL;
static SCMutex ssn_pool_mutex; static SCMutex ssn_pool_mutex;
@ -1726,6 +1732,9 @@ static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p,
case TH_RST|TH_ACK|TH_ECN|TH_CWR: case TH_RST|TH_ACK|TH_ECN|TH_CWR:
if(ValidReset(ssn, p)) { if(ValidReset(ssn, p)) {
/* force both streams to reassemble, if necessary */
StreamTcpPseudoPacketCreateStreamEndPacket(p, ssn, pq);
if(PKT_IS_TOSERVER(p)) { if(PKT_IS_TOSERVER(p)) {
StreamTcpPacketSetState(p, ssn, TCP_CLOSED); StreamTcpPacketSetState(p, ssn, TCP_CLOSED);
SCLogDebug("ssn %p: Reset received and state changed to " SCLogDebug("ssn %p: Reset received and state changed to "
@ -2038,7 +2047,10 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p,
case TH_RST|TH_ACK|TH_ECN: case TH_RST|TH_ACK|TH_ECN:
case TH_RST|TH_ACK|TH_ECN|TH_CWR: case TH_RST|TH_ACK|TH_ECN|TH_CWR:
if(ValidReset(ssn, p)) { if (ValidReset(ssn, p)) {
/* force both streams to reassemble, if necessary */
StreamTcpPseudoPacketCreateStreamEndPacket(p, ssn, pq);
StreamTcpPacketSetState(p, ssn, TCP_CLOSED); StreamTcpPacketSetState(p, ssn, TCP_CLOSED);
SCLogDebug("ssn %p: Reset received state changed to TCP_CLOSED", SCLogDebug("ssn %p: Reset received state changed to TCP_CLOSED",
ssn); ssn);
@ -2152,7 +2164,10 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p,
case TH_RST|TH_ACK|TH_ECN: case TH_RST|TH_ACK|TH_ECN:
case TH_RST|TH_ACK|TH_ECN|TH_CWR: case TH_RST|TH_ACK|TH_ECN|TH_CWR:
if(ValidReset(ssn, p)) { if (ValidReset(ssn, p)) {
/* force both streams to reassemble, if necessary */
StreamTcpPseudoPacketCreateStreamEndPacket(p, ssn, pq);
StreamTcpPacketSetState(p, ssn, TCP_CLOSED); StreamTcpPacketSetState(p, ssn, TCP_CLOSED);
SCLogDebug("ssn %p: Reset received state changed to TCP_CLOSED", SCLogDebug("ssn %p: Reset received state changed to TCP_CLOSED",
ssn); ssn);
@ -2657,8 +2672,9 @@ static int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt,
} }
if (ssn == NULL || ssn->state == TCP_NONE) { if (ssn == NULL || ssn->state == TCP_NONE) {
if (StreamTcpPacketStateNone(tv, p, stt, ssn, pq) == -1) if (StreamTcpPacketStateNone(tv, p, stt, ssn, &stt->pseudo_queue) == -1) {
SCReturnInt(-1); goto error;
}
if (ssn != NULL) if (ssn != NULL)
SCLogDebug("ssn->alproto %"PRIu16"", p->flow->alproto); SCLogDebug("ssn->alproto %"PRIu16"", p->flow->alproto);
@ -2670,40 +2686,49 @@ static int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt,
switch (ssn->state) { switch (ssn->state) {
case TCP_SYN_SENT: case TCP_SYN_SENT:
if(StreamTcpPacketStateSynSent(tv, p, stt, ssn, pq)) if(StreamTcpPacketStateSynSent(tv, p, stt, ssn, &stt->pseudo_queue)) {
SCReturnInt(-1); goto error;
}
break; break;
case TCP_SYN_RECV: case TCP_SYN_RECV:
if(StreamTcpPacketStateSynRecv(tv, p, stt, ssn, pq)) if(StreamTcpPacketStateSynRecv(tv, p, stt, ssn, &stt->pseudo_queue)) {
SCReturnInt(-1); goto error;
}
break; break;
case TCP_ESTABLISHED: case TCP_ESTABLISHED:
if(StreamTcpPacketStateEstablished(tv, p, stt, ssn, pq)) if(StreamTcpPacketStateEstablished(tv, p, stt, ssn, &stt->pseudo_queue)) {
SCReturnInt(-1); goto error;
}
break; break;
case TCP_FIN_WAIT1: case TCP_FIN_WAIT1:
if(StreamTcpPacketStateFinWait1(tv, p, stt, ssn, pq)) if(StreamTcpPacketStateFinWait1(tv, p, stt, ssn, &stt->pseudo_queue)) {
SCReturnInt(-1); goto error;
}
break; break;
case TCP_FIN_WAIT2: case TCP_FIN_WAIT2:
if(StreamTcpPacketStateFinWait2(tv, p, stt, ssn, pq)) if(StreamTcpPacketStateFinWait2(tv, p, stt, ssn, &stt->pseudo_queue)) {
SCReturnInt(-1); goto error;
}
break; break;
case TCP_CLOSING: case TCP_CLOSING:
if(StreamTcpPacketStateClosing(tv, p, stt, ssn, pq)) if(StreamTcpPacketStateClosing(tv, p, stt, ssn, &stt->pseudo_queue)) {
SCReturnInt(-1); goto error;
}
break; break;
case TCP_CLOSE_WAIT: case TCP_CLOSE_WAIT:
if(StreamTcpPacketStateCloseWait(tv, p, stt, ssn, pq)) if(StreamTcpPacketStateCloseWait(tv, p, stt, ssn, &stt->pseudo_queue)) {
SCReturnInt(-1); goto error;
}
break; break;
case TCP_LAST_ACK: case TCP_LAST_ACK:
if(StreamTcpPakcetStateLastAck(tv, p, stt, ssn, pq)) if(StreamTcpPakcetStateLastAck(tv, p, stt, ssn, &stt->pseudo_queue)) {
SCReturnInt(-1); goto error;
}
break; break;
case TCP_TIME_WAIT: case TCP_TIME_WAIT:
if(StreamTcpPacketStateTimeWait(tv, p, stt, ssn, pq)) if(StreamTcpPacketStateTimeWait(tv, p, stt, ssn, &stt->pseudo_queue)) {
SCReturnInt(-1); goto error;
}
break; break;
case TCP_CLOSED: case TCP_CLOSED:
/* TCP session memory is not returned to pool until timeout. /* TCP session memory is not returned to pool until timeout.
@ -2721,7 +2746,7 @@ static int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt,
{ {
SCLogDebug("reusing closed TCP session"); SCLogDebug("reusing closed TCP session");
if (StreamTcpPacketStateNone(tv,p,stt,ssn)) { if (StreamTcpPacketStateNone(tv,p,stt,ssn, &stt->pseudo_queue)) {
SCReturnInt(-1); SCReturnInt(-1);
} }
} else { } else {
@ -2738,11 +2763,48 @@ static int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt,
} }
} }
/* deal with a pseudo packet that is created upon receiving a RST
* segment. To be sure we process both sides of the connection, we
* inject a fake packet into the system, forcing reassembly of the
* opposing direction.
* There should be only one, but to be sure we do a while loop. */
while (stt->pseudo_queue.len > 0) {
SCLogDebug("processing pseudo packet / stream end");
Packet *np = PacketDequeue(&stt->pseudo_queue);
if (np != NULL) {
/* process the opposing direction of the original packet */
if (PKT_IS_TOSERVER(np)) {
SCLogDebug("pseudo packet is to server");
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->client, np, NULL);
} else {
SCLogDebug("pseudo packet is to client");
StreamTcpReassembleHandleSegment(tv, stt->ra_ctx, ssn,
&ssn->server, np, NULL);
}
/* enqueue this packet so we inspect it in detect etc */
PacketEnqueue(pq, np);
}
SCLogDebug("processing pseudo packet / stream end done");
}
/* Process stream smsgs we may have in queue */ /* Process stream smsgs we may have in queue */
if (StreamTcpReassembleProcessAppLayer(stt->ra_ctx) < 0) if (StreamTcpReassembleProcessAppLayer(stt->ra_ctx) < 0) {
SCReturnInt(-1); goto error;
}
SCReturnInt(0); SCReturnInt(0);
error:
/* make sure we don't leave packets in our pseudo queue */
while (stt->pseudo_queue.len > 0) {
Packet *np = PacketDequeue(&stt->pseudo_queue);
if (np != NULL) {
PacketEnqueue(pq, np);
}
}
SCReturnInt(-1);
} }
/** /**
@ -3210,6 +3272,156 @@ void StreamTcpSetSessionNoReassemblyFlag (TcpSession *ssn, char direction)
(ssn->client.flags |= STREAMTCP_STREAM_FLAG_NOREASSEMBLY); (ssn->client.flags |= STREAMTCP_STREAM_FLAG_NOREASSEMBLY);
} }
/**
* \brief Function to fetch a packet from the packet allocation queue for
* creation of the pseudo packet from the reassembled stream.
*
* @param parent Pointer to the parent of the pseudo packet
* @param pkt pointer to the raw packet of the parent
* @param len length of the packet
* @return upon success returns the pointer to the new pseudo packet
* otherwise NULL
*/
Packet *StreamTcpPseudoSetup(Packet *parent, uint8_t *pkt, uint32_t len)
{
Packet *p = PacketGetFromQueueOrAlloc();
if (p == NULL || len == 0) {
return NULL;
}
/* set the root ptr to the lowest layer */
if (parent->root != NULL)
p->root = parent->root;
else
p->root = parent;
/* copy packet and set lenght, proto */
p->tunnel_proto = parent->proto;
p->pktlen = len;
memcpy(&p->pkt, pkt, (len - parent->payload_len));
p->recursion_level = parent->recursion_level + 1;
p->ts.tv_sec = parent->ts.tv_sec;
p->ts.tv_usec = parent->ts.tv_usec;
p->flow = parent->flow;
/* set tunnel flags */
/* tell new packet it's part of a tunnel */
SET_TUNNEL_PKT(p);
/* tell parent packet it's part of a tunnel */
SET_TUNNEL_PKT(parent);
/* increment tunnel packet refcnt in the root packet */
TUNNEL_INCR_PKT_TPR(p);
return p;
}
/**
* \brief Function to setup the IP and TCP header of the pseudo packet from
* the newly copied raw packet contents of the parent.
*
* @param np pointer to the pseudo packet
* @param p pointer to the original packet
*/
void StreamTcpPseudoPacketSetupHeader(Packet *np, Packet *p)
{
/* Setup the IP header */
if (PKT_IS_IPV4(p)) {
np->ip4h = (IPV4Hdr *)(np->pkt + (np->pktlen - IPV4_GET_IPLEN(p)));
PSUEDO_PKT_SET_IPV4HDR(np->ip4h, p->ip4h);
/* Similarly setup the TCP header with ports in opposite direction */
np->tcph = (TCPHdr *)(np->ip4h + IPV4_GET_HLEN(p));
PSUEDO_PKT_SET_TCPHDR(np->tcph, p->tcph);
/* Setup the adress and port details */
SET_IPV4_SRC_ADDR(np, &np->src);
SET_IPV4_DST_ADDR(np, &np->dst);
SET_TCP_SRC_PORT(np, &np->sp);
SET_TCP_DST_PORT(np, &np->dp);
} else if (PKT_IS_IPV6(p)) {
np->ip6h = (IPV6Hdr *)(np->pkt + (np->pktlen - IPV6_GET_PLEN(p) - IPV6_HEADER_LEN));
PSUEDO_PKT_SET_IPV6HDR(np->ip6h, p->ip6h);
/* Similarly setup the TCP header with ports in opposite direction */
np->tcph = (TCPHdr *)(np->ip6h + IPV6_HEADER_LEN);
PSUEDO_PKT_SET_TCPHDR(np->tcph, p->tcph);
/* Setup the adress and port details */
SET_IPV6_SRC_ADDR(np, &np->src);
SET_IPV6_DST_ADDR(np, &np->dst);
SET_TCP_SRC_PORT(np, &np->sp);
SET_TCP_DST_PORT(np, &np->dp);
}
/* Setup the payload pointer to the starting of payload location as in the
original packet, so that we don't overwrite the protocols headers */
np->payload = NULL; //= np->pkt + (np->pktlen - p->payload_len);
np->payload_len = 0;
}
/** \brief Create a pseudo packet injected into the engine to signal the
* opposing direction of this stream to wrap up stream reassembly.
*
* \param p real packet
* \param pq packet queue to store the new pseudo packet in
*/
void StreamTcpPseudoPacketCreateStreamEndPacket(Packet *p, TcpSession *ssn, PacketQueue *pq)
{
SCEnter();
/* no need for a pseudo packet if there is nothing left to reassemble */
if (PKT_IS_TOSERVER(p)) {
if (ssn->server.seg_list == NULL) {
SCReturn;
}
} else if (PKT_IS_TOCLIENT(p)) {
if (ssn->client.seg_list == NULL) {
SCReturn;
}
}
Packet *np = StreamTcpPseudoSetup(p, p->pkt, p->pktlen);
if (np == NULL) {
SCLogDebug("The packet received from packet allocation is NULL");
SCReturn;
}
/* Setup the IP and TCP headers */
StreamTcpPseudoPacketSetupHeader(np,p);
np->flags |= PKT_STREAM_EOF;
np->flags |= PKT_HAS_FLOW;
np->flags |= PKT_PSEUDO_STREAM_END;
np->flowflags = p->flowflags;
if (PKT_IS_TOSERVER(p)) {
SCLogDebug("original is to_server, so pseudo is to_client");
np->flowflags &= ~FLOW_PKT_TOSERVER;
np->flowflags |= FLOW_PKT_TOCLIENT;
#ifdef DEBUG
BUG_ON(!(PKT_IS_TOCLIENT(np)));
BUG_ON((PKT_IS_TOSERVER(np)));
#endif
} else if (PKT_IS_TOCLIENT(p)) {
SCLogDebug("original is to_client, so pseudo is to_server");
np->flowflags &= ~FLOW_PKT_TOCLIENT;
np->flowflags |= FLOW_PKT_TOSERVER;
#ifdef DEBUG
BUG_ON(!(PKT_IS_TOSERVER(np)));
BUG_ON((PKT_IS_TOCLIENT(np)));
#endif
}
PacketEnqueue(pq, np);
SCReturn;
}
#ifdef UNITTESTS #ifdef UNITTESTS
/** /**

@ -63,6 +63,8 @@ void StreamTcpIncrMemuse(uint32_t);
void StreamTcpDecrMemuse(uint32_t); void StreamTcpDecrMemuse(uint32_t);
int StreamTcpCheckMemcap(uint32_t); int StreamTcpCheckMemcap(uint32_t);
void StreamTcpPseudoPacketSetupHeader(Packet *, Packet *);
Packet *StreamTcpPseudoSetup(Packet *, uint8_t *, uint32_t);
/** ------- Inline functions: ------ */ /** ------- Inline functions: ------ */

@ -154,7 +154,7 @@ void StreamMsgPutInQueue(StreamMsgQueue *q, StreamMsg *s)
void StreamMsgQueuesInit(void) { void StreamMsgQueuesInit(void) {
SCMutexInit(&stream_pool_memuse_mutex, NULL); SCMutexInit(&stream_pool_memuse_mutex, NULL);
stream_msg_pool = PoolInit(5000,250,StreamMsgAlloc,NULL,StreamMsgFree); stream_msg_pool = PoolInit(0,250,StreamMsgAlloc,NULL,StreamMsgFree);
if (stream_msg_pool == NULL) if (stream_msg_pool == NULL)
exit(EXIT_FAILURE); /* XXX */ exit(EXIT_FAILURE); /* XXX */
} }

Loading…
Cancel
Save