First round of adding 'stream events'. Basic stream tracking events added.

remotes/origin/master-1.1.x
Victor Julien 15 years ago
parent 2849d2b1d3
commit 25f5589078

@ -125,6 +125,42 @@ enum {
/* RAW EVENTS */
IPRAW_INVALID_IPV, /**< invalid ip version in ip raw */
STREAM_3WHS_ACK_IN_WRONG_DIR,
STREAM_3WHS_ASYNC_WRONG_SEQ,
STREAM_3WHS_RIGHT_SEQ_WRONG_ACK_EVASION,
STREAM_3WHS_SYNACK_IN_WRONG_DIRECTION,
STREAM_3WHS_SYNACK_RESEND_WITH_DIFFERENT_ACK,
STREAM_3WHS_SYNACK_RESEND_WITH_DIFF_SEQ,
STREAM_3WHS_SYNACK_TOSERVER_ON_SYN_RECV,
STREAM_3WHS_SYNACK_WITH_WRONG_ACK,
STREAM_3WHS_SYN_RESEND_DIFF_SEQ_ON_SYN_RECV,
STREAM_3WHS_SYN_TOCLIENT_ON_SYN_RECV,
STREAM_3WHS_WRONG_SEQ_WRONG_ACK,
STREAM_4WHS_SYNACK_WITH_WRONG_ACK,
STREAM_4WHS_SYNACK_WITH_WRONG_SYN,
STREAM_4WHS_WRONG_SEQ,
STREAM_CLOSEWAIT_ACK_OUT_OF_WINDOW,
STREAM_CLOSEWAIT_FIN_OUT_OF_WINDOW,
STREAM_CLOSING_ACK_WRONG_SEQ,
STREAM_EST_PACKET_OUT_OF_WINDOW,
STREAM_EST_SEQ_BEFORE_LAST_ACK,
STREAM_EST_SYNACK_RESEND,
STREAM_EST_SYNACK_RESEND_WITH_DIFFERENT_ACK,
STREAM_EST_SYNACK_RESEND_WITH_DIFF_SEQ,
STREAM_EST_SYNACK_TOSERVER,
STREAM_EST_SYN_RESEND,
STREAM_EST_SYN_RESEND_DIFF_SEQ,
STREAM_EST_SYN_TOCLIENT,
STREAM_FIN1_ACK_WRONG_SEQ,
STREAM_FIN1_FIN_WRONG_SEQ,
STREAM_FIN2_ACK_WRONG_SEQ,
STREAM_FIN2_FIN_WRONG_SEQ,
STREAM_FIN_BUT_NO_SESSION,
STREAM_FIN_OUT_OF_WINDOW,
STREAM_LASTACK_ACK_WRONG_SEQ,
STREAM_RST_BUT_NO_SESSION,
STREAM_TIMEWAIT_ACK_WRONG_SEQ,
/* should always be last! */
DECODE_EVENT_MAX,
};

