fixed unit tests and add the comments

remotes/origin/master-1.0.x
Gurvinder Singh 16 years ago committed by Victor Julien
parent e88249ee24
commit c06b2849fb

@ -18,8 +18,10 @@ typedef struct TcpStream_ {
uint32_t window; /**< current window setting */
uint8_t wscale; /**< wscale setting in this direction */
uint32_t last_ts; /**< Time stamp of last seen packet*/
uint32_t last_pkt_ts; /**< Time of last seen packet for this stream (needed for PAWS update)*/
uint32_t last_ts; /**< Time stamp (TSVAL) of the last seen packet for this stream*/
uint32_t last_pkt_ts; /**< Time of last seen packet for this stream (needed for PAWS update)
This will be used to validate the last_ts, when connection has been idle for
longer time.(RFC 1323)*/
/* reassembly */
uint32_t ra_base_seq; /**< reassembled seq. We've reassembled up to this point. */

@ -294,6 +294,7 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p, StreamTcpThread *
ssn->client.ra_base_seq = ssn->client.isn;
ssn->client.next_seq = ssn->client.isn + 1;
/*Set the stream timestamp value, if packet has timestamp option enabled.*/
if (p->tcpvars.ts != NULL) {
ssn->client.last_ts = TCP_GET_TSVAL(p);
#ifdef DEBUG
@ -362,14 +363,14 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p, StreamTcpThread *
printf("StreamTcpPacketStateNone (%p): ssn->server.isn %"PRIu32", ssn->server.next_seq %"PRIu32", ssn->server.last_ack %"PRIu32"\n",
ssn, ssn->server.isn, ssn->server.next_seq, ssn->server.last_ack);
#endif
/*Set the timestamp value for both streams, if packet has timestamp option enabled.*/
if (p->tcpvars.ts != NULL) {
ssn->client.last_ts = TCP_GET_TSVAL(p);
ssn->server.last_ts = TCP_GET_TSECR(p);
#ifdef DEBUG
printf("StreamTcpPacketStateNone (%p): ssn->server.last_ts %" PRIu32" ssn->client.last_ts %" PRIu32"\n", ssn, ssn->server.last_ts, ssn->client.last_ts);
#endif
ssn->server.flags |= STREAMTCP_FLAG_TIMESTAMP;
ssn->client.flags |= STREAMTCP_FLAG_TIMESTAMP;
ssn->flags |= STREAMTCP_FLAG_TIMESTAMP;
ssn->server.last_pkt_ts = p->ts.tv_sec;
if (ssn->server.last_ts == 0)
@ -431,14 +432,14 @@ static int StreamTcpPacketStateNone(ThreadVars *tv, Packet *p, StreamTcpThread *
ssn->client.wscale = TCP_WSCALE_MAX;
ssn->server.wscale = TCP_WSCALE_MAX;
/*Set the timestamp value for both streams, if packet has timestamp option enabled.*/
if (p->tcpvars.ts != NULL) {
ssn->client.last_ts = TCP_GET_TSVAL(p);
ssn->server.last_ts = TCP_GET_TSECR(p);
#ifdef DEBUG
printf("StreamTcpPacketStateNone (%p): ssn->server.last_ts %" PRIu32" ssn->client.last_ts %" PRIu32"\n", ssn, ssn->server.last_ts, ssn->client.last_ts);
#endif
ssn->server.flags |= STREAMTCP_FLAG_TIMESTAMP;
ssn->client.flags |= STREAMTCP_FLAG_TIMESTAMP;
ssn->flags |= STREAMTCP_FLAG_TIMESTAMP;
ssn->client.last_pkt_ts = p->ts.tv_sec;
if (ssn->server.last_ts == 0)
@ -533,7 +534,8 @@ static int StreamTcpPacketStateSynSent(ThreadVars *tv, Packet *p, StreamTcpThrea
#ifdef DEBUG
printf("StreamTcpPacketStateSynSent (%p): ssn->server.last_ts %" PRIu32" ssn->client.last_ts %" PRIu32"\n", ssn, ssn->server.last_ts, ssn->client.last_ts);
#endif
ssn->server.flags |= STREAMTCP_FLAG_TIMESTAMP;
ssn->client.flags &= ~STREAMTCP_FLAG_TIMESTAMP;
ssn->flags |= STREAMTCP_FLAG_TIMESTAMP;
ssn->server.last_pkt_ts = p->ts.tv_sec;
if (ssn->server.last_ts == 0)
ssn->server.flags |= STREAMTCP_FLAG_ZERO_TIMESTAMP;
@ -609,7 +611,11 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p, StreamTcpThrea
#endif
break;
case TH_ACK:
if ((ssn->server.flags & STREAMTCP_FLAG_TIMESTAMP) && (ssn->client.flags & STREAMTCP_FLAG_TIMESTAMP)) {
/*If the timestamp option is enabled for both the streams, then validate the received packet
timestamp value against the 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))
return -1;
}
@ -663,7 +669,7 @@ static int StreamTcpPacketStateSynRecv(ThreadVars *tv, Packet *p, StreamTcpThrea
break;
case TH_FIN:
/*FIN is handled in the same way as in TCP_ESTABLISHED case */;
if ((ssn->server.flags & STREAMTCP_FLAG_TIMESTAMP) && (ssn->client.flags & STREAMTCP_FLAG_TIMESTAMP)) {
if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
if (!ValidTimestamp(ssn, p))
return -1;
}
@ -710,7 +716,11 @@ static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p, StreamTcpT
case TH_ACK:
case TH_ACK|TH_PUSH:
if ((ssn->server.flags & STREAMTCP_FLAG_TIMESTAMP) && (ssn->client.flags & STREAMTCP_FLAG_TIMESTAMP)) {
/*If the timestamp option is enabled for both the streams, then validate the received packet
timestamp value against the 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))
return -1;
}
@ -837,7 +847,7 @@ static int StreamTcpPacketStateEstablished(ThreadVars *tv, Packet *p, StreamTcpT
case TH_FIN|TH_ACK:
case TH_FIN|TH_ACK|TH_PUSH:
if ((ssn->server.flags & STREAMTCP_FLAG_TIMESTAMP) && (ssn->client.flags & STREAMTCP_FLAG_TIMESTAMP)) {
if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
if (!ValidTimestamp(ssn, p))
return -1;
}
@ -1006,7 +1016,7 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, StreamTcpThre
switch (p->tcph->th_flags) {
case TH_ACK:
if ((ssn->server.flags & STREAMTCP_FLAG_TIMESTAMP) && (ssn->client.flags & STREAMTCP_FLAG_TIMESTAMP)) {
if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
if (!ValidTimestamp(ssn, p))
return -1;
}
@ -1052,7 +1062,7 @@ static int StreamTcpPacketStateFinWait1(ThreadVars *tv, Packet *p, StreamTcpThre
case TH_FIN|TH_ACK:
case TH_FIN|TH_ACK|TH_PUSH:
if ((ssn->server.flags & STREAMTCP_FLAG_TIMESTAMP) && (ssn->client.flags & STREAMTCP_FLAG_TIMESTAMP)) {
if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
if (!ValidTimestamp(ssn, p))
return -1;
}
@ -1151,7 +1161,7 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p, StreamTcpThre
switch (p->tcph->th_flags) {
case TH_ACK:
if ((ssn->server.flags & STREAMTCP_FLAG_TIMESTAMP) && (ssn->client.flags & STREAMTCP_FLAG_TIMESTAMP)) {
if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
if (!ValidTimestamp(ssn, p))
return -1;
}
@ -1224,7 +1234,7 @@ static int StreamTcpPacketStateFinWait2(ThreadVars *tv, Packet *p, StreamTcpThre
break;
case TH_FIN:
if ((ssn->server.flags & STREAMTCP_FLAG_TIMESTAMP) && (ssn->client.flags & STREAMTCP_FLAG_TIMESTAMP)) {
if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
if (!ValidTimestamp(ssn, p))
return -1;
}
@ -1312,7 +1322,7 @@ static int StreamTcpPacketStateClosing(ThreadVars *tv, Packet *p, StreamTcpThrea
switch(p->tcph->th_flags) {
case TH_ACK:
if ((ssn->server.flags & STREAMTCP_FLAG_TIMESTAMP) && (ssn->client.flags & STREAMTCP_FLAG_TIMESTAMP)) {
if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
if (!ValidTimestamp(ssn, p))
return -1;
}
@ -1401,7 +1411,7 @@ static int StreamTcpPacketStateCloseWait(ThreadVars *tv, Packet *p, StreamTcpThr
switch(p->tcph->th_flags) {
case TH_FIN:
if ((ssn->server.flags & STREAMTCP_FLAG_TIMESTAMP) && (ssn->client.flags & STREAMTCP_FLAG_TIMESTAMP)) {
if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
if (!ValidTimestamp(ssn, p))
return -1;
}
@ -1462,7 +1472,7 @@ static int StreamTcpPakcetStateLastAck(ThreadVars *tv, Packet *p, StreamTcpThrea
switch(p->tcph->th_flags) {
case TH_ACK:
if ((ssn->server.flags & STREAMTCP_FLAG_TIMESTAMP) && (ssn->client.flags & STREAMTCP_FLAG_TIMESTAMP)) {
if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
if (!ValidTimestamp(ssn, p))
return -1;
}
@ -1521,7 +1531,7 @@ static int StreamTcpPacketStateTimeWait(ThreadVars *tv, Packet *p, StreamTcpThre
switch(p->tcph->th_flags) {
case TH_ACK:
if ((ssn->server.flags & STREAMTCP_FLAG_TIMESTAMP) && (ssn->client.flags & STREAMTCP_FLAG_TIMESTAMP)) {
if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
if (!ValidTimestamp(ssn, p))
return -1;
}
@ -1734,7 +1744,7 @@ static int ValidReset(TcpSession *ssn, Packet *p) {
uint8_t os_policy;
if ((ssn->server.flags & STREAMTCP_FLAG_TIMESTAMP) && (ssn->client.flags & STREAMTCP_FLAG_TIMESTAMP)) {
if (ssn->flags & STREAMTCP_FLAG_TIMESTAMP) {
if (!ValidTimestamp(ssn, p))
return -1;
}
@ -1849,6 +1859,13 @@ static int ValidReset(TcpSession *ssn, Packet *p) {
return 0;
}
/**
* \brief Function to return the FLOW state depending upon the TCP session state.
*
* \param s TCP session of which the state has to be returned
* \retval The FLOW_STATE_ depends upon the TCP sesison state, default is FLOW_STATE_CLOSED
*/
int StreamTcpGetFlowState(void *s) {
TcpSession *ssn = (TcpSession *)s;
if (ssn == NULL)
@ -1874,6 +1891,15 @@ int StreamTcpGetFlowState(void *s) {
return FLOW_STATE_CLOSED;
}
/**
* \brief Function to check the validity of the received timestamp based on the target
* OS of the given stream.
*
* \param ssn TCP session to which the given packet belongs
* \param p Packet which has to be checked for its validity
* \retval If timestamp is valid, function returns 1 otherwise 0
*/
static int ValidTimestamp (TcpSession *ssn, Packet *p) {
TcpStream *sender_stream;
@ -1893,12 +1919,13 @@ static int ValidTimestamp (TcpSession *ssn, Packet *p) {
uint32_t ts = TCP_GET_TSVAL(p);
if (sender_stream->flags & STREAMTCP_FLAG_ZERO_TIMESTAMP) {
/*The 3whs used the timestamp with 0 value. */
switch (receiver_stream->os_policy) {
case OS_POLICY_LINUX:
case OS_POLICY_WINDOWS2K3:
ssn->client.flags &= ~STREAMTCP_FLAG_TIMESTAMP;
ssn->server.flags &= ~STREAMTCP_FLAG_TIMESTAMP;
/*Linux and windows 2003 does not allow the use of 0 as timestamp
in the 3whs. */
ssn->flags &= ~STREAMTCP_FLAG_TIMESTAMP;
check_ts = 0;
break;
@ -1908,7 +1935,8 @@ static int ValidTimestamp (TcpSession *ssn, Packet *p) {
sender_stream->flags &= ~STREAMTCP_FLAG_ZERO_TIMESTAMP;
if (SEQ_EQ(sender_stream->next_seq, TCP_GET_SEQ(p))) {
sender_stream->last_ts = ts;
check_ts = 0;
check_ts = 0; /*next packet will be checked for validity
and stream TS has been updated with this one.*/
}
break;
default:
@ -1917,6 +1945,7 @@ static int ValidTimestamp (TcpSession *ssn, Packet *p) {
}
if (receiver_stream->os_policy == OS_POLICY_HPUX11) {
/*HPUX11 igoners the timestamp of out of order packets*/
if (!SEQ_EQ(sender_stream->next_seq, TCP_GET_SEQ(p)))
check_ts = 0;
}
@ -1931,6 +1960,8 @@ static int ValidTimestamp (TcpSession *ssn, Packet *p) {
/*Old Linux and windows allowed packet with 0 timestamp.*/
break;
default:
/* other OS simply drop the pakcet with 0 timestamp, when 3whs
has valid timestamp*/
return 0;
}
}
@ -1960,12 +1991,16 @@ static int ValidTimestamp (TcpSession *ssn, Packet *p) {
}
if (ret == 1) {
/*Update the timestamp and last seen packet time for this stream.*/
if (SEQ_EQ(sender_stream->next_seq, TCP_GET_SEQ(p)))
sender_stream->last_ts = ts;
sender_stream->last_pkt_ts = p->ts.tv_sec;
}
if (ret == 0) {
/*if the timestamp of packet is not valid then, check if the current
stream timestamp is not so old. if so then we need to accept the packet
and update the stream->last_ts (RFC 1323)*/
if ((SEQ_EQ(sender_stream->next_seq, TCP_GET_SEQ(p)))
&& (((uint32_t) p->ts.tv_sec > (sender_stream->last_pkt_ts + PAWS_24DAYS)))) {
sender_stream->last_ts = ts;
@ -1975,8 +2010,10 @@ static int ValidTimestamp (TcpSession *ssn, Packet *p) {
}
}
} else {
/* Solaris stops using timestamps if a packet is received
without a timestamp and timestamps were used on that stream. */
if (receiver_stream->os_policy == OS_POLICY_SOLARIS)
receiver_stream->flags &= ~STREAMTCP_FLAG_TIMESTAMP;
ssn->flags &= ~STREAMTCP_FLAG_TIMESTAMP;
}
return ret;
@ -2406,8 +2443,7 @@ static int StreamTcpTest07 (void) {
u_int8_t payload[1] = {0x42};
TCPVars tcpvars;
TCPOpt ts;
uint8_t len = 10;
uint8_t data[8] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x37, 0x38, 0x39};
uint32_t data[2];
memset (&p, 0, sizeof(Packet));
memset (&f, 0, sizeof(Flow));
@ -2434,9 +2470,12 @@ static int StreamTcpTest07 (void) {
tcph.th_flags = TH_ACK|TH_PUSH;
p.tcph = &tcph;
data[0] = htonl(10);
data[1] = htonl(11);
ts.type = TCP_OPT_TS;
ts.len = len;
ts.data = data;
ts.len = 10;
ts.data = (uint8_t *)data;
tcpvars.ts = &ts;
p.tcpvars = tcpvars;
@ -2446,27 +2485,107 @@ static int StreamTcpTest07 (void) {
if (StreamTcpPacket(&tv, &p, &stt) == -1)
goto end;
printf ("the timestamp values are client %"PRIu32" server %" PRIu32 "\n", TCP_GET_TSVAL(&p), TCP_GET_TSECR(&p));
p.tcph->th_seq = htonl(11);
p.tcph->th_ack = htonl(23);
p.tcph->th_flags = TH_ACK|TH_PUSH;
p.flowflags = FLOW_PKT_TOSERVER;
data[0] = 0x11;
data[1] = 0x12;
data[2] = 0x11;
data[3] = 0x11;
p.tcpvars.ts->data = data;
data[0] = htonl(2);
p.tcpc.ts1 = 0;
p.tcpc.ts2 = 0;
p.tcpvars.ts->data = (uint8_t *)data;
if (StreamTcpPacket(&tv, &p, &stt) == -1) {
if (((TcpSession *) (p.flow->protoctx))->client.next_seq != 11) {
printf("the timestamp values are client %"PRIu32" server %" PRIu32 " seq %" PRIu32 "\n", TCP_GET_TSVAL(&p), TCP_GET_TSECR(&p), ((TcpSession *) (p.flow->protoctx))->client.next_seq);
goto end;
}
StreamTcpSessionPktFree(&p);
ret = 1;
}
end:
StreamTcpFreeConfig(TRUE);
return ret;
}
/**
* \test Test the working on PAWS. The packet will be accpeted by engine as
* the timestamp is valid and it is in window.
*
* \retval On success it returns 1 and on failure 0.
*/
static int StreamTcpTest08 (void) {
Packet p;
Flow f;
ThreadVars tv;
StreamTcpThread stt;
TCPHdr tcph;
u_int8_t payload[1] = {0x42};
TCPVars tcpvars;
TCPOpt ts;
uint32_t data[2];
memset (&p, 0, sizeof(Packet));
memset (&f, 0, sizeof(Flow));
memset(&tv, 0, sizeof (ThreadVars));
memset(&stt, 0, sizeof(StreamTcpThread));
memset(&tcph, 0, sizeof(TCPHdr));
memset(&tcpvars, 0, sizeof(TCPVars));
memset(&ts, 0, sizeof(TCPOpt));
p.flow = &f;
int ret = 0;
StreamTcpInitConfig(TRUE);
/* prevent L7 from kicking in */
StreamMsgQueueSetMinInitChunkLen(FLOW_PKT_TOSERVER, 4096);
StreamMsgQueueSetMinInitChunkLen(FLOW_PKT_TOCLIENT, 4096);
StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOSERVER, 4096);
StreamMsgQueueSetMinChunkLen(FLOW_PKT_TOCLIENT, 4096);
tcph.th_win = htons(5480);
tcph.th_seq = htonl(10);
tcph.th_ack = htonl(20);
tcph.th_flags = TH_ACK|TH_PUSH;
p.tcph = &tcph;
data[0] = htonl(10);
data[1] = htonl(11);
ts.type = TCP_OPT_TS;
ts.len = 10;
ts.data = (uint8_t *)data;
tcpvars.ts = &ts;
p.tcpvars = tcpvars;
p.payload = payload;
p.payload_len = 1;
if (StreamTcpPacket(&tv, &p, &stt) == -1)
goto end;
printf ("the timestamp values are client %"PRIu32" server %" PRIu32 "\n", TCP_GET_TSVAL(&p), TCP_GET_TSECR(&p));
p.tcph->th_seq = htonl(11);
p.tcph->th_ack = htonl(23);
p.tcph->th_flags = TH_ACK|TH_PUSH;
p.flowflags = FLOW_PKT_TOSERVER;
data[0] = htonl(12);
p.tcpc.ts1 = 0;
p.tcpc.ts2 = 0;
p.tcpvars.ts->data = (uint8_t *)data;
if (((TcpSession *)(p.flow->protoctx))->client.next_seq != 11)
if (StreamTcpPacket(&tv, &p, &stt) == -1)
goto end;
if (((TcpSession *) (p.flow->protoctx))->client.next_seq != 12) {
printf("the timestamp values are client %"PRIu32" server %" PRIu32 " seq %" PRIu32 "\n", TCP_GET_TSVAL(&p), TCP_GET_TSECR(&p), ((TcpSession *) (p.flow->protoctx))->client.next_seq);
goto end;
}
StreamTcpSessionPktFree(&p);
ret = 1;
@ -2485,7 +2604,8 @@ void StreamTcpRegisterTests (void) {
UtRegisterTest("StreamTcpTest04 -- SYN/ACK missed MidStream session", StreamTcpTest04, 1);
UtRegisterTest("StreamTcpTest05 -- 3WHS missed MidStream session", StreamTcpTest05, 1);
UtRegisterTest("StreamTcpTest06 -- FIN, RST message MidStream session", StreamTcpTest06, 1);
UtRegisterTest("StreamTcpTest07 -- PAWS", StreamTcpTest07, 1);
UtRegisterTest("StreamTcpTest07 -- PAWS invalid timestamp", StreamTcpTest07, 1);
UtRegisterTest("StreamTcpTest08 -- PAWS valid timestamp", StreamTcpTest08, 1);
/* set up the reassembly tests as well */
StreamTcpReassembleRegisterTests();
#endif /* UNITTESTS */

Loading…
Cancel
Save