@ -225,11 +225,14 @@ typedef struct PacketAlerts_ {
PacketAlert alerts[PACKET_ALERT_MAX];
} PacketAlerts;
#define PACKET_DECODER_EVENT_MAX 16
/** number of decoder events we support per packet. Power of 2 minus 1
* for memory layout */
#define PACKET_DECODER_EVENT_MAX 15
/** data structure to store decoder, defrag and stream events */
typedef struct PacketDecoderEvents_ {
uint8_t cnt;
uint8_t events[PACKET_DECODER_EVENT_MAX];
uint8_t cnt; /**< number of events */
uint8_t events[PACKET_DECODER_EVENT_MAX]; /**< array of events */
} PacketDecoderEvents;
typedef struct PktVar_ {

@ -148,7 +148,10 @@ void StreamTcpDecrMemuse(uint32_t size) {
SCSpinUnlock(&stream_memuse_spinlock);
}
/** \retval 1 if in bounds
/**
* \brief Check if alloc'ing "size" would mean we're over memcap
*
* \retval 1 if in bounds
* \retval 0 if not in bounds
*/
int StreamTcpCheckMemcap(uint32_t size) {
@ -596,6 +599,10 @@ void StreamTcpSetOSPolicy(TcpStream *stream, Packet *p)
}
void StreamTcpSetEvent(Packet *p, uint8_t e) {
DECODER_SET_EVENT(p, e);
}
/**
* \brief Function to test the received ACK values against the stream window
* and previous ack value. ACK values should be higher than previous
@ -614,7 +621,7 @@ static inline uint8_t StreamTcpValidateAck(TcpStream *stream, Packet *p)
(SEQ_LEQ(TCP_GET_ACK(p) + p->payload_len, stream->next_win)))
{
ret = TRUE;
}
}
return ret;
}
@ -638,13 +645,13 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p,
* TH_CWR -> Establish a new connection reducing window
* TH_ECN -> Echo Congestion flag
*/
case TH_SYN | TH_CWR | TH_ECN:
case TH_SYN:
case TH_SYN | TH_ECN:
case TH_SYN | TH_CWR:
case TH_SYN | TH_PUSH:
case TH_SYN | TH_URG:
case TH_SYN:
case TH_SYN|TH_PUSH|TH_URG:
case TH_SYN | TH_CWR | TH_ECN:
case TH_SYN | TH_PUSH | TH_URG:
{
if (ssn == NULL) {
ssn = StreamTcpNewSession(p);
@ -854,6 +861,10 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p,
case TH_RST|TH_ACK|TH_PUSH:
case TH_RST|TH_ACK|TH_PUSH|TH_ECN:
case TH_RST|TH_ACK|TH_PUSH|TH_ECN|TH_CWR:
StreamTcpSetEvent(p, STREAM_RST_BUT_NO_SESSION);
BUG_ON(p->flow->protoctx != NULL);
SCLogDebug("RST packet received, no session setup");
break;
case TH_FIN:
case TH_FIN|TH_ACK:
case TH_FIN|TH_ACK|TH_ECN:
@ -861,8 +872,9 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p,
case TH_FIN|TH_ACK|TH_PUSH:
case TH_FIN|TH_ACK|TH_PUSH|TH_ECN:
case TH_FIN|TH_ACK|TH_PUSH|TH_ECN|TH_CWR:
StreamTcpSetEvent(p, STREAM_FIN_BUT_NO_SESSION);
BUG_ON(p->flow->protoctx != NULL);
SCLogDebug("FIN or RST packet received, no session setup");
SCLogDebug("FIN packet received, no session setup");
break;
default:
SCLogDebug("default case");
@ -896,9 +908,10 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p,
case TH_SYN|TH_CWR:
case TH_SYN|TH_CWR|TH_ECN:
SCLogDebug("ssn %p: SYN packet on state SYN_SENT... resent", ssn);
if (ssn->flags & STREAMTCP_FLAG_4WHS)
if (ssn->flags & STREAMTCP_FLAG_4WHS) {
SCLogDebug("ssn %p: SYN packet on state SYN_SENT... resent of "
"4WHS SYN", ssn);
}
if (PKT_IS_TOCLIENT(p)) {
/** a SYN only packet in the opposite direction could be:
@ -950,6 +963,8 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p,
ssn->client.last_ack);
}
/** \todo check if it's correct or set event */
break;
case TH_SYN|TH_ACK:
case TH_SYN|TH_ACK|TH_ECN:
@ -960,6 +975,8 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p,
/* Check if the SYN/ACK packet ack's the earlier
* received SYN packet. */
if (!(SEQ_EQ(TCP_GET_ACK(p), ssn->server.isn + 1))) {
StreamTcpSetEvent(p, STREAM_4WHS_SYNACK_WITH_WRONG_ACK);
SCLogDebug("ssn %p: 4WHS ACK mismatch, packet ACK %"PRIu32""
" != %" PRIu32 " from stream", ssn,
TCP_GET_ACK(p), ssn->server.isn + 1);
@ -969,6 +986,8 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p,
/* Check if the SYN/ACK packet SEQ's the *FIRST* received SYN
* packet. */
if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->client.isn))) {
StreamTcpSetEvent(p, STREAM_4WHS_SYNACK_WITH_WRONG_SYN);
SCLogDebug("ssn %p: 4WHS SEQ mismatch, packet SEQ %"PRIu32""
" != %" PRIu32 " from *first* SYN pkt", ssn,
TCP_GET_SEQ(p), ssn->client.isn);
@ -1041,6 +1060,7 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p,
}
if (PKT_IS_TOSERVER(p)) {
StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_IN_WRONG_DIRECTION);
SCLogDebug("ssn %p: SYN/ACK received in the wrong direction", ssn);
return -1;
}
@ -1048,6 +1068,7 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p,
/* Check if the SYN/ACK packet ack's the earlier
* received SYN packet. */
if (!(SEQ_EQ(TCP_GET_ACK(p), ssn->client.isn + 1))) {
StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_WITH_WRONG_ACK);
SCLogDebug("ssn %p: ACK mismatch, packet ACK %" PRIu32 " != "
"%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
ssn->client.isn + 1);
@ -1130,16 +1151,18 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p,
case TH_ACK|TH_PUSH|TH_ECN:
case TH_ACK|TH_PUSH|TH_ECN|TH_CWR:
/* Handle the asynchronous stream, when we receive a SYN packet
and now istead of receving a SYN/ACK we receive a ACK from the
same host, which sent the SYN, this suggests the ASNYC streams.*/
and now istead of receving a SYN/ACK we receive a ACK from the
same host, which sent the SYN, this suggests the ASNYC streams.*/
if (stream_config.async_oneside == FALSE)
break;
/* Check if the ACK packet seq no is equal to the expected seq. no.*/
/*XXX GS what if we missed the initial ACK here, then we can't setup
the session. I was thinking to check the SEQ_GEQ instead of SEQ_EQ
your thoughts ?? It will quite relax then in checking.*/
/* we are in AYNC (one side) mode now. */
/* one side async means we won't see a SYN/ACK, so we can
* only check the SYN. */
if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->client.next_seq))) {
StreamTcpSetEvent(p, STREAM_3WHS_ASYNC_WRONG_SEQ);
SCLogDebug("ssn %p: SEQ mismatch, packet SEQ %" PRIu32 " != "
"%" PRIu32 " from stream",ssn, TCP_GET_SEQ(p),
ssn->client.next_seq);
@ -1193,7 +1216,8 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p,
if (PKT_IS_TOSERVER(p)) {
if (SEQ_EQ(TCP_GET_SEQ(p), ssn->client.isn) &&
SEQ_EQ(TCP_GET_WINDOW(p), 0) &&
SEQ_EQ(TCP_GET_ACK(p), (ssn->client.isn + 1))) {
SEQ_EQ(TCP_GET_ACK(p), (ssn->client.isn + 1)))
{
StreamTcpPacketSetState(p, ssn, TCP_CLOSED);
SCLogDebug("ssn %p: Reset received and state changed to "
"TCP_CLOSED", ssn);
@ -1224,6 +1248,9 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p,
* \param tv Thread Variable containig input/output queue, cpu affinity
* \param p Packet which has to be handled in this TCP state.
* \param stt Strean Thread module registered to handle the stream handling
*
* \retval 0 ok
* \retval -1 error
*/
static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p,
@ -1238,11 +1265,56 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p,
case TH_SYN|TH_CWR:
case TH_SYN|TH_CWR|TH_ECN:
SCLogDebug("ssn %p: SYN packet on state SYN_RECV... resent", ssn);
if (PKT_IS_TOCLIENT(p)) {
SCLogDebug("ssn %p: SYN-pkt to client in SYN_RECV state", ssn);
StreamTcpSetEvent(p, STREAM_3WHS_SYN_TOCLIENT_ON_SYN_RECV);
return -1;
}
if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->client.isn))) {
SCLogDebug("ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
StreamTcpSetEvent(p, STREAM_3WHS_SYN_RESEND_DIFF_SEQ_ON_SYN_RECV);
return -1;
}
break;
case TH_SYN|TH_ACK:
case TH_SYN|TH_ACK|TH_ECN:
case TH_SYN|TH_ACK|TH_ECN|TH_CWR:
SCLogDebug("ssn %p: SYN/ACK packet on state SYN_RECV. resent", ssn);
if (PKT_IS_TOSERVER(p)) {
SCLogDebug("ssn %p: SYN/ACK-pkt to server in SYN_RECV state", ssn);
StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_TOSERVER_ON_SYN_RECV);
return -1;
}
/* Check if the SYN/ACK packets ACK matches the earlier
* received SYN/ACK packet. */
if (!(SEQ_EQ(TCP_GET_ACK(p), ssn->client.last_ack))) {
SCLogDebug("ssn %p: ACK mismatch, packet ACK %" PRIu32 " != "
"%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
ssn->client.isn + 1);
StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_RESEND_WITH_DIFFERENT_ACK);
return -1;
}
/* Check if the SYN/ACK packet SEQ the earlier
* received SYN packet. */
if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->server.isn))) {
SCLogDebug("ssn %p: SEQ mismatch, packet SEQ %" PRIu32 " != "
"%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
ssn->client.isn + 1);
StreamTcpSetEvent(p, STREAM_3WHS_SYNACK_RESEND_WITH_DIFF_SEQ);
return -1;
}
break;
case TH_ACK:
case TH_ACK|TH_URG:
@ -1257,8 +1329,9 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p,
* stream->last_ts. If the timestamp is valid then process the
* packet normally otherwise the drop the packet (RFC 1323)*/
if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
if (!ValidTimestamp(ssn, p))
if (!(ValidTimestamp(ssn, p))) {
return -1;
}
}
if (ssn->flags & STREAMTCP_FLAG_4WHS && PKT_IS_TOCLIENT(p)) {
@ -1281,6 +1354,8 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p,
&ssn->server, p, pq);
} else {
SCLogDebug("ssn %p: 4WHS wrong seq nr on packet", ssn);
StreamTcpSetEvent(p, STREAM_4WHS_WRONG_SEQ);
return -1;
}
@ -1312,6 +1387,8 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p,
} else {
SCLogDebug("ssn %p: ACK received in the wrong direction",
ssn);
StreamTcpSetEvent(p, STREAM_3WHS_ACK_IN_WRONG_DIR);
return -1;
}
}
@ -1327,7 +1404,7 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p,
/* we need to make sure that both sequence and the ack are of
sane values */
if ((StreamTcpValidateAck(&ssn->server, p) == TRUE))
ssn->server.last_ack = TCP_GET_ACK(p);
ssn->server.last_ack = TCP_GET_ACK(p);
ssn->client.next_seq += p->payload_len;
ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
@ -1387,9 +1464,13 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p,
ssn->flags |= STREAMTCP_FLAG_DETECTION_EVASION_ATTEMPT;
SCLogDebug("ssn %p: wrong ack nr on packet, possible evasion!!",
ssn);
StreamTcpSetEvent(p, STREAM_3WHS_RIGHT_SEQ_WRONG_ACK_EVASION);
return -1;
} else {
SCLogDebug("ssn %p: wrong seq nr on packet", ssn);
StreamTcpSetEvent(p, STREAM_3WHS_WRONG_SEQ_WRONG_ACK);
return -1;
}
@ -1417,7 +1498,7 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p,
systems will not closed the connection. As they consider the
packet as stray packet and not belonging to the current
session, for more information check
http://www.packetstan.com/2010/06/recently-ive-been-on-campaign-to-make.html */
http://www.packetstan.com/2010/06/recently-ive-been-on-campaign-to-make.html */
if (ssn->flags & STREAMTCP_FLAG_DETECTION_EVASION_ATTEMPT) {
if (PKT_IS_TOSERVER(p)) {
if ((ssn->server.os_policy == OS_POLICY_LINUX) ||
@ -1543,6 +1624,8 @@ static int HandleEstablishedPacketToServer(ThreadVars *tv, TcpSession *ssn, Pack
p->payload_len, TCP_GET_SEQ(p) + p->payload_len,
ssn->client.last_ack, ssn->client.next_win,
TCP_GET_SEQ(p) + p->payload_len - ssn->client.next_win);
StreamTcpSetEvent(p, STREAM_EST_SEQ_BEFORE_LAST_ACK);
return -1;
}
}
@ -1591,6 +1674,9 @@ static int HandleEstablishedPacketToServer(ThreadVars *tv, TcpSession *ssn, Pack
p->payload_len, TCP_GET_SEQ(p) + p->payload_len,
ssn->client.last_ack, ssn->client.next_win,
TCP_GET_SEQ(p) + p->payload_len - ssn->client.next_win);
StreamTcpSetEvent(p, STREAM_EST_PACKET_OUT_OF_WINDOW);
return -1;
}
return 0;
}
@ -1639,6 +1725,7 @@ static int HandleEstablishedPacketToClient(ThreadVars *tv, TcpSession *ssn, Pack
ssn->server.last_ack = TCP_GET_SEQ(p);
} else {
StreamTcpSetEvent(p, STREAM_EST_SEQ_BEFORE_LAST_ACK);
return -1;
}
}
@ -1689,6 +1776,8 @@ static int HandleEstablishedPacketToClient(ThreadVars *tv, TcpSession *ssn, Pack
p->payload_len, TCP_GET_SEQ(p) + p->payload_len,
ssn->server.last_ack, ssn->server.next_win,
TCP_GET_SEQ(p) + p->payload_len - ssn->server.next_win);
StreamTcpSetEvent(p, STREAM_EST_PACKET_OUT_OF_WINDOW);
return -1;
}
return 0;
}
@ -1716,12 +1805,63 @@ static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p,
case TH_SYN|TH_CWR:
case TH_SYN|TH_CWR|TH_ECN:
SCLogDebug("ssn %p: SYN packet on state ESTABLISED... resent", ssn);
if (PKT_IS_TOCLIENT(p)) {
SCLogDebug("ssn %p: SYN-pkt to client in EST state", ssn);
StreamTcpSetEvent(p, STREAM_EST_SYN_TOCLIENT);
return -1;
}
if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->client.isn))) {
SCLogDebug("ssn %p: SYN with different SEQ on SYN_RECV state", ssn);
StreamTcpSetEvent(p, STREAM_EST_SYN_RESEND_DIFF_SEQ);
return -1;
}
/* a resend of a SYN while we are established already -- fishy */
StreamTcpSetEvent(p, STREAM_EST_SYN_RESEND);
return -1;
break;
case TH_SYN|TH_ACK:
case TH_SYN|TH_ACK|TH_ECN:
case TH_SYN|TH_ACK|TH_ECN|TH_CWR:
SCLogDebug("ssn %p: SYN/ACK packet on state ESTABLISHED... resent",
ssn);
if (PKT_IS_TOSERVER(p)) {
SCLogDebug("ssn %p: SYN/ACK-pkt to server in ESTABLISHED state", ssn);
StreamTcpSetEvent(p, STREAM_EST_SYNACK_TOSERVER);
return -1;
}
/* Check if the SYN/ACK packets ACK matches the earlier
* received SYN/ACK packet. */
if (!(SEQ_EQ(TCP_GET_ACK(p), ssn->client.last_ack))) {
SCLogDebug("ssn %p: ACK mismatch, packet ACK %" PRIu32 " != "
"%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
ssn->client.isn + 1);
StreamTcpSetEvent(p, STREAM_EST_SYNACK_RESEND_WITH_DIFFERENT_ACK);
return -1;
}
/* Check if the SYN/ACK packet SEQ the earlier
* received SYN packet. */
if (!(SEQ_EQ(TCP_GET_SEQ(p), ssn->server.isn))) {
SCLogDebug("ssn %p: SEQ mismatch, packet SEQ %" PRIu32 " != "
"%" PRIu32 " from stream", ssn, TCP_GET_ACK(p),
ssn->client.isn + 1);
StreamTcpSetEvent(p, STREAM_EST_SYNACK_RESEND_WITH_DIFF_SEQ);
return -1;
}
/* a resend of a SYN while we are established already -- fishy */
StreamTcpSetEvent(p, STREAM_EST_SYNACK_RESEND);
return -1;
break;
case TH_ACK|TH_URG:
case TH_ACK:
@ -1764,6 +1904,7 @@ static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p,
ssn->server.next_win, ssn->server.window);
}
break;
case TH_FIN:
case TH_FIN|TH_ACK:
case TH_FIN|TH_ACK|TH_ECN:
@ -1786,6 +1927,7 @@ static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p,
if((StreamTcpHandleFin(tv, stt, ssn, p, pq)) == -1)
return -1;
break;
case TH_RST:
case TH_RST|TH_ACK:
case TH_RST|TH_ACK|TH_ECN:
@ -1868,16 +2010,18 @@ static int StreamTcpHandleFin(ThreadVars *tv, StreamTcpThread *stt,
if (PKT_IS_TOSERVER(p)) {
SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ %" PRIu32 ","
" ACK %" PRIu32 "", ssn, p->payload_len, TCP_GET_SEQ(p),
TCP_GET_ACK(p));
" ACK %" PRIu32 "", ssn, p->payload_len, TCP_GET_SEQ(p),
TCP_GET_ACK(p));
if (SEQ_LT(TCP_GET_SEQ(p), ssn->client.next_seq) ||
SEQ_GT(TCP_GET_SEQ(p), (ssn->client.last_ack + ssn->client.window)))
SEQ_GT(TCP_GET_SEQ(p), (ssn->client.last_ack + ssn->client.window)))
{
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != "
"%" PRIu32 " from stream", ssn, TCP_GET_SEQ(p),
ssn->client.next_seq);
return -1;
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != "
"%" PRIu32 " from stream", ssn, TCP_GET_SEQ(p),
ssn->client.next_seq);
StreamTcpSetEvent(p, STREAM_FIN_OUT_OF_WINDOW);
return -1;
}
StreamTcpPacketSetState(p, ssn, TCP_CLOSE_WAIT);
@ -1914,6 +2058,8 @@ static int StreamTcpHandleFin(ThreadVars *tv, StreamTcpThread *stt,
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 " != "
"%" PRIu32 " from stream", ssn, TCP_GET_SEQ(p),
ssn->server.next_seq);
StreamTcpSetEvent(p, STREAM_FIN_OUT_OF_WINDOW);
return -1;
}
@ -1941,6 +2087,7 @@ static int StreamTcpHandleFin(ThreadVars *tv, StreamTcpThread *stt,
SCLogDebug("ssn %p: =+ next SEQ %" PRIu32 ", last ACK %" PRIu32 "",
ssn, ssn->server.next_seq, ssn->client.last_ack);
}
return 0;
}
@ -1961,8 +2108,8 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p,
return -1;
switch (p->tcph->th_flags) {
case TH_ACK|TH_URG:
case TH_ACK:
case TH_ACK|TH_URG:
case TH_ACK|TH_ECN:
case TH_ACK|TH_ECN|TH_CWR:
@ -1976,6 +2123,8 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
" != %" PRIu32 " from stream", ssn,
TCP_GET_SEQ(p), ssn->client.next_seq);
StreamTcpSetEvent(p, STREAM_FIN1_ACK_WRONG_SEQ);
return -1;
}
SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to server: SEQ "
@ -2013,6 +2162,7 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
" != %" PRIu32 " from stream", ssn,
TCP_GET_SEQ(p), ssn->server.next_seq);
StreamTcpSetEvent(p, STREAM_FIN1_ACK_WRONG_SEQ);
return -1;
}
SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
@ -2046,6 +2196,7 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p,
ssn->client.last_ack);
}
break;
case TH_FIN:
case TH_FIN|TH_ACK:
case TH_FIN|TH_ACK|TH_ECN:
@ -2071,6 +2222,7 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
" != %" PRIu32 " from stream", ssn,
TCP_GET_SEQ(p), ssn->client.next_seq);
StreamTcpSetEvent(p, STREAM_FIN1_FIN_WRONG_SEQ);
return -1;
}
@ -2112,6 +2264,7 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
" != %" PRIu32 " from stream", ssn,
TCP_GET_SEQ(p), ssn->server.next_seq);
StreamTcpSetEvent(p, STREAM_FIN1_FIN_WRONG_SEQ);
return -1;
}
@ -2187,8 +2340,8 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p,
return -1;
switch (p->tcph->th_flags) {
case TH_ACK|TH_URG:
case TH_ACK:
case TH_ACK|TH_URG:
case TH_ACK|TH_ECN:
case TH_ACK|TH_ECN|TH_CWR:
@ -2206,6 +2359,7 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
" != %" PRIu32 " from stream", ssn,
TCP_GET_SEQ(p), ssn->client.next_seq);
StreamTcpSetEvent(p, STREAM_FIN2_ACK_WRONG_SEQ);
return -1;
}
StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
@ -2243,6 +2397,7 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
" != %" PRIu32 " from stream", ssn,
TCP_GET_SEQ(p), ssn->server.next_seq);
StreamTcpSetEvent(p, STREAM_FIN2_ACK_WRONG_SEQ);
return -1;
}
StreamTcpPacketSetState(p, ssn, TCP_TIME_WAIT);
@ -2273,6 +2428,7 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p,
ssn->client.last_ack);
}
break;
case TH_RST:
case TH_RST|TH_ACK:
case TH_RST|TH_ACK|TH_ECN:
@ -2292,8 +2448,8 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p,
else
return -1;
break;
case TH_FIN:
case TH_FIN:
if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
if (!ValidTimestamp(ssn, p))
return -1;
@ -2311,6 +2467,7 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ "
"%" PRIu32 " != %" PRIu32 " from stream", ssn,
TCP_GET_SEQ(p), ssn->client.next_seq);
StreamTcpSetEvent(p, STREAM_FIN2_FIN_WRONG_SEQ);
return -1;
}
@ -2345,6 +2502,7 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ "
"%" PRIu32 " != %" PRIu32 " from stream", ssn,
TCP_GET_SEQ(p), ssn->server.next_seq);
StreamTcpSetEvent(p, STREAM_FIN2_FIN_WRONG_SEQ);
return -1;
}
@ -2411,6 +2569,7 @@ static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
" != %" PRIu32 " from stream", ssn,
TCP_GET_SEQ(p), ssn->client.next_seq);
StreamTcpSetEvent(p, STREAM_CLOSING_ACK_WRONG_SEQ);
return -1;
}
@ -2442,6 +2601,7 @@ static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
" != %" PRIu32 " from stream", ssn,
TCP_GET_SEQ(p), ssn->server.next_seq);
StreamTcpSetEvent(p, STREAM_CLOSING_ACK_WRONG_SEQ);
return -1;
}
@ -2486,8 +2646,11 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
StreamTcpThread *stt, TcpSession *ssn, PacketQueue *pq)
{
SCEnter();
if (ssn == NULL)
if (ssn == NULL) {
SCReturnInt(-1);
}
if (PKT_IS_TOCLIENT(p)) {
SCLogDebug("ssn %p: pkt (%" PRIu32 ") is to client: SEQ "
"%" PRIu32 ", ACK %" PRIu32 "", ssn, p->payload_len,
@ -2521,6 +2684,7 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
" != %" PRIu32 " from stream", ssn,
TCP_GET_SEQ(p), ssn->server.next_seq);
StreamTcpSetEvent(p, STREAM_CLOSEWAIT_FIN_OUT_OF_WINDOW);
SCReturnInt(-1);
}
@ -2554,6 +2718,7 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
" != %" PRIu32 " from stream", ssn,
TCP_GET_SEQ(p), ssn->client.next_seq);
StreamTcpSetEvent(p, STREAM_CLOSEWAIT_FIN_OUT_OF_WINDOW);
SCReturnInt(-1);
}
@ -2577,6 +2742,7 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
ssn->server.last_ack);
}
break;
case TH_ACK:
case TH_ACK|TH_PUSH:
case TH_ACK|TH_ECN:
@ -2598,6 +2764,7 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
" != %" PRIu32 " from stream", ssn,
TCP_GET_SEQ(p), ssn->server.next_seq);
StreamTcpSetEvent(p, STREAM_CLOSEWAIT_ACK_OUT_OF_WINDOW);
SCReturnInt(-1);
}
ssn->client.window = TCP_GET_WINDOW(p) << ssn->client.wscale;
@ -2632,6 +2799,7 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p,
" != %" PRIu32 " from stream", ssn,
TCP_GET_SEQ(p), ssn->client.next_seq);
SCReturnInt(-1);
StreamTcpSetEvent(p, STREAM_CLOSEWAIT_ACK_OUT_OF_WINDOW);
}
ssn->server.window = TCP_GET_WINDOW(p) << ssn->server.wscale;
@ -2696,6 +2864,7 @@ static int StreamTcpPakcetStateLastAck(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
" != %" PRIu32 " from stream", ssn,
TCP_GET_SEQ(p), ssn->client.next_seq);
StreamTcpSetEvent(p, STREAM_LASTACK_ACK_WRONG_SEQ);
return -1;
}
@ -2764,6 +2933,7 @@ static int StreamTcpPacketStateTimeWait(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
" != %" PRIu32 " from stream", ssn,
TCP_GET_SEQ(p), ssn->client.next_seq);
StreamTcpSetEvent(p, STREAM_TIMEWAIT_ACK_WRONG_SEQ);
return -1;
}
@ -2797,6 +2967,7 @@ static int StreamTcpPacketStateTimeWait(ThreadVars *tv, Packet *p,
SCLogDebug("ssn %p: -> SEQ mismatch, packet SEQ %" PRIu32 ""
" != %" PRIu32 " from stream", ssn,
TCP_GET_SEQ(p), ssn->server.next_seq);
StreamTcpSetEvent(p, STREAM_TIMEWAIT_ACK_WRONG_SEQ);
return -1;
}

Loading…
Cancel
Save